OSDN Git Service

netns: enable to inherit devconf from current netns
authorNicolas Dichtel <nicolas.dichtel@6wind.com>
Wed, 13 May 2020 13:58:43 +0000 (15:58 +0200)
committerDavid S. Miller <davem@davemloft.net>
Sat, 16 May 2020 20:46:37 +0000 (13:46 -0700)
The goal is to be able to inherit the initial devconf parameters from the
current netns, ie the netns where this new netns has been created.

This is useful in a containers environment where /proc/sys is read only.
For example, if a pod is created with specifics devconf parameters and has
the capability to create netns, the user expects to get the same parameters
than his 'init_net', which is not the real init_net in this case.

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Documentation/admin-guide/sysctl/net.rst
net/core/sysctl_net_core.c
net/ipv4/devinet.c
net/ipv6/addrconf.c

index 2ad1b77..42cd04b 100644 (file)
@@ -339,7 +339,9 @@ settings from init_net and for IPv6 we reset all settings to default.
 
 If set to 1, both IPv4 and IPv6 settings are forced to inherit from
 current ones in init_net. If set to 2, both IPv4 and IPv6 settings are
-forced to reset to their default values.
+forced to reset to their default values. If set to 3, both IPv4 and IPv6
+settings are forced to inherit from current ones in the netns where this
+new netns has been created.
 
 Default : 0  (for compatibility reasons)
 
index 0ddb13a..b109cc8 100644 (file)
@@ -23,6 +23,7 @@
 #include <net/pkt_sched.h>
 
 static int two __maybe_unused = 2;
+static int three = 3;
 static int min_sndbuf = SOCK_MIN_SNDBUF;
 static int min_rcvbuf = SOCK_MIN_RCVBUF;
 static int max_skb_frags = MAX_SKB_FRAGS;
@@ -39,6 +40,7 @@ EXPORT_SYMBOL(sysctl_fb_tunnels_only_for_init_net);
  *     IPv6: reset all settings to default
  * 1 - Both inherit all current settings from init_net
  * 2 - Both reset all settings to default
+ * 3 - Both inherit all settings from current netns
  */
 int sysctl_devconf_inherit_init_net __read_mostly;
 EXPORT_SYMBOL(sysctl_devconf_inherit_init_net);
@@ -553,7 +555,7 @@ static struct ctl_table net_core_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec_minmax,
                .extra1         = SYSCTL_ZERO,
-               .extra2         = &two,
+               .extra2         = &three,
        },
        {
                .procname       = "high_order_alloc_disable",
index fc94f82..f048d0a 100644 (file)
@@ -2666,11 +2666,24 @@ static __net_init int devinet_init_net(struct net *net)
        tbl[0].extra2 = net;
 #endif
 
-       if ((!IS_ENABLED(CONFIG_SYSCTL) ||
-            sysctl_devconf_inherit_init_net != 2) &&
-           !net_eq(net, &init_net)) {
-               memcpy(all, init_net.ipv4.devconf_all, sizeof(ipv4_devconf));
-               memcpy(dflt, init_net.ipv4.devconf_dflt, sizeof(ipv4_devconf_dflt));
+       if (!net_eq(net, &init_net)) {
+               if (IS_ENABLED(CONFIG_SYSCTL) &&
+                   sysctl_devconf_inherit_init_net == 3) {
+                       /* copy from the current netns */
+                       memcpy(all, current->nsproxy->net_ns->ipv4.devconf_all,
+                              sizeof(ipv4_devconf));
+                       memcpy(dflt,
+                              current->nsproxy->net_ns->ipv4.devconf_dflt,
+                              sizeof(ipv4_devconf_dflt));
+               } else if (!IS_ENABLED(CONFIG_SYSCTL) ||
+                          sysctl_devconf_inherit_init_net != 2) {
+                       /* inherit == 0 or 1: copy from init_net */
+                       memcpy(all, init_net.ipv4.devconf_all,
+                              sizeof(ipv4_devconf));
+                       memcpy(dflt, init_net.ipv4.devconf_dflt,
+                              sizeof(ipv4_devconf_dflt));
+               }
+               /* else inherit == 2: use compiled values */
        }
 
 #ifdef CONFIG_SYSCTL
index fd885f0..ab7e839 100644 (file)
@@ -6991,9 +6991,26 @@ static int __net_init addrconf_init_net(struct net *net)
                goto err_alloc_dflt;
 
        if (IS_ENABLED(CONFIG_SYSCTL) &&
-           sysctl_devconf_inherit_init_net == 1 && !net_eq(net, &init_net)) {
-               memcpy(all, init_net.ipv6.devconf_all, sizeof(ipv6_devconf));
-               memcpy(dflt, init_net.ipv6.devconf_dflt, sizeof(ipv6_devconf_dflt));
+           !net_eq(net, &init_net)) {
+               switch (sysctl_devconf_inherit_init_net) {
+               case 1:  /* copy from init_net */
+                       memcpy(all, init_net.ipv6.devconf_all,
+                              sizeof(ipv6_devconf));
+                       memcpy(dflt, init_net.ipv6.devconf_dflt,
+                              sizeof(ipv6_devconf_dflt));
+                       break;
+               case 3: /* copy from the current netns */
+                       memcpy(all, current->nsproxy->net_ns->ipv6.devconf_all,
+                              sizeof(ipv6_devconf));
+                       memcpy(dflt,
+                              current->nsproxy->net_ns->ipv6.devconf_dflt,
+                              sizeof(ipv6_devconf_dflt));
+                       break;
+               case 0:
+               case 2:
+                       /* use compiled values */
+                       break;
+               }
        }
 
        /* these will be inherited by all namespaces */