Blame view

kernel/pid_namespace.c 11.3 KB
457c89965   Thomas Gleixner   treewide: Add SPD...
1
  // SPDX-License-Identifier: GPL-2.0-only
74bd59bb3   Pavel Emelyanov   namespaces: clean...
2
3
4
5
6
7
8
9
10
11
12
13
  /*
   * Pid namespaces
   *
   * Authors:
   *    (C) 2007 Pavel Emelyanov <xemul@openvz.org>, OpenVZ, SWsoft Inc.
   *    (C) 2007 Sukadev Bhattiprolu <sukadev@us.ibm.com>, IBM
   *     Many thanks to Oleg Nesterov for comments and help
   *
   */
  
  #include <linux/pid.h>
  #include <linux/pid_namespace.h>
49f4d8b93   Eric W. Biederman   pidns: Capture th...
14
  #include <linux/user_namespace.h>
74bd59bb3   Pavel Emelyanov   namespaces: clean...
15
  #include <linux/syscalls.h>
5b825c3af   Ingo Molnar   sched/headers: Pr...
16
  #include <linux/cred.h>
74bd59bb3   Pavel Emelyanov   namespaces: clean...
17
  #include <linux/err.h>
0b6b030fc   Pavel Emelyanov   bsdacct: switch f...
18
  #include <linux/acct.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
19
  #include <linux/slab.h>
0bb80f240   David Howells   proc: Split the n...
20
  #include <linux/proc_ns.h>
cf3f89214   Daniel Lezcano   pidns: add reboot...
21
  #include <linux/reboot.h>
523a6a945   Eric W. Biederman   pidns: Export fre...
22
  #include <linux/export.h>
299300258   Ingo Molnar   sched/headers: Pr...
23
  #include <linux/sched/task.h>
f361bf4a6   Ingo Molnar   sched/headers: Pr...
24
  #include <linux/sched/signal.h>
95846ecf9   Gargi Sharma   pid: replace pid ...
25
  #include <linux/idr.h>
74bd59bb3   Pavel Emelyanov   namespaces: clean...
26

74bd59bb3   Pavel Emelyanov   namespaces: clean...
27
28
  static DEFINE_MUTEX(pid_caches_mutex);
  static struct kmem_cache *pid_ns_cachep;
dd206bec9   Alexey Dobriyan   pidns: simpler al...
29
30
  /* Write once array, filled from the beginning. */
  static struct kmem_cache *pid_cache[MAX_PID_NS_LEVEL];
74bd59bb3   Pavel Emelyanov   namespaces: clean...
31
32
33
  
  /*
   * creates the kmem cache to allocate pids from.
dd206bec9   Alexey Dobriyan   pidns: simpler al...
34
   * @level: pid namespace level
74bd59bb3   Pavel Emelyanov   namespaces: clean...
35
   */
dd206bec9   Alexey Dobriyan   pidns: simpler al...
36
  static struct kmem_cache *create_pid_cachep(unsigned int level)
74bd59bb3   Pavel Emelyanov   namespaces: clean...
37
  {
dd206bec9   Alexey Dobriyan   pidns: simpler al...
38
39
40
41
42
43
44
45
46
47
48
49
  	/* Level 0 is init_pid_ns.pid_cachep */
  	struct kmem_cache **pkc = &pid_cache[level - 1];
  	struct kmem_cache *kc;
  	char name[4 + 10 + 1];
  	unsigned int len;
  
  	kc = READ_ONCE(*pkc);
  	if (kc)
  		return kc;
  
  	snprintf(name, sizeof(name), "pid_%u", level + 1);
  	len = sizeof(struct pid) + level * sizeof(struct upid);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
50
  	mutex_lock(&pid_caches_mutex);
dd206bec9   Alexey Dobriyan   pidns: simpler al...
51
52
53
  	/* Name collision forces to do allocation under mutex. */
  	if (!*pkc)
  		*pkc = kmem_cache_create(name, len, 0, SLAB_HWCACHE_ALIGN, 0);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
54
  	mutex_unlock(&pid_caches_mutex);
dd206bec9   Alexey Dobriyan   pidns: simpler al...
55
56
  	/* current can fail, but someone else can succeed. */
  	return READ_ONCE(*pkc);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
57
  }
