diff options
-rw-r--r-- | include/net/net_namespace.h | 9 | ||||
-rw-r--r-- | kernel/nsproxy.c | 2 | ||||
-rw-r--r-- | net/core/net_namespace.c | 16 |
3 files changed, 20 insertions, 7 deletions
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 32dcb6085ebe..c5a43f56b796 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #endif | 23 | #endif |
24 | #include <net/netns/xfrm.h> | 24 | #include <net/netns/xfrm.h> |
25 | 25 | ||
26 | struct user_namespace; | ||
26 | struct proc_dir_entry; | 27 | struct proc_dir_entry; |
27 | struct net_device; | 28 | struct net_device; |
28 | struct sock; | 29 | struct sock; |
@@ -53,6 +54,8 @@ struct net { | |||
53 | struct list_head cleanup_list; /* namespaces on death row */ | 54 | struct list_head cleanup_list; /* namespaces on death row */ |
54 | struct list_head exit_list; /* Use only net_mutex */ | 55 | struct list_head exit_list; /* Use only net_mutex */ |
55 | 56 | ||
57 | struct user_namespace *user_ns; /* Owning user namespace */ | ||
58 | |||
56 | struct proc_dir_entry *proc_net; | 59 | struct proc_dir_entry *proc_net; |
57 | struct proc_dir_entry *proc_net_stat; | 60 | struct proc_dir_entry *proc_net_stat; |
58 | 61 | ||
@@ -127,12 +130,14 @@ struct net { | |||
127 | extern struct net init_net; | 130 | extern struct net init_net; |
128 | 131 | ||
129 | #ifdef CONFIG_NET_NS | 132 | #ifdef CONFIG_NET_NS |
130 | extern struct net *copy_net_ns(unsigned long flags, struct net *net_ns); | 133 | extern struct net *copy_net_ns(unsigned long flags, |
134 | struct user_namespace *user_ns, struct net *old_net); | ||
131 | 135 | ||
132 | #else /* CONFIG_NET_NS */ | 136 | #else /* CONFIG_NET_NS */ |
133 | #include <linux/sched.h> | 137 | #include <linux/sched.h> |
134 | #include <linux/nsproxy.h> | 138 | #include <linux/nsproxy.h> |
135 | static inline struct net *copy_net_ns(unsigned long flags, struct net *old_net) | 139 | static inline struct net *copy_net_ns(unsigned long flags, |
140 | struct user_namespace *user_ns, struct net *old_net) | ||
136 | { | 141 | { |
137 | if (flags & CLONE_NEWNET) | 142 | if (flags & CLONE_NEWNET) |
138 | return ERR_PTR(-EINVAL); | 143 | return ERR_PTR(-EINVAL); |
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c index b576f7f14bc6..7e1c3de1ce45 100644 --- a/kernel/nsproxy.c +++ b/kernel/nsproxy.c | |||
@@ -90,7 +90,7 @@ static struct nsproxy *create_new_namespaces(unsigned long flags, | |||
90 | goto out_pid; | 90 | goto out_pid; |
91 | } | 91 | } |
92 | 92 | ||
93 | new_nsp->net_ns = copy_net_ns(flags, tsk->nsproxy->net_ns); | 93 | new_nsp->net_ns = copy_net_ns(flags, task_cred_xxx(tsk, user_ns), tsk->nsproxy->net_ns); |
94 | if (IS_ERR(new_nsp->net_ns)) { | 94 | if (IS_ERR(new_nsp->net_ns)) { |
95 | err = PTR_ERR(new_nsp->net_ns); | 95 | err = PTR_ERR(new_nsp->net_ns); |
96 | goto out_net; | 96 | goto out_net; |
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 2c1c59091685..6456439cbbd9 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/proc_fs.h> | 13 | #include <linux/proc_fs.h> |
14 | #include <linux/file.h> | 14 | #include <linux/file.h> |
15 | #include <linux/export.h> | 15 | #include <linux/export.h> |
16 | #include <linux/user_namespace.h> | ||
16 | #include <net/net_namespace.h> | 17 | #include <net/net_namespace.h> |
17 | #include <net/netns/generic.h> | 18 | #include <net/netns/generic.h> |
18 | 19 | ||
@@ -145,7 +146,7 @@ static void ops_free_list(const struct pernet_operations *ops, | |||
145 | /* | 146 | /* |
146 | * setup_net runs the initializers for the network namespace object. | 147 | * setup_net runs the initializers for the network namespace object. |
147 | */ | 148 | */ |
148 | static __net_init int setup_net(struct net *net) | 149 | static __net_init int setup_net(struct net *net, struct user_namespace *user_ns) |
149 | { | 150 | { |
150 | /* Must be called with net_mutex held */ | 151 | /* Must be called with net_mutex held */ |
151 | const struct pernet_operations *ops, *saved_ops; | 152 | const struct pernet_operations *ops, *saved_ops; |
@@ -155,6 +156,7 @@ static __net_init int setup_net(struct net *net) | |||
155 | atomic_set(&net->count, 1); | 156 | atomic_set(&net->count, 1); |
156 | atomic_set(&net->passive, 1); | 157 | atomic_set(&net->passive, 1); |
157 | net->dev_base_seq = 1; | 158 | net->dev_base_seq = 1; |
159 | net->user_ns = user_ns; | ||
158 | 160 | ||
159 | #ifdef NETNS_REFCNT_DEBUG | 161 | #ifdef NETNS_REFCNT_DEBUG |
160 | atomic_set(&net->use_count, 0); | 162 | atomic_set(&net->use_count, 0); |
@@ -232,7 +234,8 @@ void net_drop_ns(void *p) | |||
232 | net_free(ns); | 234 | net_free(ns); |
233 | } | 235 | } |
234 | 236 | ||
235 | struct net *copy_net_ns(unsigned long flags, struct net *old_net) | 237 | struct net *copy_net_ns(unsigned long flags, |
238 | struct user_namespace *user_ns, struct net *old_net) | ||
236 | { | 239 | { |
237 | struct net *net; | 240 | struct net *net; |
238 | int rv; | 241 | int rv; |
@@ -243,8 +246,11 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net) | |||
243 | net = net_alloc(); | 246 | net = net_alloc(); |
244 | if (!net) | 247 | if (!net) |
245 | return ERR_PTR(-ENOMEM); | 248 | return ERR_PTR(-ENOMEM); |
249 | |||
250 | get_user_ns(user_ns); | ||
251 | |||
246 | mutex_lock(&net_mutex); | 252 | mutex_lock(&net_mutex); |
247 | rv = setup_net(net); | 253 | rv = setup_net(net, user_ns); |
248 | if (rv == 0) { | 254 | if (rv == 0) { |
249 | rtnl_lock(); | 255 | rtnl_lock(); |
250 | list_add_tail_rcu(&net->list, &net_namespace_list); | 256 | list_add_tail_rcu(&net->list, &net_namespace_list); |
@@ -252,6 +258,7 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net) | |||
252 | } | 258 | } |
253 | mutex_unlock(&net_mutex); | 259 | mutex_unlock(&net_mutex); |
254 | if (rv < 0) { | 260 | if (rv < 0) { |
261 | put_user_ns(user_ns); | ||
255 | net_drop_ns(net); | 262 | net_drop_ns(net); |
256 | return ERR_PTR(rv); | 263 | return ERR_PTR(rv); |
257 | } | 264 | } |
@@ -308,6 +315,7 @@ static void cleanup_net(struct work_struct *work) | |||
308 | /* Finally it is safe to free my network namespace structure */ | 315 | /* Finally it is safe to free my network namespace structure */ |
309 | list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) { | 316 | list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) { |
310 | list_del_init(&net->exit_list); | 317 | list_del_init(&net->exit_list); |
318 | put_user_ns(net->user_ns); | ||
311 | net_drop_ns(net); | 319 | net_drop_ns(net); |
312 | } | 320 | } |
313 | } | 321 | } |
@@ -395,7 +403,7 @@ static int __init net_ns_init(void) | |||
395 | rcu_assign_pointer(init_net.gen, ng); | 403 | rcu_assign_pointer(init_net.gen, ng); |
396 | 404 | ||
397 | mutex_lock(&net_mutex); | 405 | mutex_lock(&net_mutex); |
398 | if (setup_net(&init_net)) | 406 | if (setup_net(&init_net, &init_user_ns)) |
399 | panic("Could not setup the initial network namespace"); | 407 | panic("Could not setup the initial network namespace"); |
400 | 408 | ||
401 | rtnl_lock(); | 409 | rtnl_lock(); |