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

Reply via email to