f333c700c   Eric W. Biederman   pidns: Add a limi...
58
59
60
61
62
63
64
65
66
  static struct ucounts *inc_pid_namespaces(struct user_namespace *ns)
  {
  	return inc_ucount(ns, current_euid(), UCOUNT_PID_NAMESPACES);
  }
  
  static void dec_pid_namespaces(struct ucounts *ucounts)
  {
  	dec_ucount(ucounts, UCOUNT_PID_NAMESPACES);
  }
49f4d8b93   Eric W. Biederman   pidns: Capture th...
67
68
  static struct pid_namespace *create_pid_namespace(struct user_namespace *user_ns,
  	struct pid_namespace *parent_pid_ns)
74bd59bb3   Pavel Emelyanov   namespaces: clean...
69
70
  {
  	struct pid_namespace *ns;
ed469a63c   Alexey Dobriyan   pidns: make creat...
71
  	unsigned int level = parent_pid_ns->level + 1;
f333c700c   Eric W. Biederman   pidns: Add a limi...
72
  	struct ucounts *ucounts;
f23025057   Andrew Vagin   pidns: limit the ...
73
  	int err;
a2b426267   Eric W. Biederman   userns,pidns: Ver...
74
75
76
  	err = -EINVAL;
  	if (!in_userns(parent_pid_ns->user_ns, user_ns))
  		goto out;
df75e7748   Eric W. Biederman   userns: When the ...
77
  	err = -ENOSPC;
f333c700c   Eric W. Biederman   pidns: Add a limi...
78
79
80
81
  	if (level > MAX_PID_NS_LEVEL)
  		goto out;
  	ucounts = inc_pid_namespaces(user_ns);
  	if (!ucounts)
f23025057   Andrew Vagin   pidns: limit the ...
82
  		goto out;
74bd59bb3   Pavel Emelyanov   namespaces: clean...
83

f23025057   Andrew Vagin   pidns: limit the ...
84
  	err = -ENOMEM;
84406c153   Pavel Emelyanov   pidns: use kzallo...
85
  	ns = kmem_cache_zalloc(pid_ns_cachep, GFP_KERNEL);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
86
  	if (ns == NULL)
f333c700c   Eric W. Biederman   pidns: Add a limi...
87
  		goto out_dec;
74bd59bb3   Pavel Emelyanov   namespaces: clean...
88

95846ecf9   Gargi Sharma   pid: replace pid ...
89
  	idr_init(&ns->idr);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
90

dd206bec9   Alexey Dobriyan   pidns: simpler al...
91
  	ns->pid_cachep = create_pid_cachep(level);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
92
  	if (ns->pid_cachep == NULL)
95846ecf9   Gargi Sharma   pid: replace pid ...
93
  		goto out_free_idr;
74bd59bb3   Pavel Emelyanov   namespaces: clean...
94

6344c433a   Al Viro   new helpers: ns_a...
95
  	err = ns_alloc_inum(&ns->ns);
98f842e67   Eric W. Biederman   proc: Usable inod...
96
  	if (err)
95846ecf9   Gargi Sharma   pid: replace pid ...
97
  		goto out_free_idr;
33c429405   Al Viro   copy address of p...
98
  	ns->ns.ops = &pidns_operations;
98f842e67   Eric W. Biederman   proc: Usable inod...
99

74bd59bb3   Pavel Emelyanov   namespaces: clean...
100
  	kref_init(&ns->kref);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
101
  	ns->level = level;
ed469a63c   Alexey Dobriyan   pidns: make creat...
102
  	ns->parent = get_pid_ns(parent_pid_ns);
49f4d8b93   Eric W. Biederman   pidns: Capture th...
103
  	ns->user_ns = get_user_ns(user_ns);
f333c700c   Eric W. Biederman   pidns: Add a limi...
104
  	ns->ucounts = ucounts;
e8cfbc245   Gargi Sharma   pid: remove pidhash
105
  	ns->pid_allocated = PIDNS_ADDING;
74bd59bb3   Pavel Emelyanov   namespaces: clean...
106

74bd59bb3   Pavel Emelyanov   namespaces: clean...
107
  	return ns;
95846ecf9   Gargi Sharma   pid: replace pid ...
108
109
  out_free_idr:
  	idr_destroy(&ns->idr);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
110
  	kmem_cache_free(pid_ns_cachep, ns);
f333c700c   Eric W. Biederman   pidns: Add a limi...
111
112
  out_dec:
  	dec_pid_namespaces(ucounts);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
113
  out:
4308eebbe   Eric W. Biederman   pidns: call pid_n...
114
  	return ERR_PTR(err);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
115
  }
