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