aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/exit.c4
-rw-r--r--kernel/fork.c17
-rw-r--r--kernel/nsproxy.c32
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(&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}