1adfcb03e   Al Viro   pid_namespace: ma...
116
117
  static void delayed_free_pidns(struct rcu_head *p)
  {
add7c65ca   Andrei Vagin   pid: fix lockdep ...
118
119
120
121
122
123
  	struct pid_namespace *ns = container_of(p, struct pid_namespace, rcu);
  
  	dec_pid_namespaces(ns->ucounts);
  	put_user_ns(ns->user_ns);
  
  	kmem_cache_free(pid_ns_cachep, ns);
1adfcb03e   Al Viro   pid_namespace: ma...
124
  }
74bd59bb3   Pavel Emelyanov   namespaces: clean...
125
126
  static void destroy_pid_namespace(struct pid_namespace *ns)
  {
6344c433a   Al Viro   new helpers: ns_a...
127
  	ns_free_inum(&ns->ns);
95846ecf9   Gargi Sharma   pid: replace pid ...
128
129
  
  	idr_destroy(&ns->idr);
1adfcb03e   Al Viro   pid_namespace: ma...
130
  	call_rcu(&ns->rcu, delayed_free_pidns);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
131
  }
49f4d8b93   Eric W. Biederman   pidns: Capture th...
132
133
  struct pid_namespace *copy_pid_ns(unsigned long flags,
  	struct user_namespace *user_ns, struct pid_namespace *old_ns)
74bd59bb3   Pavel Emelyanov   namespaces: clean...
134
  {
74bd59bb3   Pavel Emelyanov   namespaces: clean...
135
  	if (!(flags & CLONE_NEWPID))
dca4a9796   Alexey Dobriyan   pidns: rewrite co...
136
  		return get_pid_ns(old_ns);
225778d68   Eric W. Biederman   pidns: Deny stran...
137
138
  	if (task_active_pid_ns(current) != old_ns)
  		return ERR_PTR(-EINVAL);
49f4d8b93   Eric W. Biederman   pidns: Capture th...
139
  	return create_pid_namespace(user_ns, old_ns);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
140
  }
bbc2e3ef8   Cyrill Gorcunov   pidns: remove rec...
141
  static void free_pid_ns(struct kref *kref)
74bd59bb3   Pavel Emelyanov   namespaces: clean...
142
  {
bbc2e3ef8   Cyrill Gorcunov   pidns: remove rec...
143
  	struct pid_namespace *ns;
74bd59bb3   Pavel Emelyanov   namespaces: clean...
144
145
  
  	ns = container_of(kref, struct pid_namespace, kref);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
146
  	destroy_pid_namespace(ns);
bbc2e3ef8   Cyrill Gorcunov   pidns: remove rec...
147
  }
74bd59bb3   Pavel Emelyanov   namespaces: clean...
148

bbc2e3ef8   Cyrill Gorcunov   pidns: remove rec...
149
150
151
152
153
154
155
156
157
158
  void put_pid_ns(struct pid_namespace *ns)
  {
  	struct pid_namespace *parent;
  
  	while (ns != &init_pid_ns) {
  		parent = ns->parent;
  		if (!kref_put(&ns->kref, free_pid_ns))
  			break;
  		ns = parent;
  	}
74bd59bb3   Pavel Emelyanov   namespaces: clean...
159
  }
bbc2e3ef8   Cyrill Gorcunov   pidns: remove rec...
160
  EXPORT_SYMBOL_GPL(put_pid_ns);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
