aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/namespace.c22
-rw-r--r--fs/proc/base.c5
-rw-r--r--include/linux/init_task.h1
-rw-r--r--include/linux/namespace.h6
-rw-r--r--include/linux/nsproxy.h3
-rw-r--r--include/linux/sched.h4
-rw-r--r--kernel/exit.c4
-rw-r--r--kernel/fork.c17
-rw-r--r--kernel/nsproxy.c32
9 files changed, 55 insertions, 39 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index 66d921e14fee..55442a6cf221 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -133,7 +133,7 @@ struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry)
133 133
134static inline int check_mnt(struct vfsmount *mnt) 134static inline int check_mnt(struct vfsmount *mnt)
135{ 135{
136 return mnt->mnt_namespace == current->namespace; 136 return mnt->mnt_namespace == current->nsproxy->namespace;
137} 137}
138 138
139static void touch_namespace(struct namespace *ns) 139static void touch_namespace(struct namespace *ns)
@@ -830,7 +830,7 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt,
830 if (parent_nd) { 830 if (parent_nd) {
831 detach_mnt(source_mnt, parent_nd); 831 detach_mnt(source_mnt, parent_nd);
832 attach_mnt(source_mnt, nd); 832 attach_mnt(source_mnt, nd);
833 touch_namespace(current->namespace); 833 touch_namespace(current->nsproxy->namespace);
834 } else { 834 } else {
835 mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt); 835 mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt);
836 commit_tree(source_mnt); 836 commit_tree(source_mnt);
@@ -1441,7 +1441,7 @@ dput_out:
1441 */ 1441 */
1442struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs) 1442struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs)
1443{ 1443{
1444 struct namespace *namespace = tsk->namespace; 1444 struct namespace *namespace = tsk->nsproxy->namespace;
1445 struct namespace *new_ns; 1445 struct namespace *new_ns;
1446 struct vfsmount *rootmnt = NULL, *pwdmnt = NULL, *altrootmnt = NULL; 1446 struct vfsmount *rootmnt = NULL, *pwdmnt = NULL, *altrootmnt = NULL;
1447 struct vfsmount *p, *q; 1447 struct vfsmount *p, *q;
@@ -1508,7 +1508,7 @@ struct namespace *dup_namespace(struct task_struct *tsk, struct fs_struct *fs)
1508 1508
1509int copy_namespace(int flags, struct task_struct *tsk) 1509int copy_namespace(int flags, struct task_struct *tsk)
1510{ 1510{
1511 struct namespace *namespace = tsk->namespace; 1511 struct namespace *namespace = tsk->nsproxy->namespace;
1512 struct namespace *new_ns; 1512 struct namespace *new_ns;
1513 int err = 0; 1513 int err = 0;
1514 1514
@@ -1531,7 +1531,7 @@ int copy_namespace(int flags, struct task_struct *tsk)
1531 goto out; 1531 goto out;
1532 } 1532 }
1533 1533
1534 tsk->namespace = new_ns; 1534 tsk->nsproxy->namespace = new_ns;
1535 1535
1536out: 1536out:
1537 put_namespace(namespace); 1537 put_namespace(namespace);
@@ -1754,7 +1754,7 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
1754 detach_mnt(user_nd.mnt, &root_parent); 1754 detach_mnt(user_nd.mnt, &root_parent);
1755 attach_mnt(user_nd.mnt, &old_nd); /* mount old root on put_old */ 1755 attach_mnt(user_nd.mnt, &old_nd); /* mount old root on put_old */
1756 attach_mnt(new_nd.mnt, &root_parent); /* mount new_root on / */ 1756 attach_mnt(new_nd.mnt, &root_parent); /* mount new_root on / */
1757 touch_namespace(current->namespace); 1757 touch_namespace(current->nsproxy->namespace);
1758 spin_unlock(&vfsmount_lock); 1758 spin_unlock(&vfsmount_lock);
1759 chroot_fs_refs(&user_nd, &new_nd); 1759 chroot_fs_refs(&user_nd, &new_nd);
1760 security_sb_post_pivotroot(&user_nd, &new_nd); 1760 security_sb_post_pivotroot(&user_nd, &new_nd);
@@ -1780,7 +1780,6 @@ static void __init init_mount_tree(void)
1780{ 1780{
1781 struct vfsmount *mnt; 1781 struct vfsmount *mnt;
1782 struct namespace *namespace; 1782 struct namespace *namespace;
1783 struct task_struct *g, *p;
1784 1783
1785 mnt = do_kern_mount("rootfs", 0, "rootfs", NULL); 1784 mnt = do_kern_mount("rootfs", 0, "rootfs", NULL);
1786 if (IS_ERR(mnt)) 1785 if (IS_ERR(mnt))
@@ -1796,13 +1795,8 @@ static void __init init_mount_tree(void)
1796 namespace->root = mnt; 1795 namespace->root = mnt;
1797 mnt->mnt_namespace = namespace; 1796 mnt->mnt_namespace = namespace;
1798 1797
1799 init_task.namespace = namespace; 1798 init_task.nsproxy->namespace = namespace;
1800 read_lock(&tasklist_lock); 1799 get_namespace(namespace);
1801 do_each_thread(g, p) {
1802 get_namespace(namespace);
1803 p->namespace = namespace;
1804 } while_each_thread(g, p);
1805 read_unlock(&tasklist_lock);
1806 1800
1807 set_fs_pwd(current->fs, namespace->root, namespace->root->mnt_root); 1801 set_fs_pwd(current->fs, namespace->root, namespace->root->mnt_root);
1808 set_fs_root(current->fs, namespace->root, namespace->root->mnt_root); 1802 set_fs_root(current->fs, namespace->root, namespace->root->mnt_root);
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 9c6a809f92b6..6d00ccc48c1c 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -71,6 +71,7 @@
71#include <linux/cpuset.h> 71#include <linux/cpuset.h>
72#include <linux/audit.h> 72#include <linux/audit.h>
73#include <linux/poll.h> 73#include <linux/poll.h>
74#include <linux/nsproxy.h>
74#include "internal.h" 75#include "internal.h"
75 76
76/* NOTE: 77/* NOTE:
@@ -473,7 +474,7 @@ static int mounts_open(struct inode *inode, struct file *file)
473 474
474 if (task) { 475 if (task) {
475 task_lock(task); 476 task_lock(task);
476 namespace = task->namespace; 477 namespace = task->nsproxy->namespace;
477 if (namespace) 478 if (namespace)
478 get_namespace(namespace); 479 get_namespace(namespace);
479 task_unlock(task); 480 task_unlock(task);
@@ -544,7 +545,7 @@ static int mountstats_open(struct inode *inode, struct file *file)
544 545
545 if (task) { 546 if (task) {
546 task_lock(task); 547 task_lock(task);
547 namespace = task->namespace; 548 namespace = task->nsproxy->namespace;
548 if (namespace) 549 if (namespace)
549 get_namespace(namespace); 550 get_namespace(namespace);
550 task_unlock(task); 551 task_unlock(task);
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 8f8bb422a5c7..4865348ca8bd 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -72,6 +72,7 @@ extern struct nsproxy init_nsproxy;
72#define INIT_NSPROXY(nsproxy) { \ 72#define INIT_NSPROXY(nsproxy) { \
73 .count = ATOMIC_INIT(1), \ 73 .count = ATOMIC_INIT(1), \
74 .nslock = SPIN_LOCK_UNLOCKED, \ 74 .nslock = SPIN_LOCK_UNLOCKED, \
75 .namespace = NULL, \
75} 76}
76 77
77#define INIT_SIGHAND(sighand) { \ 78#define INIT_SIGHAND(sighand) { \
diff --git a/include/linux/namespace.h b/include/linux/namespace.h
index 3abc8e3b4879..d137009f0b2b 100644
--- a/include/linux/namespace.h
+++ b/include/linux/namespace.h
@@ -4,6 +4,7 @@
4 4
5#include <linux/mount.h> 5#include <linux/mount.h>
6#include <linux/sched.h> 6#include <linux/sched.h>
7#include <linux/nsproxy.h>
7 8
8struct namespace { 9struct namespace {
9 atomic_t count; 10 atomic_t count;
@@ -26,11 +27,8 @@ static inline void put_namespace(struct namespace *namespace)
26 27
27static inline void exit_namespace(struct task_struct *p) 28static inline void exit_namespace(struct task_struct *p)
28{ 29{
29 struct namespace *namespace = p->namespace; 30 struct namespace *namespace = p->nsproxy->namespace;
30 if (namespace) { 31 if (namespace) {
31 task_lock(p);
32 p->namespace = NULL;
33 task_unlock(p);
34 put_namespace(namespace); 32 put_namespace(namespace);
35 } 33 }
36} 34}
diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index 7bdebfaab6a5..7ebe66670c59 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -4,6 +4,8 @@
4#include <linux/spinlock.h> 4#include <linux/spinlock.h>
5#include <linux/sched.h> 5#include <linux/sched.h>
6 6
7struct namespace;
8
7/* 9/*
8 * A structure to contain pointers to all per-process 10 * A structure to contain pointers to all per-process
9 * namespaces - fs (mount), uts, network, sysvipc, etc. 11 * namespaces - fs (mount), uts, network, sysvipc, etc.
@@ -19,6 +21,7 @@
19struct nsproxy { 21struct nsproxy {
20 atomic_t count; 22 atomic_t count;
21 spinlock_t nslock; 23 spinlock_t nslock;
24 struct namespace *namespace;
22}; 25};
23extern struct nsproxy init_nsproxy; 26extern struct nsproxy init_nsproxy;
24 27
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 4fa631fa55e3..670b89a20070 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -238,7 +238,6 @@ extern signed long schedule_timeout_interruptible(signed long timeout);
238extern signed long schedule_timeout_uninterruptible(signed long timeout); 238extern signed long schedule_timeout_uninterruptible(signed long timeout);
239asmlinkage void schedule(void); 239asmlinkage void schedule(void);
240 240
241struct namespace;
242struct nsproxy; 241struct nsproxy;
243 242
244/* Maximum number of active map areas.. This is a random (large) number */ 243/* Maximum number of active map areas.. This is a random (large) number */
@@ -897,8 +896,7 @@ struct task_struct {
897 struct fs_struct *fs; 896 struct fs_struct *fs;
898/* open file information */ 897/* open file information */
899 struct files_struct *files; 898 struct files_struct *files;
900/* namespace */ 899/* namespaces */
901 struct namespace *namespace;
902 struct nsproxy *nsproxy; 900 struct nsproxy *nsproxy;
903/* signal handlers */ 901/* signal handlers */
904 struct signal_struct *signal; 902 struct signal_struct *signal;
diff --git a/kernel/exit.c b/kernel/exit.c
index 1d0e9ea1fa05..741bbe42dfe8 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -399,11 +399,8 @@ void daemonize(const char *name, ...)
399 current->fs = fs; 399 current->fs = fs;
400 atomic_inc(&fs->count); 400 atomic_inc(&fs->count);
401 401
402 exit_namespace(current);
403 exit_task_namespaces(current); 402 exit_task_namespaces(current);
404 current->namespace = init_task.namespace;
405 current->nsproxy = init_task.nsproxy; 403 current->nsproxy = init_task.nsproxy;
406 get_namespace(current->namespace);
407 get_task_namespaces(current); 404 get_task_namespaces(current);
408 405
409 exit_files(current); 406 exit_files(current);
@@ -923,7 +920,6 @@ fastcall NORET_TYPE void do_exit(long code)
923 exit_sem(tsk); 920 exit_sem(tsk);
924 __exit_files(tsk); 921 __exit_files(tsk);
925 __exit_fs(tsk); 922 __exit_fs(tsk);
926 exit_namespace(tsk);
927 exit_task_namespaces(tsk); 923 exit_task_namespaces(tsk);
928 exit_thread(); 924 exit_thread();
929 cpuset_exit(tsk); 925 cpuset_exit(tsk);
diff --git a/kernel/fork.c b/kernel/fork.c
index c9e660ae47aa..33fcf0733ca6 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1119,11 +1119,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1119 goto bad_fork_cleanup_mm; 1119 goto bad_fork_cleanup_mm;
1120 if ((retval = copy_namespaces(clone_flags, p))) 1120 if ((retval = copy_namespaces(clone_flags, p)))
1121 goto bad_fork_cleanup_keys; 1121 goto bad_fork_cleanup_keys;
1122 if ((retval = copy_namespace(clone_flags, p)))
1123 goto bad_fork_cleanup_namespaces;
1124 retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs); 1122 retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs);
1125 if (retval) 1123 if (retval)
1126 goto bad_fork_cleanup_namespace; 1124 goto bad_fork_cleanup_namespaces;
1127 1125
1128 p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; 1126 p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
1129 /* 1127 /*
@@ -1215,7 +1213,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1215 spin_unlock(&current->sighand->siglock); 1213 spin_unlock(&current->sighand->siglock);
1216 write_unlock_irq(&tasklist_lock); 1214 write_unlock_irq(&tasklist_lock);
1217 retval = -ERESTARTNOINTR; 1215 retval = -ERESTARTNOINTR;
1218 goto bad_fork_cleanup_namespace; 1216 goto bad_fork_cleanup_namespaces;
1219 } 1217 }
1220 1218
1221 if (clone_flags & CLONE_THREAD) { 1219 if (clone_flags & CLONE_THREAD) {
@@ -1263,8 +1261,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1263 proc_fork_connector(p); 1261 proc_fork_connector(p);
1264 return p; 1262 return p;
1265 1263
1266bad_fork_cleanup_namespace:
1267 exit_namespace(p);
1268bad_fork_cleanup_namespaces: 1264bad_fork_cleanup_namespaces:
1269 exit_task_namespaces(p); 1265 exit_task_namespaces(p);
1270bad_fork_cleanup_keys: 1266bad_fork_cleanup_keys:
@@ -1519,10 +1515,9 @@ static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp)
1519 */ 1515 */
1520static int unshare_namespace(unsigned long unshare_flags, struct namespace **new_nsp, struct fs_struct *new_fs) 1516static int unshare_namespace(unsigned long unshare_flags, struct namespace **new_nsp, struct fs_struct *new_fs)
1521{ 1517{
1522 struct namespace *ns = current->namespace; 1518 struct namespace *ns = current->nsproxy->namespace;
1523 1519
1524 if ((unshare_flags & CLONE_NEWNS) && 1520 if ((unshare_flags & CLONE_NEWNS) && ns) {
1525 (ns && atomic_read(&ns->count) > 1)) {
1526 if (!capable(CAP_SYS_ADMIN)) 1521 if (!capable(CAP_SYS_ADMIN))
1527 return -EPERM; 1522 return -EPERM;
1528 1523
@@ -1655,8 +1650,8 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
1655 } 1650 }
1656 1651
1657 if (new_ns) { 1652 if (new_ns) {
1658 ns = current->namespace; 1653 ns = current->nsproxy->namespace;
1659 current->namespace = new_ns; 1654 current->nsproxy->namespace = new_ns;
1660 new_ns = ns; 1655 new_ns = ns;
1661 } 1656 }
1662 1657
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index a3612f82f187..e10385c17f73 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -13,6 +13,7 @@
13#include <linux/version.h> 13#include <linux/version.h>
14#include <linux/nsproxy.h> 14#include <linux/nsproxy.h>
15#include <linux/init_task.h> 15#include <linux/init_task.h>
16#include <linux/namespace.h>
16 17
17struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy); 18struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
18 19
@@ -55,6 +56,11 @@ struct nsproxy *dup_namespaces(struct nsproxy *orig)
55{ 56{
56 struct nsproxy *ns = clone_namespaces(orig); 57 struct nsproxy *ns = clone_namespaces(orig);
57 58
59 if (ns) {
60 if (ns->namespace)
61 get_namespace(ns->namespace);
62 }
63
58 return ns; 64 return ns;
59} 65}
60 66
@@ -65,16 +71,40 @@ struct nsproxy *dup_namespaces(struct nsproxy *orig)
65int copy_namespaces(int flags, struct task_struct *tsk) 71int copy_namespaces(int flags, struct task_struct *tsk)
66{ 72{
67 struct nsproxy *old_ns = tsk->nsproxy; 73 struct nsproxy *old_ns = tsk->nsproxy;
74 struct nsproxy *new_ns;
75 int err = 0;
68 76
69 if (!old_ns) 77 if (!old_ns)
70 return 0; 78 return 0;
71 79
72 get_nsproxy(old_ns); 80 get_nsproxy(old_ns);
73 81
74 return 0; 82 if (!(flags & CLONE_NEWNS))
83 return 0;
84
85 new_ns = clone_namespaces(old_ns);
86 if (!new_ns) {
87 err = -ENOMEM;
88 goto out;
89 }
90
91 tsk->nsproxy = new_ns;
92
93 err = copy_namespace(flags, tsk);
94 if (err) {
95 tsk->nsproxy = old_ns;
96 put_nsproxy(new_ns);
97 goto out;
98 }
99
100out:
101 put_nsproxy(old_ns);
102 return err;
75} 103}
76 104
77void free_nsproxy(struct nsproxy *ns) 105void free_nsproxy(struct nsproxy *ns)
78{ 106{
107 if (ns->namespace)
108 put_namespace(ns->namespace);
79 kfree(ns); 109 kfree(ns);
80} 110}