Skip to content

Commit e9dcc6e

Browse files
Eric Dumazetsmb49
authored andcommitted
net: initialize init_net earlier
BugLink: https://bugs.launchpad.net/bugs/1969107 [ Upstream commit 9c1be19 ] While testing a patch that will follow later ("net: add netns refcount tracker to struct nsproxy") I found that devtmpfs_init() was called before init_net was initialized. This is a bug, because devtmpfs_setup() calls ksys_unshare(CLONE_NEWNS); This has the effect of increasing init_net refcount, which will be later overwritten to 1, as part of setup_net(&init_net) We had too many prior patches [1] trying to work around the root cause. Really, make sure init_net is in BSS section, and that net_ns_init() is called earlier at boot time. Note that another patch ("vfs: add netns refcount tracker to struct fs_context") also will need net_ns_init() being called before vfs_caches_init() As a bonus, this patch saves around 4KB in .data section. [1] f8c46cb ("netns: do not call pernet ops for not yet set up init_net namespace") b5082df ("net: Initialise init_net.count to 1") 734b654 ("net: Statically initialize init_net.dev_base_head") v2: fixed a build error reported by kernel build bots (CONFIG_NET=n) Signed-off-by: Eric Dumazet <[email protected]> Signed-off-by: David S. Miller <[email protected]> Signed-off-by: Sasha Levin <[email protected]> (cherry picked from commit 9c1ace066f22fe490d240dba8e13aeee9a88c589) Signed-off-by: Paolo Pisati <[email protected]>
1 parent 9ab50b0 commit e9dcc6e

File tree

4 files changed

+14
-14
lines changed

4 files changed

+14
-14
lines changed

include/net/net_namespace.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,4 +479,10 @@ static inline void fnhe_genid_bump(struct net *net)
479479
atomic_inc(&net->fnhe_genid);
480480
}
481481

482+
#ifdef CONFIG_NET
483+
void net_ns_init(void);
484+
#else
485+
static inline void net_ns_init(void) {}
486+
#endif
487+
482488
#endif /* __NET_NET_NAMESPACE_H */

init/main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
#include <linux/kcsan.h>
101101
#include <linux/init_syscalls.h>
102102
#include <linux/stackdepot.h>
103+
#include <net/net_namespace.h>
103104

104105
#include <asm/io.h>
105106
#include <asm/bugs.h>
@@ -1122,6 +1123,7 @@ asmlinkage __visible void __init __no_sanitize_address start_kernel(void)
11221123
key_init();
11231124
security_init();
11241125
dbg_late_init();
1126+
net_ns_init();
11251127
vfs_caches_init();
11261128
pagecache_init();
11271129
signals_init();

net/core/dev.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11378,8 +11378,7 @@ static int __net_init netdev_init(struct net *net)
1137811378
BUILD_BUG_ON(GRO_HASH_BUCKETS >
1137911379
8 * sizeof_field(struct napi_struct, gro_bitmask));
1138011380

11381-
if (net != &init_net)
11382-
INIT_LIST_HEAD(&net->dev_base_head);
11381+
INIT_LIST_HEAD(&net->dev_base_head);
1138311382

1138411383
net->dev_name_head = netdev_create_hash();
1138511384
if (net->dev_name_head == NULL)

net/core/net_namespace.c

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,7 @@ EXPORT_SYMBOL_GPL(net_rwsem);
4444
static struct key_tag init_net_key_domain = { .usage = REFCOUNT_INIT(1) };
4545
#endif
4646

47-
struct net init_net = {
48-
.ns.count = REFCOUNT_INIT(1),
49-
.dev_base_head = LIST_HEAD_INIT(init_net.dev_base_head),
50-
#ifdef CONFIG_KEYS
51-
.key_domain = &init_net_key_domain,
52-
#endif
53-
};
47+
struct net init_net;
5448
EXPORT_SYMBOL(init_net);
5549

5650
static bool init_net_initialized;
@@ -1081,7 +1075,7 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id, u32 portid,
10811075
rtnl_set_sk_err(net, RTNLGRP_NSID, err);
10821076
}
10831077

1084-
static int __init net_ns_init(void)
1078+
void __init net_ns_init(void)
10851079
{
10861080
struct net_generic *ng;
10871081

@@ -1102,6 +1096,9 @@ static int __init net_ns_init(void)
11021096

11031097
rcu_assign_pointer(init_net.gen, ng);
11041098

1099+
#ifdef CONFIG_KEYS
1100+
init_net.key_domain = &init_net_key_domain;
1101+
#endif
11051102
down_write(&pernet_ops_rwsem);
11061103
if (setup_net(&init_net, &init_user_ns))
11071104
panic("Could not setup the initial network namespace");
@@ -1116,12 +1113,8 @@ static int __init net_ns_init(void)
11161113
RTNL_FLAG_DOIT_UNLOCKED);
11171114
rtnl_register(PF_UNSPEC, RTM_GETNSID, rtnl_net_getid, rtnl_net_dumpid,
11181115
RTNL_FLAG_DOIT_UNLOCKED);
1119-
1120-
return 0;
11211116
}
11221117

1123-
pure_initcall(net_ns_init);
1124-
11251118
static void free_exit_list(struct pernet_operations *ops, struct list_head *net_exit_list)
11261119
{
11271120
ops_pre_exit_list(ops, net_exit_list);

0 commit comments

Comments
 (0)