Commit a5612ca1 authored by Kuniyuki Iwashima's avatar Kuniyuki Iwashima Committed by David S. Miller
Browse files

net: Fix data-races around sysctl_devconf_inherit_init_net.



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

Fixes: 856c395c ("net: introduce a knob to control whether to inherit devconf config")
Signed-off-by: default avatarKuniyuki Iwashima <kuniyu@amazon.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent af67508e
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -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)
+10 −6
Original line number Diff line number Diff line
@@ -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
+2 −3
Original line number Diff line number Diff line
@@ -7162,9 +7162,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));