Skip to content

Commit f8c46cb

Browse files
dtordavem330
authored andcommitted
netns: do not call pernet ops for not yet set up init_net namespace
When CONFIG_NET_NS is disabled, registering pernet operations causes init() to be called immediately with init_net as an argument. Unfortunately this leads to some pernet ops, such as proc_net_ns_init() to be called too early, when init_net namespace has not been fully initialized. This causes issues when we want to change pernet ops to use more data from the net namespace in question, for example reference user namespace that owns our network namespace. To fix this we could either play game of musical chairs and rearrange init order, or we could do the same as when CONFIG_NET_NS is enabled, and postpone calling pernet ops->init() until namespace is set up properly. Note that we can not simply undo commit ed160e8 ("[NET]: Cleanup pernet operation without CONFIG_NET_NS") and use the same implementations for __register_pernet_operations() and __unregister_pernet_operations(), because many pernet ops are marked as __net_initdata and will be discarded, which wreaks havoc on our ops lists. Here we rely on the fact that we only use lists until init_net is fully initialized, which happens much earlier than discarding __net_initdata sections. Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent d16d9d2 commit f8c46cb

File tree

1 file changed

+17
-4
lines changed

1 file changed

+17
-4
lines changed

net/core/net_namespace.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ struct net init_net = {
3737
};
3838
EXPORT_SYMBOL(init_net);
3939

40+
static bool init_net_initialized;
41+
4042
#define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */
4143

4244
static unsigned int max_gen_ptrs = INITIAL_NET_GEN_PTRS;
@@ -750,6 +752,8 @@ static int __init net_ns_init(void)
750752
if (setup_net(&init_net, &init_user_ns))
751753
panic("Could not setup the initial network namespace");
752754

755+
init_net_initialized = true;
756+
753757
rtnl_lock();
754758
list_add_tail_rcu(&init_net.list, &net_namespace_list);
755759
rtnl_unlock();
@@ -811,15 +815,24 @@ static void __unregister_pernet_operations(struct pernet_operations *ops)
811815
static int __register_pernet_operations(struct list_head *list,
812816
struct pernet_operations *ops)
813817
{
818+
if (!init_net_initialized) {
819+
list_add_tail(&ops->list, list);
820+
return 0;
821+
}
822+
814823
return ops_init(ops, &init_net);
815824
}
816825

817826
static void __unregister_pernet_operations(struct pernet_operations *ops)
818827
{
819-
LIST_HEAD(net_exit_list);
820-
list_add(&init_net.exit_list, &net_exit_list);
821-
ops_exit_list(ops, &net_exit_list);
822-
ops_free_list(ops, &net_exit_list);
828+
if (!init_net_initialized) {
829+
list_del(&ops->list);
830+
} else {
831+
LIST_HEAD(net_exit_list);
832+
list_add(&init_net.exit_list, &net_exit_list);
833+
ops_exit_list(ops, &net_exit_list);
834+
ops_free_list(ops, &net_exit_list);
835+
}
823836
}
824837

825838
#endif /* CONFIG_NET_NS */

0 commit comments

Comments
 (0)