net: Fix data-races around sysctl_devconf_inherit_init_net.
[ 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: 856c395cfa
("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>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
371a3bcf31
commit
9fcc4f4066
@@ -643,6 +643,15 @@ static inline bool net_has_fallback_tunnels(const struct net *net)
|
|||||||
#endif
|
#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)
|
static inline int netdev_queue_numa_node_read(const struct netdev_queue *q)
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_XPS) && defined(CONFIG_NUMA)
|
#if defined(CONFIG_XPS) && defined(CONFIG_NUMA)
|
||||||
|
@@ -2668,23 +2668,27 @@ static __net_init int devinet_init_net(struct net *net)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!net_eq(net, &init_net)) {
|
if (!net_eq(net, &init_net)) {
|
||||||
if (IS_ENABLED(CONFIG_SYSCTL) &&
|
switch (net_inherit_devconf()) {
|
||||||
sysctl_devconf_inherit_init_net == 3) {
|
case 3:
|
||||||
/* copy from the current netns */
|
/* copy from the current netns */
|
||||||
memcpy(all, current->nsproxy->net_ns->ipv4.devconf_all,
|
memcpy(all, current->nsproxy->net_ns->ipv4.devconf_all,
|
||||||
sizeof(ipv4_devconf));
|
sizeof(ipv4_devconf));
|
||||||
memcpy(dflt,
|
memcpy(dflt,
|
||||||
current->nsproxy->net_ns->ipv4.devconf_dflt,
|
current->nsproxy->net_ns->ipv4.devconf_dflt,
|
||||||
sizeof(ipv4_devconf_dflt));
|
sizeof(ipv4_devconf_dflt));
|
||||||
} else if (!IS_ENABLED(CONFIG_SYSCTL) ||
|
break;
|
||||||
sysctl_devconf_inherit_init_net != 2) {
|
case 0:
|
||||||
/* inherit == 0 or 1: copy from init_net */
|
case 1:
|
||||||
|
/* copy from init_net */
|
||||||
memcpy(all, init_net.ipv4.devconf_all,
|
memcpy(all, init_net.ipv4.devconf_all,
|
||||||
sizeof(ipv4_devconf));
|
sizeof(ipv4_devconf));
|
||||||
memcpy(dflt, init_net.ipv4.devconf_dflt,
|
memcpy(dflt, init_net.ipv4.devconf_dflt,
|
||||||
sizeof(ipv4_devconf_dflt));
|
sizeof(ipv4_devconf_dflt));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
/* use compiled values */
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
/* else inherit == 2: use compiled values */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SYSCTL
|
#ifdef CONFIG_SYSCTL
|
||||||
|
@@ -7042,9 +7042,8 @@ static int __net_init addrconf_init_net(struct net *net)
|
|||||||
if (!dflt)
|
if (!dflt)
|
||||||
goto err_alloc_dflt;
|
goto err_alloc_dflt;
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_SYSCTL) &&
|
if (!net_eq(net, &init_net)) {
|
||||||
!net_eq(net, &init_net)) {
|
switch (net_inherit_devconf()) {
|
||||||
switch (sysctl_devconf_inherit_init_net) {
|
|
||||||
case 1: /* copy from init_net */
|
case 1: /* copy from init_net */
|
||||||
memcpy(all, init_net.ipv6.devconf_all,
|
memcpy(all, init_net.ipv6.devconf_all,
|
||||||
sizeof(ipv6_devconf));
|
sizeof(ipv6_devconf));
|
||||||
|
Reference in New Issue
Block a user