161
162
163
164
165
  
  void zap_pid_ns_processes(struct pid_namespace *pid_ns)
  {
  	int nr;
  	int rc;
00c10bc13   Eric W. Biederman   pidns: make kille...
166
  	struct task_struct *task, *me = current;
751c644b9   Eric W. Biederman   pid: Handle the e...
167
  	int init_pids = thread_group_leader(me) ? 1 : 2;
95846ecf9   Gargi Sharma   pid: replace pid ...
168
  	struct pid *pid;
00c10bc13   Eric W. Biederman   pidns: make kille...
169

c876ad768   Eric W. Biederman   pidns: Stop pid a...
170
171
  	/* Don't allow any more processes into the pid namespace */
  	disable_pid_allocation(pid_ns);
a53b83154   Oleg Nesterov   exit: pidns: fix/...
172
173
174
175
176
  	/*
  	 * Ignore SIGCHLD causing any terminated children to autoreap.
  	 * This speeds up the namespace shutdown, plus see the comment
  	 * below.
  	 */
00c10bc13   Eric W. Biederman   pidns: make kille...
177
178
179
  	spin_lock_irq(&me->sighand->siglock);
  	me->sighand->action[SIGCHLD - 1].sa.sa_handler = SIG_IGN;
  	spin_unlock_irq(&me->sighand->siglock);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
180
181
182
183
184
185
186
187
188
189
190
191
192
193
  
  	/*
  	 * The last thread in the cgroup-init thread group is terminating.
  	 * Find remaining pid_ts in the namespace, signal and wait for them
  	 * to exit.
  	 *
  	 * Note:  This signals each threads in the namespace - even those that
  	 * 	  belong to the same thread group, To avoid this, we would have
  	 * 	  to walk the entire tasklist looking a processes in this
  	 * 	  namespace, but that could be unnecessarily expensive if the
  	 * 	  pid namespace has just a few processes. Or we need to
  	 * 	  maintain a tasklist for each pid namespace.
  	 *
  	 */
95846ecf9   Gargi Sharma   pid: replace pid ...
194
  	rcu_read_lock();
74bd59bb3   Pavel Emelyanov   namespaces: clean...
195
  	read_lock(&tasklist_lock);
95846ecf9   Gargi Sharma   pid: replace pid ...
196
197
198
  	nr = 2;
  	idr_for_each_entry_continue(&pid_ns->idr, pid, nr) {
  		task = pid_task(pid, PIDTYPE_PID);
a02d6fd64   Oleg Nesterov   signal: zap_pid_n...
199
  		if (task && !__fatal_signal_pending(task))
82058d668   Eric W. Biederman   signal: Use group...
200
  			group_send_sig_info(SIGKILL, SEND_SIG_PRIV, task, PIDTYPE_MAX);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
201
202
  	}
  	read_unlock(&tasklist_lock);
95846ecf9   Gargi Sharma   pid: replace pid ...
203
  	rcu_read_unlock();
74bd59bb3   Pavel Emelyanov   namespaces: clean...
204

a53b83154   Oleg Nesterov   exit: pidns: fix/...
205
206
  	/*
  	 * Reap the EXIT_ZOMBIE children we had before we ignored SIGCHLD.
d300b6108   Dominik Brodowski   kernel: use kerne...
207
  	 * kernel_wait4() will also block until our children traced from the
a53b83154   Oleg Nesterov   exit: pidns: fix/...
208
209
  	 * parent namespace are detached and become EXIT_DEAD.
  	 */
74bd59bb3   Pavel Emelyanov   namespaces: clean...
210
211
  	do {
  		clear_thread_flag(TIF_SIGPENDING);
d300b6108   Dominik Brodowski   kernel: use kerne...
212
  		rc = kernel_wait4(-1, NULL, __WALL, NULL);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
213
  	} while (rc != -ECHILD);
6347e9009   Eric W. Biederman   pidns: guarantee ...
214
  	/*
af9fe6d60   Eric W. Biederman   pid: Improve the ...
215
216
217
  	 * kernel_wait4() misses EXIT_DEAD children, and EXIT_ZOMBIE
  	 * process whose parents processes are outside of the pid
  	 * namespace.  Such processes are created with setns()+fork().
a53b83154   Oleg Nesterov   exit: pidns: fix/...
218
  	 *
af9fe6d60   Eric W. Biederman   pid: Improve the ...
219
220
221
222
  	 * If those EXIT_ZOMBIE processes are not reaped by their
  	 * parents before their parents exit, they will be reparented
  	 * to pid_ns->child_reaper.  Thus pidns->child_reaper needs to
  	 * stay valid until they all go away.
a53b83154   Oleg Nesterov   exit: pidns: fix/...
223
  	 *
7b7b8a2c9   Randy Dunlap   kernel/: fix repe...
224
  	 * The code relies on the pid_ns->child_reaper ignoring
af9fe6d60   Eric W. Biederman   pid: Improve the ...
225
226
227
228
229
230
231
232
233
234
235
  	 * SIGCHILD to cause those EXIT_ZOMBIE processes to be
  	 * autoreaped if reparented.
  	 *
  	 * Semantically it is also desirable to wait for EXIT_ZOMBIE
  	 * processes before allowing the child_reaper to be reaped, as
  	 * that gives the invariant that when the init process of a
  	 * pid namespace is reaped all of the processes in the pid
  	 * namespace are gone.
  	 *
  	 * Once all of the other tasks are gone from the pid_namespace
  	 * free_pid() will awaken this task.
6347e9009   Eric W. Biederman   pidns: guarantee ...
236
237
  	 */
  	for (;;) {
b9a985db9   Eric W. Biederman   pid_ns: Sleep in ...
238
  		set_current_state(TASK_INTERRUPTIBLE);
e8cfbc245   Gargi Sharma   pid: remove pidhash
239
  		if (pid_ns->pid_allocated == init_pids)
6347e9009   Eric W. Biederman   pidns: guarantee ...
240
241
242
  			break;
  		schedule();
  	}
af4b8a83a   Eric W. Biederman   pidns: Wait in za...
243
  	__set_current_state(TASK_RUNNING);
6347e9009   Eric W. Biederman   pidns: guarantee ...
244

cf3f89214   Daniel Lezcano   pidns: add reboot...
245
246
  	if (pid_ns->reboot)
  		current->signal->group_exit_code = pid_ns->reboot;
0b6b030fc   Pavel Emelyanov   bsdacct: switch f...
247
  	acct_exit_ns(pid_ns);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
248
249
  	return;
  }
