diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/exit.c | 4 | ||||
-rw-r--r-- | kernel/fork.c | 17 | ||||
-rw-r--r-- | kernel/nsproxy.c | 32 |
3 files changed, 37 insertions, 16 deletions
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(¤t->sighand->siglock); | 1213 | spin_unlock(¤t->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 | ||
1266 | bad_fork_cleanup_namespace: | ||
1267 | exit_namespace(p); | ||
1268 | bad_fork_cleanup_namespaces: | 1264 | bad_fork_cleanup_namespaces: |
1269 | exit_task_namespaces(p); | 1265 | exit_task_namespaces(p); |
1270 | bad_fork_cleanup_keys: | 1266 | bad_fork_cleanup_keys: |
@@ -1519,10 +1515,9 @@ static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp) | |||
1519 | */ | 1515 | */ |
1520 | static int unshare_namespace(unsigned long unshare_flags, struct namespace **new_nsp, struct fs_struct *new_fs) | 1516 | static 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 | ||
17 | struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy); | 18 | struct 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) | |||
65 | int copy_namespaces(int flags, struct task_struct *tsk) | 71 | int 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 | |||
100 | out: | ||
101 | put_nsproxy(old_ns); | ||
102 | return err; | ||
75 | } | 103 | } |
76 | 104 | ||
77 | void free_nsproxy(struct nsproxy *ns) | 105 | void free_nsproxy(struct nsproxy *ns) |
78 | { | 106 | { |
107 | if (ns->namespace) | ||
108 | put_namespace(ns->namespace); | ||
79 | kfree(ns); | 109 | kfree(ns); |
80 | } | 110 | } |