diff options
Diffstat (limited to 'net/core/net_namespace.c')
-rw-r--r-- | net/core/net_namespace.c | 23 |
1 files changed, 12 insertions, 11 deletions
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 42f1e1c7514f..6456439cbbd9 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -13,6 +13,7 @@ #include <linux/proc_fs.h> #include <linux/file.h> #include <linux/export.h> +#include <linux/user_namespace.h> #include <net/net_namespace.h> #include <net/netns/generic.h> @@ -145,7 +146,7 @@ static void ops_free_list(const struct pernet_operations *ops, /* * setup_net runs the initializers for the network namespace object. */ -static __net_init int setup_net(struct net *net) +static __net_init int setup_net(struct net *net, struct user_namespace *user_ns) { /* Must be called with net_mutex held */ const struct pernet_operations *ops, *saved_ops; @@ -155,6 +156,7 @@ static __net_init int setup_net(struct net *net) atomic_set(&net->count, 1); atomic_set(&net->passive, 1); net->dev_base_seq = 1; + net->user_ns = user_ns; #ifdef NETNS_REFCNT_DEBUG atomic_set(&net->use_count, 0); @@ -232,7 +234,8 @@ void net_drop_ns(void *p) net_free(ns); } -struct net *copy_net_ns(unsigned long flags, struct net *old_net) +struct net *copy_net_ns(unsigned long flags, + struct user_namespace *user_ns, struct net *old_net) { struct net *net; int rv; @@ -243,8 +246,11 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net) net = net_alloc(); if (!net) return ERR_PTR(-ENOMEM); + + get_user_ns(user_ns); + mutex_lock(&net_mutex); - rv = setup_net(net); + rv = setup_net(net, user_ns); if (rv == 0) { rtnl_lock(); 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) } mutex_unlock(&net_mutex); if (rv < 0) { + put_user_ns(user_ns); net_drop_ns(net); return ERR_PTR(rv); } @@ -308,6 +315,7 @@ static void cleanup_net(struct work_struct *work) /* Finally it is safe to free my network namespace structure */ list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) { list_del_init(&net->exit_list); + put_user_ns(net->user_ns); net_drop_ns(net); } } @@ -347,13 +355,6 @@ struct net *get_net_ns_by_fd(int fd) } #else -struct net *copy_net_ns(unsigned long flags, struct net *old_net) -{ - if (flags & CLONE_NEWNET) - return ERR_PTR(-EINVAL); - return old_net; -} - struct net *get_net_ns_by_fd(int fd) { return ERR_PTR(-EINVAL); @@ -402,7 +403,7 @@ static int __init net_ns_init(void) rcu_assign_pointer(init_net.gen, ng); mutex_lock(&net_mutex); - if (setup_net(&init_net)) + if (setup_net(&init_net, &init_user_ns)) panic("Could not setup the initial network namespace"); rtnl_lock(); |