98ed57eef   Cyrill Gorcunov   sysctl: make kern...
250
  #ifdef CONFIG_CHECKPOINT_RESTORE
b8f566b04   Pavel Emelyanov   sysctl: add the k...
251
  static int pid_ns_ctl_handler(struct ctl_table *table, int write,
32927393d   Christoph Hellwig   sysctl: pass kern...
252
  		void *buffer, size_t *lenp, loff_t *ppos)
b8f566b04   Pavel Emelyanov   sysctl: add the k...
253
  {
49f4d8b93   Eric W. Biederman   pidns: Capture th...
254
  	struct pid_namespace *pid_ns = task_active_pid_ns(current);
b8f566b04   Pavel Emelyanov   sysctl: add the k...
255
  	struct ctl_table tmp = *table;
95846ecf9   Gargi Sharma   pid: replace pid ...
256
  	int ret, next;
b8f566b04   Pavel Emelyanov   sysctl: add the k...
257

b9a3db92e   Adrian Reber   pid_namespace: us...
258
  	if (write && !checkpoint_restore_ns_capable(pid_ns->user_ns))
b8f566b04   Pavel Emelyanov   sysctl: add the k...
259
260
261
262
263
264
265
  		return -EPERM;
  
  	/*
  	 * Writing directly to ns' last_pid field is OK, since this field
  	 * is volatile in a living namespace anyway and a code writing to
  	 * it should synchronize its usage with external means.
  	 */
95846ecf9   Gargi Sharma   pid: replace pid ...
266
267
268
269
270
271
272
273
  	next = idr_get_cursor(&pid_ns->idr) - 1;
  
  	tmp.data = &next;
  	ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
  	if (!ret && write)
  		idr_set_cursor(&pid_ns->idr, next + 1);
  
  	return ret;
b8f566b04   Pavel Emelyanov   sysctl: add the k...
274
  }
579035dc5   Andrew Vagin   pid-namespace: li...
275
  extern int pid_max;
b8f566b04   Pavel Emelyanov   sysctl: add the k...
276
277
278
279
280
281
  static struct ctl_table pid_ns_ctl_table[] = {
  	{
  		.procname = "ns_last_pid",
  		.maxlen = sizeof(int),
  		.mode = 0666, /* permissions are checked in the handler */
  		.proc_handler = pid_ns_ctl_handler,
eec4844fa   Matteo Croce   proc/sysctl: add ...
282
  		.extra1 = SYSCTL_ZERO,
579035dc5   Andrew Vagin   pid-namespace: li...
283
  		.extra2 = &pid_max,
b8f566b04   Pavel Emelyanov   sysctl: add the k...
284
285
286
  	},
  	{ }
  };
