aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/pid_namespace.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2010-03-07 21:17:03 -0500
committerEric W. Biederman <ebiederm@xmission.com>2012-11-19 08:59:14 -0500
commit57e8391d327609cbf12d843259c968b9e5c1838f (patch)
tree53a5750360300da641fea08890bb531789ffba91 /kernel/pid_namespace.c
parent225778d68d98e7cfe2579f8d8b2d7b76f8541b8b (diff)
pidns: Add setns support
- Pid namespaces are designed to be inescapable so verify that the passed in pid namespace is a child of the currently active pid namespace or the currently active pid namespace itself. Allowing the currently active pid namespace is important so the effects of an earlier setns can be cancelled. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Diffstat (limited to 'kernel/pid_namespace.c')
-rw-r--r--kernel/pid_namespace.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index 0dbbc66b6ec6..f78fc48c86bc 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -301,6 +301,60 @@ int reboot_pid_ns(struct pid_namespace *pid_ns, int cmd)
301 return 0; 301 return 0;
302} 302}
303 303
304static void *pidns_get(struct task_struct *task)
305{
306 struct pid_namespace *ns;
307
308 rcu_read_lock();
309 ns = get_pid_ns(task_active_pid_ns(task));
310 rcu_read_unlock();
311
312 return ns;
313}
314
315static void pidns_put(void *ns)
316{
317 put_pid_ns(ns);
318}
319
320static int pidns_install(struct nsproxy *nsproxy, void *ns)
321{
322 struct pid_namespace *active = task_active_pid_ns(current);
323 struct pid_namespace *ancestor, *new = ns;
324
325 if (!ns_capable(new->user_ns, CAP_SYS_ADMIN))
326 return -EPERM;
327
328 /*
329 * Only allow entering the current active pid namespace
330 * or a child of the current active pid namespace.
331 *
332 * This is required for fork to return a usable pid value and
333 * this maintains the property that processes and their
334 * children can not escape their current pid namespace.
335 */
336 if (new->level < active->level)
337 return -EINVAL;
338
339 ancestor = new;
340 while (ancestor->level > active->level)
341 ancestor = ancestor->parent;
342 if (ancestor != active)
343 return -EINVAL;
344
345 put_pid_ns(nsproxy->pid_ns);
346 nsproxy->pid_ns = get_pid_ns(new);
347 return 0;
348}
349
350const struct proc_ns_operations pidns_operations = {
351 .name = "pid",
352 .type = CLONE_NEWPID,
353 .get = pidns_get,
354 .put = pidns_put,
355 .install = pidns_install,
356};
357
304static __init int pid_namespaces_init(void) 358static __init int pid_namespaces_init(void)
305{ 359{
306 pid_ns_cachep = KMEM_CACHE(pid_namespace, SLAB_PANIC); 360 pid_ns_cachep = KMEM_CACHE(pid_namespace, SLAB_PANIC);