From: Tonghao Zhang <xiangxia.m....@gmail.com> The devconf setting on the init_net will affect other namespace when them created. For example:
$ cat /proc/sys/net/ipv4/conf/all/rp_filter 0 $ echo 2 > /proc/sys/net/ipv4/conf/all/rp_filter $ cat /proc/sys/net/ipv4/conf/all/rp_filter 2 $ ip netns add ns100 $ ip netns exec ns100 bash $ cat /proc/sys/net/ipv4/conf/all/rp_filter 2 The value of rp_filter in the ns100, should be 0 as default, but it is 2 same as _init_net_. To fix it and init devconf to default value, we allocate memory for every namespace(include init_net), this memory will be used to store themself setting data and we also allocate memory to register sys_ctl tables. IPv6 does that in the same way. Signed-off-by: Tonghao Zhang <xiangxia.m....@gmail.com> --- net/ipv4/devinet.c | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 5b9b6d4..2edf0f8 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -2555,33 +2555,28 @@ static __net_init int devinet_init_net(struct net *net) int err; struct ipv4_devconf *all, *dflt; #ifdef CONFIG_SYSCTL - struct ctl_table *tbl = ctl_forward_entry; + struct ctl_table *tbl; struct ctl_table_header *forw_hdr; #endif err = -ENOMEM; - all = &ipv4_devconf; - dflt = &ipv4_devconf_dflt; - - if (!net_eq(net, &init_net)) { - all = kmemdup(all, sizeof(ipv4_devconf), GFP_KERNEL); - if (!all) - goto err_alloc_all; + all = kmemdup(&ipv4_devconf, sizeof(ipv4_devconf), GFP_KERNEL); + if (!all) + goto err_alloc_all; - dflt = kmemdup(dflt, sizeof(ipv4_devconf_dflt), GFP_KERNEL); - if (!dflt) - goto err_alloc_dflt; + dflt = kmemdup(&ipv4_devconf_dflt, sizeof(ipv4_devconf_dflt), GFP_KERNEL); + if (!dflt) + goto err_alloc_dflt; #ifdef CONFIG_SYSCTL - tbl = kmemdup(tbl, sizeof(ctl_forward_entry), GFP_KERNEL); - if (!tbl) - goto err_alloc_ctl; + tbl = kmemdup(ctl_forward_entry, sizeof(ctl_forward_entry), GFP_KERNEL); + if (!tbl) + goto err_alloc_ctl; - tbl[0].data = &all->data[IPV4_DEVCONF_FORWARDING - 1]; - tbl[0].extra1 = all; - tbl[0].extra2 = net; + tbl[0].data = &all->data[IPV4_DEVCONF_FORWARDING - 1]; + tbl[0].extra1 = all; + tbl[0].extra2 = net; #endif - } #ifdef CONFIG_SYSCTL err = __devinet_sysctl_register(net, "all", NETCONFA_IFINDEX_ALL, all); @@ -2610,15 +2605,12 @@ static __net_init int devinet_init_net(struct net *net) err_reg_dflt: __devinet_sysctl_unregister(net, all, NETCONFA_IFINDEX_ALL); err_reg_all: - if (tbl != ctl_forward_entry) - kfree(tbl); + kfree(tbl); err_alloc_ctl: #endif - if (dflt != &ipv4_devconf_dflt) - kfree(dflt); + kfree(dflt); err_alloc_dflt: - if (all != &ipv4_devconf) - kfree(all); + kfree(all); err_alloc_all: return err; } -- 1.8.3.1