b8f566b04   Pavel Emelyanov   sysctl: add the k...
287
  static struct ctl_path kern_path[] = { { .procname = "kernel", }, { } };
98ed57eef   Cyrill Gorcunov   sysctl: make kern...
288
  #endif	/* CONFIG_CHECKPOINT_RESTORE */
b8f566b04   Pavel Emelyanov   sysctl: add the k...
289

cf3f89214   Daniel Lezcano   pidns: add reboot...
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
  int reboot_pid_ns(struct pid_namespace *pid_ns, int cmd)
  {
  	if (pid_ns == &init_pid_ns)
  		return 0;
  
  	switch (cmd) {
  	case LINUX_REBOOT_CMD_RESTART2:
  	case LINUX_REBOOT_CMD_RESTART:
  		pid_ns->reboot = SIGHUP;
  		break;
  
  	case LINUX_REBOOT_CMD_POWER_OFF:
  	case LINUX_REBOOT_CMD_HALT:
  		pid_ns->reboot = SIGINT;
  		break;
  	default:
  		return -EINVAL;
  	}
  
  	read_lock(&tasklist_lock);
f9070dc94   Eric W. Biederman   signal/pid_namesp...
310
  	send_sig(SIGKILL, pid_ns->child_reaper, 1);
cf3f89214   Daniel Lezcano   pidns: add reboot...
311
312
313
314
315
316
317
  	read_unlock(&tasklist_lock);
  
  	do_exit(0);
  
  	/* Not reached */
  	return 0;
  }
3c0411846   Al Viro   switch the rest o...
318
319
320
321
  static inline struct pid_namespace *to_pid_ns(struct ns_common *ns)
  {
  	return container_of(ns, struct pid_namespace, ns);
  }
64964528b   Al Viro   make proc_ns_oper...
322
  static struct ns_common *pidns_get(struct task_struct *task)
57e8391d3   Eric W. Biederman   pidns: Add setns ...
323
324
325
326
  {
  	struct pid_namespace *ns;
  
  	rcu_read_lock();
d23082257   Oleg Nesterov   pid_namespace: pi...
327
328
329
  	ns = task_active_pid_ns(task);
  	if (ns)
  		get_pid_ns(ns);
57e8391d3   Eric W. Biederman   pidns: Add setns ...
330
  	rcu_read_unlock();
3c0411846   Al Viro   switch the rest o...
331
  	return ns ? &ns->ns : NULL;
57e8391d3   Eric W. Biederman   pidns: Add setns ...
332
  }
eaa0d190b   Kirill Tkhai   pidns: expose tas...
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
  static struct ns_common *pidns_for_children_get(struct task_struct *task)
  {
  	struct pid_namespace *ns = NULL;
  
  	task_lock(task);
  	if (task->nsproxy) {
  		ns = task->nsproxy->pid_ns_for_children;
  		get_pid_ns(ns);
  	}
  	task_unlock(task);
  
  	if (ns) {
  		read_lock(&tasklist_lock);
  		if (!ns->child_reaper) {
  			put_pid_ns(ns);
  			ns = NULL;
  		}
  		read_unlock(&tasklist_lock);
  	}
  
  	return ns ? &ns->ns : NULL;
  }
64964528b   Al Viro   make proc_ns_oper...
355
  static void pidns_put(struct ns_common *ns)
57e8391d3   Eric W. Biederman   pidns: Add setns ...
356
  {
3c0411846   Al Viro   switch the rest o...
357
  	put_pid_ns(to_pid_ns(ns));
57e8391d3   Eric W. Biederman   pidns: Add setns ...
358
  }
f2a8d52e0   Christian Brauner   nsproxy: add stru...
359
  static int pidns_install(struct nsset *nsset, struct ns_common *ns)
