1e005d193d55ee5f757b13306112d8c23aac27a88Joe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 2e005d193d55ee5f757b13306112d8c23aac27a88Joe Perches 35f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman#include <linux/workqueue.h> 45f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman#include <linux/rtnetlink.h> 55f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman#include <linux/cache.h> 65f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman#include <linux/slab.h> 75f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman#include <linux/list.h> 85f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman#include <linux/delay.h> 99dd776b6d7b0b85966b6ddd03e2b2aae59012ab1Eric W. Biederman#include <linux/sched.h> 10c93cf61fd1d5378134f9b06703f7078067542e00Pavel Emelyanov#include <linux/idr.h> 1111a28d373ed2539a110d56419457e2e7db221ac7Johannes Berg#include <linux/rculist.h> 1230ffee8480c13fbcf8ab6c28e31f79dfff683117Johannes Berg#include <linux/nsproxy.h> 130bb80f240520c4148b623161e7856858c021696dDavid Howells#include <linux/fs.h> 140bb80f240520c4148b623161e7856858c021696dDavid Howells#include <linux/proc_ns.h> 15f063052947f770845a6252f7fa24f6f624592a24Eric W. Biederman#include <linux/file.h> 16bc3b2d7fb9b014d75ebb79ba371a763dbab5e8cfPaul Gortmaker#include <linux/export.h> 17038e7332b8d4c0629a2965e3ede1a92e8e427bd6Eric W. Biederman#include <linux/user_namespace.h> 185f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman#include <net/net_namespace.h> 19dec827d174d7f76c457238800183ca864a639365Pavel Emelyanov#include <net/netns/generic.h> 205f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman 215f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman/* 225f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * Our network namespace constructor/destructor lists 235f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman */ 245f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman 255f256becd868bf63b70da8f2769033d6734670e9Eric W. Biedermanstatic LIST_HEAD(pernet_list); 265f256becd868bf63b70da8f2769033d6734670e9Eric W. Biedermanstatic struct list_head *first_device = &pernet_list; 27200b916f3575bdf11609cb447661b8d5957b0bbfCong WangDEFINE_MUTEX(net_mutex); 285f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman 295f256becd868bf63b70da8f2769033d6734670e9Eric W. BiedermanLIST_HEAD(net_namespace_list); 30b76a461f11eb5f32d37a9c8eae7b2f3b3f261b43Alexey DobriyanEXPORT_SYMBOL_GPL(net_namespace_list); 315f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman 32734b65417b24d6eea3e3d7457e1f11493890ee1dRustad, Mark Dstruct net init_net = { 33734b65417b24d6eea3e3d7457e1f11493890ee1dRustad, Mark D .dev_base_head = LIST_HEAD_INIT(init_net.dev_base_head), 34734b65417b24d6eea3e3d7457e1f11493890ee1dRustad, Mark D}; 35ff4b950277b6534caab2b2b956dba6ce29757551Denis V. LunevEXPORT_SYMBOL(init_net); 365f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman 37dec827d174d7f76c457238800183ca864a639365Pavel Emelyanov#define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */ 38dec827d174d7f76c457238800183ca864a639365Pavel Emelyanov 39073862ba5d249c20bd5c49fc6d904ff0e1f6a672Eric Dumazetstatic unsigned int max_gen_ptrs = INITIAL_NET_GEN_PTRS; 40073862ba5d249c20bd5c49fc6d904ff0e1f6a672Eric Dumazet 41073862ba5d249c20bd5c49fc6d904ff0e1f6a672Eric Dumazetstatic struct net_generic *net_alloc_generic(void) 42073862ba5d249c20bd5c49fc6d904ff0e1f6a672Eric Dumazet{ 43073862ba5d249c20bd5c49fc6d904ff0e1f6a672Eric Dumazet struct net_generic *ng; 44073862ba5d249c20bd5c49fc6d904ff0e1f6a672Eric Dumazet size_t generic_size = offsetof(struct net_generic, ptr[max_gen_ptrs]); 45073862ba5d249c20bd5c49fc6d904ff0e1f6a672Eric Dumazet 46073862ba5d249c20bd5c49fc6d904ff0e1f6a672Eric Dumazet ng = kzalloc(generic_size, GFP_KERNEL); 47073862ba5d249c20bd5c49fc6d904ff0e1f6a672Eric Dumazet if (ng) 48073862ba5d249c20bd5c49fc6d904ff0e1f6a672Eric Dumazet ng->len = max_gen_ptrs; 49073862ba5d249c20bd5c49fc6d904ff0e1f6a672Eric Dumazet 50073862ba5d249c20bd5c49fc6d904ff0e1f6a672Eric Dumazet return ng; 51073862ba5d249c20bd5c49fc6d904ff0e1f6a672Eric Dumazet} 52073862ba5d249c20bd5c49fc6d904ff0e1f6a672Eric Dumazet 5305fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirkostatic int net_assign_generic(struct net *net, int id, void *data) 5405fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko{ 5505fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko struct net_generic *ng, *old_ng; 5605fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko 5705fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko BUG_ON(!mutex_is_locked(&net_mutex)); 5805fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko BUG_ON(id == 0); 5905fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko 601c87733d0682547050ccccb400cdac425fa43b39Eric Dumazet old_ng = rcu_dereference_protected(net->gen, 611c87733d0682547050ccccb400cdac425fa43b39Eric Dumazet lockdep_is_held(&net_mutex)); 621c87733d0682547050ccccb400cdac425fa43b39Eric Dumazet ng = old_ng; 6305fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko if (old_ng->len >= id) 6405fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko goto assign; 6505fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko 66073862ba5d249c20bd5c49fc6d904ff0e1f6a672Eric Dumazet ng = net_alloc_generic(); 6705fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko if (ng == NULL) 6805fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko return -ENOMEM; 6905fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko 7005fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko /* 7105fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko * Some synchronisation notes: 7205fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko * 7305fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko * The net_generic explores the net->gen array inside rcu 7405fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko * read section. Besides once set the net->gen->ptr[x] 7505fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko * pointer never changes (see rules in netns/generic.h). 7605fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko * 7705fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko * That said, we simply duplicate this array and schedule 7805fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko * the old copy for kfree after a grace period. 7905fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko */ 8005fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko 8105fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko memcpy(&ng->ptr, &old_ng->ptr, old_ng->len * sizeof(void*)); 8205fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko 8305fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko rcu_assign_pointer(net->gen, ng); 8404d4dfed8e64f65d672502a614a4bb9093d1affdLai Jiangshan kfree_rcu(old_ng, rcu); 8505fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirkoassign: 8605fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko ng->ptr[id - 1] = data; 8705fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko return 0; 8805fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko} 8905fceb4ad7e8bf809a2a97061d6273d27d1a8449Jiri Pirko 90f875bae065334907796da12523f9df85c89f5712Eric W. Biedermanstatic int ops_init(const struct pernet_operations *ops, struct net *net) 91f875bae065334907796da12523f9df85c89f5712Eric W. Biederman{ 92b922934d017f1cc831b017913ed7d1a56c558b43Julian Anastasov int err = -ENOMEM; 93b922934d017f1cc831b017913ed7d1a56c558b43Julian Anastasov void *data = NULL; 94b922934d017f1cc831b017913ed7d1a56c558b43Julian Anastasov 95f875bae065334907796da12523f9df85c89f5712Eric W. Biederman if (ops->id && ops->size) { 96b922934d017f1cc831b017913ed7d1a56c558b43Julian Anastasov data = kzalloc(ops->size, GFP_KERNEL); 97f875bae065334907796da12523f9df85c89f5712Eric W. Biederman if (!data) 98b922934d017f1cc831b017913ed7d1a56c558b43Julian Anastasov goto out; 99f875bae065334907796da12523f9df85c89f5712Eric W. Biederman 100f875bae065334907796da12523f9df85c89f5712Eric W. Biederman err = net_assign_generic(net, *ops->id, data); 101b922934d017f1cc831b017913ed7d1a56c558b43Julian Anastasov if (err) 102b922934d017f1cc831b017913ed7d1a56c558b43Julian Anastasov goto cleanup; 103f875bae065334907796da12523f9df85c89f5712Eric W. Biederman } 104b922934d017f1cc831b017913ed7d1a56c558b43Julian Anastasov err = 0; 105f875bae065334907796da12523f9df85c89f5712Eric W. Biederman if (ops->init) 106b922934d017f1cc831b017913ed7d1a56c558b43Julian Anastasov err = ops->init(net); 107b922934d017f1cc831b017913ed7d1a56c558b43Julian Anastasov if (!err) 108b922934d017f1cc831b017913ed7d1a56c558b43Julian Anastasov return 0; 109b922934d017f1cc831b017913ed7d1a56c558b43Julian Anastasov 110b922934d017f1cc831b017913ed7d1a56c558b43Julian Anastasovcleanup: 111b922934d017f1cc831b017913ed7d1a56c558b43Julian Anastasov kfree(data); 112b922934d017f1cc831b017913ed7d1a56c558b43Julian Anastasov 113b922934d017f1cc831b017913ed7d1a56c558b43Julian Anastasovout: 114b922934d017f1cc831b017913ed7d1a56c558b43Julian Anastasov return err; 115f875bae065334907796da12523f9df85c89f5712Eric W. Biederman} 116f875bae065334907796da12523f9df85c89f5712Eric W. Biederman 117f875bae065334907796da12523f9df85c89f5712Eric W. Biedermanstatic void ops_free(const struct pernet_operations *ops, struct net *net) 118f875bae065334907796da12523f9df85c89f5712Eric W. Biederman{ 119f875bae065334907796da12523f9df85c89f5712Eric W. Biederman if (ops->id && ops->size) { 120f875bae065334907796da12523f9df85c89f5712Eric W. Biederman int id = *ops->id; 121f875bae065334907796da12523f9df85c89f5712Eric W. Biederman kfree(net_generic(net, id)); 122f875bae065334907796da12523f9df85c89f5712Eric W. Biederman } 123f875bae065334907796da12523f9df85c89f5712Eric W. Biederman} 124f875bae065334907796da12523f9df85c89f5712Eric W. Biederman 12572ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biedermanstatic void ops_exit_list(const struct pernet_operations *ops, 12672ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman struct list_head *net_exit_list) 12772ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman{ 12872ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman struct net *net; 12972ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman if (ops->exit) { 13072ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman list_for_each_entry(net, net_exit_list, exit_list) 13172ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman ops->exit(net); 13272ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman } 13372ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman if (ops->exit_batch) 13472ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman ops->exit_batch(net_exit_list); 13572ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman} 13672ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman 13772ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biedermanstatic void ops_free_list(const struct pernet_operations *ops, 13872ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman struct list_head *net_exit_list) 13972ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman{ 14072ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman struct net *net; 14172ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman if (ops->size && ops->id) { 14272ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman list_for_each_entry(net, net_exit_list, exit_list) 14372ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman ops_free(ops, net); 14472ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman } 14572ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman} 14672ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman 1475f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman/* 1485f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * setup_net runs the initializers for the network namespace object. 1495f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman */ 150038e7332b8d4c0629a2965e3ede1a92e8e427bd6Eric W. Biedermanstatic __net_init int setup_net(struct net *net, struct user_namespace *user_ns) 1515f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman{ 1525f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman /* Must be called with net_mutex held */ 153f875bae065334907796da12523f9df85c89f5712Eric W. Biederman const struct pernet_operations *ops, *saved_ops; 154486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano int error = 0; 15572ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman LIST_HEAD(net_exit_list); 1565f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman 1575f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman atomic_set(&net->count, 1); 158a685e08987d1edf1995b76511d4c98ea0e905377Al Viro atomic_set(&net->passive, 1); 1594e985adaa504c1c1a05c8e013777ea0791a17b4dThomas Graf net->dev_base_seq = 1; 160038e7332b8d4c0629a2965e3ede1a92e8e427bd6Eric W. Biederman net->user_ns = user_ns; 161486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano 1625d1e4468a7705db7c1415a65fd16f07113afc1b2Denis V. Lunev#ifdef NETNS_REFCNT_DEBUG 1635f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman atomic_set(&net->use_count, 0); 1645d1e4468a7705db7c1415a65fd16f07113afc1b2Denis V. Lunev#endif 1655f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman 166768f3591e2b1cc309fd6f10d6579b216026d7817Pavel Emelyanov list_for_each_entry(ops, &pernet_list, list) { 167f875bae065334907796da12523f9df85c89f5712Eric W. Biederman error = ops_init(ops, net); 168f875bae065334907796da12523f9df85c89f5712Eric W. Biederman if (error < 0) 169f875bae065334907796da12523f9df85c89f5712Eric W. Biederman goto out_undo; 1705f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman } 1715f256becd868bf63b70da8f2769033d6734670e9Eric W. Biedermanout: 1725f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman return error; 173768f3591e2b1cc309fd6f10d6579b216026d7817Pavel Emelyanov 1745f256becd868bf63b70da8f2769033d6734670e9Eric W. Biedermanout_undo: 1755f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman /* Walk through the list backwards calling the exit functions 1765f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * for the pernet modules whose init functions did not fail. 1775f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman */ 17872ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman list_add(&net->exit_list, &net_exit_list); 179f875bae065334907796da12523f9df85c89f5712Eric W. Biederman saved_ops = ops; 18072ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman list_for_each_entry_continue_reverse(ops, &pernet_list, list) 18172ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman ops_exit_list(ops, &net_exit_list); 18272ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman 183f875bae065334907796da12523f9df85c89f5712Eric W. Biederman ops = saved_ops; 184f875bae065334907796da12523f9df85c89f5712Eric W. Biederman list_for_each_entry_continue_reverse(ops, &pernet_list, list) 18572ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman ops_free_list(ops, &net_exit_list); 186310928d9633b04866a47f07eb43c498b2d82ebcbDaniel Lezcano 187310928d9633b04866a47f07eb43c498b2d82ebcbDaniel Lezcano rcu_barrier(); 1885f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman goto out; 1895f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman} 1905f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman 1916a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov 192ebe47d47b7b7fed72dabcce4717da727b4e2367dClemens Noss#ifdef CONFIG_NET_NS 193ebe47d47b7b7fed72dabcce4717da727b4e2367dClemens Nossstatic struct kmem_cache *net_cachep; 194ebe47d47b7b7fed72dabcce4717da727b4e2367dClemens Nossstatic struct workqueue_struct *netns_wq; 195ebe47d47b7b7fed72dabcce4717da727b4e2367dClemens Noss 196486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcanostatic struct net *net_alloc(void) 19745a19b0a725a04f3255d9d3da1fca30bb97f1481Johann Felix Soden{ 198486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano struct net *net = NULL; 199486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano struct net_generic *ng; 200486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano 201486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano ng = net_alloc_generic(); 202486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano if (!ng) 203486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano goto out; 204486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano 205486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano net = kmem_cache_zalloc(net_cachep, GFP_KERNEL); 20645a19b0a725a04f3255d9d3da1fca30bb97f1481Johann Felix Soden if (!net) 207486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano goto out_free; 20845a19b0a725a04f3255d9d3da1fca30bb97f1481Johann Felix Soden 209486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano rcu_assign_pointer(net->gen, ng); 210486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcanoout: 211486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano return net; 212486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano 213486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcanoout_free: 214486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano kfree(ng); 215486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano goto out; 216486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano} 217486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano 218486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcanostatic void net_free(struct net *net) 219486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano{ 2205d1e4468a7705db7c1415a65fd16f07113afc1b2Denis V. Lunev#ifdef NETNS_REFCNT_DEBUG 22145a19b0a725a04f3255d9d3da1fca30bb97f1481Johann Felix Soden if (unlikely(atomic_read(&net->use_count) != 0)) { 222e005d193d55ee5f757b13306112d8c23aac27a88Joe Perches pr_emerg("network namespace not free! Usage: %d\n", 223e005d193d55ee5f757b13306112d8c23aac27a88Joe Perches atomic_read(&net->use_count)); 22445a19b0a725a04f3255d9d3da1fca30bb97f1481Johann Felix Soden return; 22545a19b0a725a04f3255d9d3da1fca30bb97f1481Johann Felix Soden } 2265d1e4468a7705db7c1415a65fd16f07113afc1b2Denis V. Lunev#endif 227416c51e17b8b31b574763ac2b88ee99ddbb0c85dEric Dumazet kfree(rcu_access_pointer(net->gen)); 22845a19b0a725a04f3255d9d3da1fca30bb97f1481Johann Felix Soden kmem_cache_free(net_cachep, net); 22945a19b0a725a04f3255d9d3da1fca30bb97f1481Johann Felix Soden} 23045a19b0a725a04f3255d9d3da1fca30bb97f1481Johann Felix Soden 231a685e08987d1edf1995b76511d4c98ea0e905377Al Virovoid net_drop_ns(void *p) 232a685e08987d1edf1995b76511d4c98ea0e905377Al Viro{ 233a685e08987d1edf1995b76511d4c98ea0e905377Al Viro struct net *ns = p; 234a685e08987d1edf1995b76511d4c98ea0e905377Al Viro if (ns && atomic_dec_and_test(&ns->passive)) 235a685e08987d1edf1995b76511d4c98ea0e905377Al Viro net_free(ns); 236a685e08987d1edf1995b76511d4c98ea0e905377Al Viro} 237a685e08987d1edf1995b76511d4c98ea0e905377Al Viro 238038e7332b8d4c0629a2965e3ede1a92e8e427bd6Eric W. Biedermanstruct net *copy_net_ns(unsigned long flags, 239038e7332b8d4c0629a2965e3ede1a92e8e427bd6Eric W. Biederman struct user_namespace *user_ns, struct net *old_net) 2409dd776b6d7b0b85966b6ddd03e2b2aae59012ab1Eric W. Biederman{ 241088eb2d905de9518dad913995bb8aef493d4a7c5Alexey Dobriyan struct net *net; 242088eb2d905de9518dad913995bb8aef493d4a7c5Alexey Dobriyan int rv; 2439dd776b6d7b0b85966b6ddd03e2b2aae59012ab1Eric W. Biederman 244911cb193f3eb0370f20fbba712211e55ffede4deRob Landley if (!(flags & CLONE_NEWNET)) 245911cb193f3eb0370f20fbba712211e55ffede4deRob Landley return get_net(old_net); 246911cb193f3eb0370f20fbba712211e55ffede4deRob Landley 247088eb2d905de9518dad913995bb8aef493d4a7c5Alexey Dobriyan net = net_alloc(); 248088eb2d905de9518dad913995bb8aef493d4a7c5Alexey Dobriyan if (!net) 249088eb2d905de9518dad913995bb8aef493d4a7c5Alexey Dobriyan return ERR_PTR(-ENOMEM); 250038e7332b8d4c0629a2965e3ede1a92e8e427bd6Eric W. Biederman 251038e7332b8d4c0629a2965e3ede1a92e8e427bd6Eric W. Biederman get_user_ns(user_ns); 252038e7332b8d4c0629a2965e3ede1a92e8e427bd6Eric W. Biederman 2539dd776b6d7b0b85966b6ddd03e2b2aae59012ab1Eric W. Biederman mutex_lock(&net_mutex); 254038e7332b8d4c0629a2965e3ede1a92e8e427bd6Eric W. Biederman rv = setup_net(net, user_ns); 255088eb2d905de9518dad913995bb8aef493d4a7c5Alexey Dobriyan if (rv == 0) { 256486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano rtnl_lock(); 25711a28d373ed2539a110d56419457e2e7db221ac7Johannes Berg list_add_tail_rcu(&net->list, &net_namespace_list); 258486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano rtnl_unlock(); 259486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano } 2609dd776b6d7b0b85966b6ddd03e2b2aae59012ab1Eric W. Biederman mutex_unlock(&net_mutex); 261088eb2d905de9518dad913995bb8aef493d4a7c5Alexey Dobriyan if (rv < 0) { 262038e7332b8d4c0629a2965e3ede1a92e8e427bd6Eric W. Biederman put_user_ns(user_ns); 263a685e08987d1edf1995b76511d4c98ea0e905377Al Viro net_drop_ns(net); 264088eb2d905de9518dad913995bb8aef493d4a7c5Alexey Dobriyan return ERR_PTR(rv); 265088eb2d905de9518dad913995bb8aef493d4a7c5Alexey Dobriyan } 266088eb2d905de9518dad913995bb8aef493d4a7c5Alexey Dobriyan return net; 267088eb2d905de9518dad913995bb8aef493d4a7c5Alexey Dobriyan} 268486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano 2692b035b39970740722598f7a9d548835f9bdd730fEric W. Biedermanstatic DEFINE_SPINLOCK(cleanup_list_lock); 2702b035b39970740722598f7a9d548835f9bdd730fEric W. Biedermanstatic LIST_HEAD(cleanup_list); /* Must hold cleanup_list_lock to touch */ 2712b035b39970740722598f7a9d548835f9bdd730fEric W. Biederman 2726a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanovstatic void cleanup_net(struct work_struct *work) 2736a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov{ 274f875bae065334907796da12523f9df85c89f5712Eric W. Biederman const struct pernet_operations *ops; 2752b035b39970740722598f7a9d548835f9bdd730fEric W. Biederman struct net *net, *tmp; 2761818ce4dc59a71a53faa33a7ca050ca9c406bf66xiao jin struct list_head net_kill_list; 27772ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman LIST_HEAD(net_exit_list); 2786a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov 2792b035b39970740722598f7a9d548835f9bdd730fEric W. Biederman /* Atomically snapshot the list of namespaces to cleanup */ 2802b035b39970740722598f7a9d548835f9bdd730fEric W. Biederman spin_lock_irq(&cleanup_list_lock); 2812b035b39970740722598f7a9d548835f9bdd730fEric W. Biederman list_replace_init(&cleanup_list, &net_kill_list); 2822b035b39970740722598f7a9d548835f9bdd730fEric W. Biederman spin_unlock_irq(&cleanup_list_lock); 2836a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov 2846a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov mutex_lock(&net_mutex); 2856a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov 2866a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov /* Don't let anyone else find us. */ 2876a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov rtnl_lock(); 28872ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman list_for_each_entry(net, &net_kill_list, cleanup_list) { 2892b035b39970740722598f7a9d548835f9bdd730fEric W. Biederman list_del_rcu(&net->list); 29072ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman list_add_tail(&net->exit_list, &net_exit_list); 29172ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman } 2926a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov rtnl_unlock(); 2936a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov 29411a28d373ed2539a110d56419457e2e7db221ac7Johannes Berg /* 29511a28d373ed2539a110d56419457e2e7db221ac7Johannes Berg * Another CPU might be rcu-iterating the list, wait for it. 29611a28d373ed2539a110d56419457e2e7db221ac7Johannes Berg * This needs to be before calling the exit() notifiers, so 29711a28d373ed2539a110d56419457e2e7db221ac7Johannes Berg * the rcu_barrier() below isn't sufficient alone. 29811a28d373ed2539a110d56419457e2e7db221ac7Johannes Berg */ 29911a28d373ed2539a110d56419457e2e7db221ac7Johannes Berg synchronize_rcu(); 30011a28d373ed2539a110d56419457e2e7db221ac7Johannes Berg 3016a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov /* Run all of the network namespace exit methods */ 30272ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman list_for_each_entry_reverse(ops, &pernet_list, list) 30372ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman ops_exit_list(ops, &net_exit_list); 30472ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman 305f875bae065334907796da12523f9df85c89f5712Eric W. Biederman /* Free the net generic variables */ 30672ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman list_for_each_entry_reverse(ops, &pernet_list, list) 30772ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman ops_free_list(ops, &net_exit_list); 3086a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov 3096a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov mutex_unlock(&net_mutex); 3106a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov 3116a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov /* Ensure there are no outstanding rcu callbacks using this 3126a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov * network namespace. 3136a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov */ 3146a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov rcu_barrier(); 3156a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov 3166a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov /* Finally it is safe to free my network namespace structure */ 31772ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) { 31872ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman list_del_init(&net->exit_list); 319038e7332b8d4c0629a2965e3ede1a92e8e427bd6Eric W. Biederman put_user_ns(net->user_ns); 320a685e08987d1edf1995b76511d4c98ea0e905377Al Viro net_drop_ns(net); 3212b035b39970740722598f7a9d548835f9bdd730fEric W. Biederman } 3226a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov} 3232b035b39970740722598f7a9d548835f9bdd730fEric W. Biedermanstatic DECLARE_WORK(net_cleanup_work, cleanup_net); 3246a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov 3256a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanovvoid __put_net(struct net *net) 3266a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov{ 3276a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov /* Cleanup the network namespace in process context */ 3282b035b39970740722598f7a9d548835f9bdd730fEric W. Biederman unsigned long flags; 3292b035b39970740722598f7a9d548835f9bdd730fEric W. Biederman 3302b035b39970740722598f7a9d548835f9bdd730fEric W. Biederman spin_lock_irqsave(&cleanup_list_lock, flags); 3312b035b39970740722598f7a9d548835f9bdd730fEric W. Biederman list_add(&net->cleanup_list, &cleanup_list); 3322b035b39970740722598f7a9d548835f9bdd730fEric W. Biederman spin_unlock_irqrestore(&cleanup_list_lock, flags); 3332b035b39970740722598f7a9d548835f9bdd730fEric W. Biederman 3342b035b39970740722598f7a9d548835f9bdd730fEric W. Biederman queue_work(netns_wq, &net_cleanup_work); 3356a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov} 3366a1a3b9f686bb04820a232cc1657ef2c45670709Pavel EmelyanovEXPORT_SYMBOL_GPL(__put_net); 3376a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov 338956c920786694f51601a0ef7ee12956fd6aa216eStephen Rothwellstruct net *get_net_ns_by_fd(int fd) 339956c920786694f51601a0ef7ee12956fd6aa216eStephen Rothwell{ 3400bb80f240520c4148b623161e7856858c021696dDavid Howells struct proc_ns *ei; 341956c920786694f51601a0ef7ee12956fd6aa216eStephen Rothwell struct file *file; 342956c920786694f51601a0ef7ee12956fd6aa216eStephen Rothwell struct net *net; 343956c920786694f51601a0ef7ee12956fd6aa216eStephen Rothwell 344956c920786694f51601a0ef7ee12956fd6aa216eStephen Rothwell file = proc_ns_fget(fd); 345c316e6a3084cef1a5857cd66bb5429c969f06c93Al Viro if (IS_ERR(file)) 346c316e6a3084cef1a5857cd66bb5429c969f06c93Al Viro return ERR_CAST(file); 347956c920786694f51601a0ef7ee12956fd6aa216eStephen Rothwell 3480bb80f240520c4148b623161e7856858c021696dDavid Howells ei = get_proc_ns(file_inode(file)); 349c316e6a3084cef1a5857cd66bb5429c969f06c93Al Viro if (ei->ns_ops == &netns_operations) 350c316e6a3084cef1a5857cd66bb5429c969f06c93Al Viro net = get_net(ei->ns); 351c316e6a3084cef1a5857cd66bb5429c969f06c93Al Viro else 352c316e6a3084cef1a5857cd66bb5429c969f06c93Al Viro net = ERR_PTR(-EINVAL); 353956c920786694f51601a0ef7ee12956fd6aa216eStephen Rothwell 354c316e6a3084cef1a5857cd66bb5429c969f06c93Al Viro fput(file); 355956c920786694f51601a0ef7ee12956fd6aa216eStephen Rothwell return net; 356956c920786694f51601a0ef7ee12956fd6aa216eStephen Rothwell} 357956c920786694f51601a0ef7ee12956fd6aa216eStephen Rothwell 3586a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov#else 359956c920786694f51601a0ef7ee12956fd6aa216eStephen Rothwellstruct net *get_net_ns_by_fd(int fd) 360956c920786694f51601a0ef7ee12956fd6aa216eStephen Rothwell{ 361956c920786694f51601a0ef7ee12956fd6aa216eStephen Rothwell return ERR_PTR(-EINVAL); 362956c920786694f51601a0ef7ee12956fd6aa216eStephen Rothwell} 3636a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov#endif 3646a1a3b9f686bb04820a232cc1657ef2c45670709Pavel Emelyanov 36530ffee8480c13fbcf8ab6c28e31f79dfff683117Johannes Bergstruct net *get_net_ns_by_pid(pid_t pid) 36630ffee8480c13fbcf8ab6c28e31f79dfff683117Johannes Berg{ 36730ffee8480c13fbcf8ab6c28e31f79dfff683117Johannes Berg struct task_struct *tsk; 36830ffee8480c13fbcf8ab6c28e31f79dfff683117Johannes Berg struct net *net; 36930ffee8480c13fbcf8ab6c28e31f79dfff683117Johannes Berg 37030ffee8480c13fbcf8ab6c28e31f79dfff683117Johannes Berg /* Lookup the network namespace */ 37130ffee8480c13fbcf8ab6c28e31f79dfff683117Johannes Berg net = ERR_PTR(-ESRCH); 37230ffee8480c13fbcf8ab6c28e31f79dfff683117Johannes Berg rcu_read_lock(); 37330ffee8480c13fbcf8ab6c28e31f79dfff683117Johannes Berg tsk = find_task_by_vpid(pid); 37430ffee8480c13fbcf8ab6c28e31f79dfff683117Johannes Berg if (tsk) { 37530ffee8480c13fbcf8ab6c28e31f79dfff683117Johannes Berg struct nsproxy *nsproxy; 376728dba3a39c66b3d8ac889ddbe38b5b1c264aec3Eric W. Biederman task_lock(tsk); 377728dba3a39c66b3d8ac889ddbe38b5b1c264aec3Eric W. Biederman nsproxy = tsk->nsproxy; 37830ffee8480c13fbcf8ab6c28e31f79dfff683117Johannes Berg if (nsproxy) 37930ffee8480c13fbcf8ab6c28e31f79dfff683117Johannes Berg net = get_net(nsproxy->net_ns); 380728dba3a39c66b3d8ac889ddbe38b5b1c264aec3Eric W. Biederman task_unlock(tsk); 38130ffee8480c13fbcf8ab6c28e31f79dfff683117Johannes Berg } 38230ffee8480c13fbcf8ab6c28e31f79dfff683117Johannes Berg rcu_read_unlock(); 38330ffee8480c13fbcf8ab6c28e31f79dfff683117Johannes Berg return net; 38430ffee8480c13fbcf8ab6c28e31f79dfff683117Johannes Berg} 38530ffee8480c13fbcf8ab6c28e31f79dfff683117Johannes BergEXPORT_SYMBOL_GPL(get_net_ns_by_pid); 38630ffee8480c13fbcf8ab6c28e31f79dfff683117Johannes Berg 38798f842e675f96ffac96e6c50315790912b2812beEric W. Biedermanstatic __net_init int net_ns_net_init(struct net *net) 38898f842e675f96ffac96e6c50315790912b2812beEric W. Biederman{ 38998f842e675f96ffac96e6c50315790912b2812beEric W. Biederman return proc_alloc_inum(&net->proc_inum); 39098f842e675f96ffac96e6c50315790912b2812beEric W. Biederman} 39198f842e675f96ffac96e6c50315790912b2812beEric W. Biederman 39298f842e675f96ffac96e6c50315790912b2812beEric W. Biedermanstatic __net_exit void net_ns_net_exit(struct net *net) 39398f842e675f96ffac96e6c50315790912b2812beEric W. Biederman{ 39498f842e675f96ffac96e6c50315790912b2812beEric W. Biederman proc_free_inum(net->proc_inum); 39598f842e675f96ffac96e6c50315790912b2812beEric W. Biederman} 39698f842e675f96ffac96e6c50315790912b2812beEric W. Biederman 39798f842e675f96ffac96e6c50315790912b2812beEric W. Biedermanstatic struct pernet_operations __net_initdata net_ns_ops = { 39898f842e675f96ffac96e6c50315790912b2812beEric W. Biederman .init = net_ns_net_init, 39998f842e675f96ffac96e6c50315790912b2812beEric W. Biederman .exit = net_ns_net_exit, 40098f842e675f96ffac96e6c50315790912b2812beEric W. Biederman}; 40198f842e675f96ffac96e6c50315790912b2812beEric W. Biederman 4025f256becd868bf63b70da8f2769033d6734670e9Eric W. Biedermanstatic int __init net_ns_init(void) 4035f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman{ 404486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano struct net_generic *ng; 4055f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman 406d57a9212e00779181d8d820887dcab3e9d529194Pavel Emelyanov#ifdef CONFIG_NET_NS 4075f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman net_cachep = kmem_cache_create("net_namespace", sizeof(struct net), 4085f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman SMP_CACHE_BYTES, 4095f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman SLAB_PANIC, NULL); 4103ef1355dcb8551730cc71e9ef4363f5c66ccad17Benjamin Thery 4113ef1355dcb8551730cc71e9ef4363f5c66ccad17Benjamin Thery /* Create workqueue for cleanup */ 4123ef1355dcb8551730cc71e9ef4363f5c66ccad17Benjamin Thery netns_wq = create_singlethread_workqueue("netns"); 4133ef1355dcb8551730cc71e9ef4363f5c66ccad17Benjamin Thery if (!netns_wq) 4143ef1355dcb8551730cc71e9ef4363f5c66ccad17Benjamin Thery panic("Could not create netns workq"); 415d57a9212e00779181d8d820887dcab3e9d529194Pavel Emelyanov#endif 4163ef1355dcb8551730cc71e9ef4363f5c66ccad17Benjamin Thery 417486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano ng = net_alloc_generic(); 418486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano if (!ng) 419486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano panic("Could not allocate generic netns"); 420486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano 421486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano rcu_assign_pointer(init_net.gen, ng); 422486a87f1e5624096bd1c09e9e716239597d48dcaDaniel Lezcano 4235f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman mutex_lock(&net_mutex); 424038e7332b8d4c0629a2965e3ede1a92e8e427bd6Eric W. Biederman if (setup_net(&init_net, &init_user_ns)) 425ca0f31125c5cf0d48f47c2e1a3785a08876a7e87Stephen Hemminger panic("Could not setup the initial network namespace"); 4265f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman 427f4618d39a34dab316090263b42cd8799f31ce277Eric W. Biederman rtnl_lock(); 42811a28d373ed2539a110d56419457e2e7db221ac7Johannes Berg list_add_tail_rcu(&init_net.list, &net_namespace_list); 429f4618d39a34dab316090263b42cd8799f31ce277Eric W. Biederman rtnl_unlock(); 4305f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman 4315f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman mutex_unlock(&net_mutex); 4325f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman 43398f842e675f96ffac96e6c50315790912b2812beEric W. Biederman register_pernet_subsys(&net_ns_ops); 43498f842e675f96ffac96e6c50315790912b2812beEric W. Biederman 4355f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman return 0; 4365f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman} 4375f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman 4385f256becd868bf63b70da8f2769033d6734670e9Eric W. Biedermanpure_initcall(net_ns_init); 4395f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman 440ed160e839d2e1118529e58b04d52dba703ca629cDenis V. Lunev#ifdef CONFIG_NET_NS 441f875bae065334907796da12523f9df85c89f5712Eric W. Biedermanstatic int __register_pernet_operations(struct list_head *list, 442f875bae065334907796da12523f9df85c89f5712Eric W. Biederman struct pernet_operations *ops) 4435f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman{ 44472ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman struct net *net; 4455f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman int error; 44672ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman LIST_HEAD(net_exit_list); 4475f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman 4485f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman list_add_tail(&ops->list, list); 449f875bae065334907796da12523f9df85c89f5712Eric W. Biederman if (ops->init || (ops->id && ops->size)) { 4501dba323b3f92cf4a475236763b0373cb7d49395dPavel Emelyanov for_each_net(net) { 451f875bae065334907796da12523f9df85c89f5712Eric W. Biederman error = ops_init(ops, net); 4525f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman if (error) 4535f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman goto out_undo; 45472ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman list_add_tail(&net->exit_list, &net_exit_list); 4555f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman } 4565f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman } 4571dba323b3f92cf4a475236763b0373cb7d49395dPavel Emelyanov return 0; 4585f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman 4595f256becd868bf63b70da8f2769033d6734670e9Eric W. Biedermanout_undo: 4605f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman /* If I have an error cleanup all namespaces I initialized */ 4615f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman list_del(&ops->list); 46272ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman ops_exit_list(ops, &net_exit_list); 46372ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman ops_free_list(ops, &net_exit_list); 4641dba323b3f92cf4a475236763b0373cb7d49395dPavel Emelyanov return error; 4655f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman} 4665f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman 467f875bae065334907796da12523f9df85c89f5712Eric W. Biedermanstatic void __unregister_pernet_operations(struct pernet_operations *ops) 4685f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman{ 4695f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman struct net *net; 47072ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman LIST_HEAD(net_exit_list); 4715f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman 4725f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman list_del(&ops->list); 47372ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman for_each_net(net) 47472ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman list_add_tail(&net->exit_list, &net_exit_list); 47572ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman ops_exit_list(ops, &net_exit_list); 47672ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman ops_free_list(ops, &net_exit_list); 4775f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman} 4785f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman 479ed160e839d2e1118529e58b04d52dba703ca629cDenis V. Lunev#else 480ed160e839d2e1118529e58b04d52dba703ca629cDenis V. Lunev 481f875bae065334907796da12523f9df85c89f5712Eric W. Biedermanstatic int __register_pernet_operations(struct list_head *list, 482f875bae065334907796da12523f9df85c89f5712Eric W. Biederman struct pernet_operations *ops) 483ed160e839d2e1118529e58b04d52dba703ca629cDenis V. Lunev{ 484b922934d017f1cc831b017913ed7d1a56c558b43Julian Anastasov return ops_init(ops, &init_net); 485ed160e839d2e1118529e58b04d52dba703ca629cDenis V. Lunev} 486ed160e839d2e1118529e58b04d52dba703ca629cDenis V. Lunev 487f875bae065334907796da12523f9df85c89f5712Eric W. Biedermanstatic void __unregister_pernet_operations(struct pernet_operations *ops) 488ed160e839d2e1118529e58b04d52dba703ca629cDenis V. Lunev{ 48972ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman LIST_HEAD(net_exit_list); 49072ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman list_add(&init_net.exit_list, &net_exit_list); 49172ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman ops_exit_list(ops, &net_exit_list); 49272ad937abd0a43b7cf2c557ba1f2ec75e608c516Eric W. Biederman ops_free_list(ops, &net_exit_list); 493ed160e839d2e1118529e58b04d52dba703ca629cDenis V. Lunev} 494f875bae065334907796da12523f9df85c89f5712Eric W. Biederman 495f875bae065334907796da12523f9df85c89f5712Eric W. Biederman#endif /* CONFIG_NET_NS */ 496ed160e839d2e1118529e58b04d52dba703ca629cDenis V. Lunev 497c93cf61fd1d5378134f9b06703f7078067542e00Pavel Emelyanovstatic DEFINE_IDA(net_generic_ids); 498c93cf61fd1d5378134f9b06703f7078067542e00Pavel Emelyanov 499f875bae065334907796da12523f9df85c89f5712Eric W. Biedermanstatic int register_pernet_operations(struct list_head *list, 500f875bae065334907796da12523f9df85c89f5712Eric W. Biederman struct pernet_operations *ops) 501f875bae065334907796da12523f9df85c89f5712Eric W. Biederman{ 502f875bae065334907796da12523f9df85c89f5712Eric W. Biederman int error; 503f875bae065334907796da12523f9df85c89f5712Eric W. Biederman 504f875bae065334907796da12523f9df85c89f5712Eric W. Biederman if (ops->id) { 505f875bae065334907796da12523f9df85c89f5712Eric W. Biedermanagain: 506f875bae065334907796da12523f9df85c89f5712Eric W. Biederman error = ida_get_new_above(&net_generic_ids, 1, ops->id); 507f875bae065334907796da12523f9df85c89f5712Eric W. Biederman if (error < 0) { 508f875bae065334907796da12523f9df85c89f5712Eric W. Biederman if (error == -EAGAIN) { 509f875bae065334907796da12523f9df85c89f5712Eric W. Biederman ida_pre_get(&net_generic_ids, GFP_KERNEL); 510f875bae065334907796da12523f9df85c89f5712Eric W. Biederman goto again; 511f875bae065334907796da12523f9df85c89f5712Eric W. Biederman } 512f875bae065334907796da12523f9df85c89f5712Eric W. Biederman return error; 513f875bae065334907796da12523f9df85c89f5712Eric W. Biederman } 514073862ba5d249c20bd5c49fc6d904ff0e1f6a672Eric Dumazet max_gen_ptrs = max_t(unsigned int, max_gen_ptrs, *ops->id); 515f875bae065334907796da12523f9df85c89f5712Eric W. Biederman } 516f875bae065334907796da12523f9df85c89f5712Eric W. Biederman error = __register_pernet_operations(list, ops); 5173a765edadb28cc736d185f67d1ba6bedcc85f4b9Eric W. Biederman if (error) { 5183a765edadb28cc736d185f67d1ba6bedcc85f4b9Eric W. Biederman rcu_barrier(); 5193a765edadb28cc736d185f67d1ba6bedcc85f4b9Eric W. Biederman if (ops->id) 5203a765edadb28cc736d185f67d1ba6bedcc85f4b9Eric W. Biederman ida_remove(&net_generic_ids, *ops->id); 5213a765edadb28cc736d185f67d1ba6bedcc85f4b9Eric W. Biederman } 522f875bae065334907796da12523f9df85c89f5712Eric W. Biederman 523f875bae065334907796da12523f9df85c89f5712Eric W. Biederman return error; 524f875bae065334907796da12523f9df85c89f5712Eric W. Biederman} 525f875bae065334907796da12523f9df85c89f5712Eric W. Biederman 526f875bae065334907796da12523f9df85c89f5712Eric W. Biedermanstatic void unregister_pernet_operations(struct pernet_operations *ops) 527f875bae065334907796da12523f9df85c89f5712Eric W. Biederman{ 528f875bae065334907796da12523f9df85c89f5712Eric W. Biederman 529f875bae065334907796da12523f9df85c89f5712Eric W. Biederman __unregister_pernet_operations(ops); 5303a765edadb28cc736d185f67d1ba6bedcc85f4b9Eric W. Biederman rcu_barrier(); 531f875bae065334907796da12523f9df85c89f5712Eric W. Biederman if (ops->id) 532f875bae065334907796da12523f9df85c89f5712Eric W. Biederman ida_remove(&net_generic_ids, *ops->id); 533f875bae065334907796da12523f9df85c89f5712Eric W. Biederman} 534f875bae065334907796da12523f9df85c89f5712Eric W. Biederman 5355f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman/** 5365f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * register_pernet_subsys - register a network namespace subsystem 5375f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * @ops: pernet operations structure for the subsystem 5385f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * 5395f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * Register a subsystem which has init and exit functions 5405f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * that are called when network namespaces are created and 5415f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * destroyed respectively. 5425f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * 5435f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * When registered all network namespace init functions are 5445f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * called for every existing network namespace. Allowing kernel 5455f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * modules to have a race free view of the set of network namespaces. 5465f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * 5475f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * When a new network namespace is created all of the init 5485f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * methods are called in the order in which they were registered. 5495f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * 5505f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * When a network namespace is destroyed all of the exit methods 5515f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * are called in the reverse of the order with which they were 5525f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * registered. 5535f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman */ 5545f256becd868bf63b70da8f2769033d6734670e9Eric W. Biedermanint register_pernet_subsys(struct pernet_operations *ops) 5555f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman{ 5565f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman int error; 5575f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman mutex_lock(&net_mutex); 5585f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman error = register_pernet_operations(first_device, ops); 5595f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman mutex_unlock(&net_mutex); 5605f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman return error; 5615f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman} 5625f256becd868bf63b70da8f2769033d6734670e9Eric W. BiedermanEXPORT_SYMBOL_GPL(register_pernet_subsys); 5635f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman 5645f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman/** 5655f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * unregister_pernet_subsys - unregister a network namespace subsystem 5665f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * @ops: pernet operations structure to manipulate 5675f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * 5685f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * Remove the pernet operations structure from the list to be 56953379e57a7705e2946c8d77d09a57a169097a6feOliver Pinter * used when network namespaces are created or destroyed. In 5705f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * addition run the exit method for all existing network 5715f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * namespaces. 5725f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman */ 573b3c981d2bbbe889125169bd0bb482e64d3c028a1Jiri Pirkovoid unregister_pernet_subsys(struct pernet_operations *ops) 5745f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman{ 5755f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman mutex_lock(&net_mutex); 576b3c981d2bbbe889125169bd0bb482e64d3c028a1Jiri Pirko unregister_pernet_operations(ops); 5775f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman mutex_unlock(&net_mutex); 5785f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman} 5795f256becd868bf63b70da8f2769033d6734670e9Eric W. BiedermanEXPORT_SYMBOL_GPL(unregister_pernet_subsys); 5805f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman 5815f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman/** 5825f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * register_pernet_device - register a network namespace device 5835f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * @ops: pernet operations structure for the subsystem 5845f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * 5855f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * Register a device which has init and exit functions 5865f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * that are called when network namespaces are created and 5875f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * destroyed respectively. 5885f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * 5895f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * When registered all network namespace init functions are 5905f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * called for every existing network namespace. Allowing kernel 5915f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * modules to have a race free view of the set of network namespaces. 5925f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * 5935f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * When a new network namespace is created all of the init 5945f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * methods are called in the order in which they were registered. 5955f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * 5965f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * When a network namespace is destroyed all of the exit methods 5975f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * are called in the reverse of the order with which they were 5985f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * registered. 5995f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman */ 6005f256becd868bf63b70da8f2769033d6734670e9Eric W. Biedermanint register_pernet_device(struct pernet_operations *ops) 6015f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman{ 6025f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman int error; 6035f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman mutex_lock(&net_mutex); 6045f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman error = register_pernet_operations(&pernet_list, ops); 6055f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman if (!error && (first_device == &pernet_list)) 6065f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman first_device = &ops->list; 6075f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman mutex_unlock(&net_mutex); 6085f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman return error; 6095f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman} 6105f256becd868bf63b70da8f2769033d6734670e9Eric W. BiedermanEXPORT_SYMBOL_GPL(register_pernet_device); 6115f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman 6125f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman/** 6135f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * unregister_pernet_device - unregister a network namespace netdevice 6145f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * @ops: pernet operations structure to manipulate 6155f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * 6165f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * Remove the pernet operations structure from the list to be 61753379e57a7705e2946c8d77d09a57a169097a6feOliver Pinter * used when network namespaces are created or destroyed. In 6185f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * addition run the exit method for all existing network 6195f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman * namespaces. 6205f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman */ 6215f256becd868bf63b70da8f2769033d6734670e9Eric W. Biedermanvoid unregister_pernet_device(struct pernet_operations *ops) 6225f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman{ 6235f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman mutex_lock(&net_mutex); 6245f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman if (&ops->list == first_device) 6255f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman first_device = first_device->next; 6265f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman unregister_pernet_operations(ops); 6275f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman mutex_unlock(&net_mutex); 6285f256becd868bf63b70da8f2769033d6734670e9Eric W. Biederman} 6295f256becd868bf63b70da8f2769033d6734670e9Eric W. BiedermanEXPORT_SYMBOL_GPL(unregister_pernet_device); 63013b6f57623bc485e116344fe91fbcb29f149242bEric W. Biederman 63113b6f57623bc485e116344fe91fbcb29f149242bEric W. Biederman#ifdef CONFIG_NET_NS 63213b6f57623bc485e116344fe91fbcb29f149242bEric W. Biedermanstatic void *netns_get(struct task_struct *task) 63313b6f57623bc485e116344fe91fbcb29f149242bEric W. Biederman{ 634f063052947f770845a6252f7fa24f6f624592a24Eric W. Biederman struct net *net = NULL; 635f063052947f770845a6252f7fa24f6f624592a24Eric W. Biederman struct nsproxy *nsproxy; 636f063052947f770845a6252f7fa24f6f624592a24Eric W. Biederman 637728dba3a39c66b3d8ac889ddbe38b5b1c264aec3Eric W. Biederman task_lock(task); 638728dba3a39c66b3d8ac889ddbe38b5b1c264aec3Eric W. Biederman nsproxy = task->nsproxy; 639f063052947f770845a6252f7fa24f6f624592a24Eric W. Biederman if (nsproxy) 640f063052947f770845a6252f7fa24f6f624592a24Eric W. Biederman net = get_net(nsproxy->net_ns); 641728dba3a39c66b3d8ac889ddbe38b5b1c264aec3Eric W. Biederman task_unlock(task); 642f063052947f770845a6252f7fa24f6f624592a24Eric W. Biederman 64313b6f57623bc485e116344fe91fbcb29f149242bEric W. Biederman return net; 64413b6f57623bc485e116344fe91fbcb29f149242bEric W. Biederman} 64513b6f57623bc485e116344fe91fbcb29f149242bEric W. Biederman 64613b6f57623bc485e116344fe91fbcb29f149242bEric W. Biedermanstatic void netns_put(void *ns) 64713b6f57623bc485e116344fe91fbcb29f149242bEric W. Biederman{ 64813b6f57623bc485e116344fe91fbcb29f149242bEric W. Biederman put_net(ns); 64913b6f57623bc485e116344fe91fbcb29f149242bEric W. Biederman} 65013b6f57623bc485e116344fe91fbcb29f149242bEric W. Biederman 65113b6f57623bc485e116344fe91fbcb29f149242bEric W. Biedermanstatic int netns_install(struct nsproxy *nsproxy, void *ns) 65213b6f57623bc485e116344fe91fbcb29f149242bEric W. Biederman{ 653142e1d1d5f088e7a38659daca6e84a730967774aEric W. Biederman struct net *net = ns; 654142e1d1d5f088e7a38659daca6e84a730967774aEric W. Biederman 6555e4a08476b50fa39210fca82e03325cc46b9c235Eric W. Biederman if (!ns_capable(net->user_ns, CAP_SYS_ADMIN) || 656c7b96acf1456ef127fef461fcfedb54b81fecfbbEric W. Biederman !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) 657142e1d1d5f088e7a38659daca6e84a730967774aEric W. Biederman return -EPERM; 658142e1d1d5f088e7a38659daca6e84a730967774aEric W. Biederman 65913b6f57623bc485e116344fe91fbcb29f149242bEric W. Biederman put_net(nsproxy->net_ns); 660142e1d1d5f088e7a38659daca6e84a730967774aEric W. Biederman nsproxy->net_ns = get_net(net); 66113b6f57623bc485e116344fe91fbcb29f149242bEric W. Biederman return 0; 66213b6f57623bc485e116344fe91fbcb29f149242bEric W. Biederman} 66313b6f57623bc485e116344fe91fbcb29f149242bEric W. Biederman 66498f842e675f96ffac96e6c50315790912b2812beEric W. Biedermanstatic unsigned int netns_inum(void *ns) 66598f842e675f96ffac96e6c50315790912b2812beEric W. Biederman{ 66698f842e675f96ffac96e6c50315790912b2812beEric W. Biederman struct net *net = ns; 66798f842e675f96ffac96e6c50315790912b2812beEric W. Biederman return net->proc_inum; 66898f842e675f96ffac96e6c50315790912b2812beEric W. Biederman} 66998f842e675f96ffac96e6c50315790912b2812beEric W. Biederman 67013b6f57623bc485e116344fe91fbcb29f149242bEric W. Biedermanconst struct proc_ns_operations netns_operations = { 67113b6f57623bc485e116344fe91fbcb29f149242bEric W. Biederman .name = "net", 67213b6f57623bc485e116344fe91fbcb29f149242bEric W. Biederman .type = CLONE_NEWNET, 67313b6f57623bc485e116344fe91fbcb29f149242bEric W. Biederman .get = netns_get, 67413b6f57623bc485e116344fe91fbcb29f149242bEric W. Biederman .put = netns_put, 67513b6f57623bc485e116344fe91fbcb29f149242bEric W. Biederman .install = netns_install, 67698f842e675f96ffac96e6c50315790912b2812beEric W. Biederman .inum = netns_inum, 67713b6f57623bc485e116344fe91fbcb29f149242bEric W. Biederman}; 67813b6f57623bc485e116344fe91fbcb29f149242bEric W. Biederman#endif 679