]> git.itanic.dy.fi Git - linux-stable/commitdiff
net: Fix data-races around sysctl_devconf_inherit_init_net.
authorKuniyuki Iwashima <kuniyu@amazon.com>
Tue, 23 Aug 2022 17:46:57 +0000 (10:46 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 31 Aug 2022 15:18:09 +0000 (17:18 +0200)
[ Upstream commit a5612ca10d1aa05624ebe72633e0c8c792970833 ]

While reading sysctl_devconf_inherit_init_net, it can be changed
concurrently.  Thus, we need to add READ_ONCE() to its readers.

Fixes: 856c395cfa63 ("net: introduce a knob to control whether to inherit devconf config")
Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
include/linux/netdevice.h
net/ipv4/devinet.c
net/ipv6/addrconf.c

index 78dd63a5c7c80d8aa5e5009341b9cf68cfd62a3b..db40bc62213bda37330ff5fea6981d5291c26c36 100644 (file)
@@ -650,6 +650,15 @@ static inline bool net_has_fallback_tunnels(const struct net *net)
 #endif
 }
 
+static inline int net_inherit_devconf(void)
+{
+#if IS_ENABLED(CONFIG_SYSCTL)
+       return READ_ONCE(sysctl_devconf_inherit_init_net);
+#else
+       return 0;
+#endif
+}
+
 static inline int netdev_queue_numa_node_read(const struct netdev_queue *q)
 {
 #if defined(CONFIG_XPS) && defined(CONFIG_NUMA)
index b2366ad540e622d37de2283a676d8b4617054929..787a44e3222db04d77183a25709e682910cdc655 100644 (file)
@@ -2682,23 +2682,27 @@ static __net_init int devinet_init_net(struct net *net)
 #endif
 
        if (!net_eq(net, &init_net)) {
-               if (IS_ENABLED(CONFIG_SYSCTL) &&
-                   sysctl_devconf_inherit_init_net == 3) {
+               switch (net_inherit_devconf()) {
+               case 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 */
+                       break;
+               case 0:
+               case 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));
+                       break;
+               case 2:
+                       /* use compiled values */
+                       break;
                }
-               /* else inherit == 2: use compiled values */
        }
 
 #ifdef CONFIG_SYSCTL
index 49cc6587dd771ac0bb17fbc31402785bcdd8ff18..b738eb7e1cae80d86241737feb2a467f0da2fc6d 100644 (file)
@@ -7158,9 +7158,8 @@ static int __net_init addrconf_init_net(struct net *net)
        if (!dflt)
                goto err_alloc_dflt;
 
-       if (IS_ENABLED(CONFIG_SYSCTL) &&
-           !net_eq(net, &init_net)) {
-               switch (sysctl_devconf_inherit_init_net) {
+       if (!net_eq(net, &init_net)) {
+               switch (net_inherit_devconf()) {
                case 1:  /* copy from init_net */
                        memcpy(all, init_net.ipv6.devconf_all,
                               sizeof(ipv6_devconf));