aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--fs/proc/namespaces.c3
-rw-r--r--include/linux/proc_fs.h1
-rw-r--r--kernel/pid_namespace.c54
3 files changed, 58 insertions, 0 deletions
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
index b178ed733c3..85ca047e35f 100644
--- a/fs/proc/namespaces.c
+++ b/fs/proc/namespaces.c
@@ -24,6 +24,9 @@ static const struct proc_ns_operations *ns_entries[] = {
24#ifdef CONFIG_IPC_NS 24#ifdef CONFIG_IPC_NS
25 &ipcns_operations, 25 &ipcns_operations,
26#endif 26#endif
27#ifdef CONFIG_PID_NS
28 &pidns_operations,
29#endif
27}; 30};
28 31
29static const struct file_operations ns_file_operations = { 32static const struct file_operations ns_file_operations = {
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 3fd2e871ff1..acaafcd40aa 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -251,6 +251,7 @@ struct proc_ns_operations {
251extern const struct proc_ns_operations netns_operations; 251extern const struct proc_ns_operations netns_operations;
252extern const struct proc_ns_operations utsns_operations; 252extern const struct proc_ns_operations utsns_operations;
253extern const struct proc_ns_operations ipcns_operations; 253extern const struct proc_ns_operations ipcns_operations;
254extern const struct proc_ns_operations pidns_operations;
254 255
255union proc_op { 256union proc_op {
256 int (*proc_get_link)(struct dentry *, struct path *); 257 int (*proc_get_link)(struct dentry *, struct path *);
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index 0dbbc66b6ec..f78fc48c86b 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);