57e8391d3   Eric W. Biederman   pidns: Add setns ...
360
  {
f2a8d52e0   Christian Brauner   nsproxy: add stru...
361
  	struct nsproxy *nsproxy = nsset->nsproxy;
57e8391d3   Eric W. Biederman   pidns: Add setns ...
362
  	struct pid_namespace *active = task_active_pid_ns(current);
3c0411846   Al Viro   switch the rest o...
363
  	struct pid_namespace *ancestor, *new = to_pid_ns(ns);
57e8391d3   Eric W. Biederman   pidns: Add setns ...
364

5e4a08476   Eric W. Biederman   userns: Require C...
365
  	if (!ns_capable(new->user_ns, CAP_SYS_ADMIN) ||
f2a8d52e0   Christian Brauner   nsproxy: add stru...
366
  	    !ns_capable(nsset->cred->user_ns, CAP_SYS_ADMIN))
57e8391d3   Eric W. Biederman   pidns: Add setns ...
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
  		return -EPERM;
  
  	/*
  	 * Only allow entering the current active pid namespace
  	 * or a child of the current active pid namespace.
  	 *
  	 * This is required for fork to return a usable pid value and
  	 * this maintains the property that processes and their
  	 * children can not escape their current pid namespace.
  	 */
  	if (new->level < active->level)
  		return -EINVAL;
  
  	ancestor = new;
  	while (ancestor->level > active->level)
  		ancestor = ancestor->parent;
  	if (ancestor != active)
  		return -EINVAL;
c2b1df2eb   Andy Lutomirski   Rename nsproxy.pi...
385
386
  	put_pid_ns(nsproxy->pid_ns_for_children);
  	nsproxy->pid_ns_for_children = get_pid_ns(new);
57e8391d3   Eric W. Biederman   pidns: Add setns ...
387
388
  	return 0;
  }
a7306ed8d   Andrey Vagin   nsfs: add ioctl t...
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
  static struct ns_common *pidns_get_parent(struct ns_common *ns)
  {
  	struct pid_namespace *active = task_active_pid_ns(current);
  	struct pid_namespace *pid_ns, *p;
  
  	/* See if the parent is in the current namespace */
  	pid_ns = p = to_pid_ns(ns)->parent;
  	for (;;) {
  		if (!p)
  			return ERR_PTR(-EPERM);
  		if (p == active)
  			break;
  		p = p->parent;
  	}
  
  	return &get_pid_ns(pid_ns)->ns;
  }
bcac25a58   Andrey Vagin   kernel: add a hel...
406
407
408
409
  static struct user_namespace *pidns_owner(struct ns_common *ns)
  {
  	return to_pid_ns(ns)->user_ns;
  }
57e8391d3   Eric W. Biederman   pidns: Add setns ...
410
411
412
413
414
415
  const struct proc_ns_operations pidns_operations = {
  	.name		= "pid",
  	.type		= CLONE_NEWPID,
  	.get		= pidns_get,
  	.put		= pidns_put,
  	.install	= pidns_install,
bcac25a58   Andrey Vagin   kernel: add a hel...
416
  	.owner		= pidns_owner,
a7306ed8d   Andrey Vagin   nsfs: add ioctl t...
417
  	.get_parent	= pidns_get_parent,
57e8391d3   Eric W. Biederman   pidns: Add setns ...
418
  };
eaa0d190b   Kirill Tkhai   pidns: expose tas...
419
420
421
422
423
424
425
426
427
428
  const struct proc_ns_operations pidns_for_children_operations = {
  	.name		= "pid_for_children",
  	.real_ns_name	= "pid",
  	.type		= CLONE_NEWPID,
  	.get		= pidns_for_children_get,
  	.put		= pidns_put,
  	.install	= pidns_install,
  	.owner		= pidns_owner,
  	.get_parent	= pidns_get_parent,
  };
74bd59bb3   Pavel Emelyanov   namespaces: clean...
429
430
431
  static __init int pid_namespaces_init(void)
  {
  	pid_ns_cachep = KMEM_CACHE(pid_namespace, SLAB_PANIC);
98ed57eef   Cyrill Gorcunov   sysctl: make kern...
432
433
  
  #ifdef CONFIG_CHECKPOINT_RESTORE
b8f566b04   Pavel Emelyanov   sysctl: add the k...
434
  	register_sysctl_paths(kern_path, pid_ns_ctl_table);
98ed57eef   Cyrill Gorcunov   sysctl: make kern...
435
  #endif
74bd59bb3   Pavel Emelyanov   namespaces: clean...
436
437
438
439
  	return 0;
  }
  
  __initcall(pid_namespaces_init);