Commit 32f75417 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

ipv6: annotate data-races around cnf.forwarding



idev->cnf.forwarding and net->ipv6.devconf_all->forwarding
might be read locklessly, add appropriate READ_ONCE()
and WRITE_ONCE() annotations.

Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Reviewed-by: default avatarJiri Pirko <jiri@nvidia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e0bb2675
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -339,7 +339,7 @@ static void do_neigh_solicit(struct usbnet *dev, u8 *buf, u16 tci)
	in6_dev = in6_dev_get(netdev);
	if (!in6_dev)
		goto out;
	is_router = !!in6_dev->cnf.forwarding;
	is_router = !!READ_ONCE(in6_dev->cnf.forwarding);
	in6_dev_put(in6_dev);

	/* ipv6_stub != NULL if in6_dev_get returned an inet6_dev */
+5 −3
Original line number Diff line number Diff line
@@ -534,13 +534,15 @@ static inline int ipv6_hopopt_jumbo_remove(struct sk_buff *skb)
	return 0;
}

static inline bool ipv6_accept_ra(struct inet6_dev *idev)
static inline bool ipv6_accept_ra(const struct inet6_dev *idev)
{
	s32 accept_ra = READ_ONCE(idev->cnf.accept_ra);

	/* If forwarding is enabled, RA are not accepted unless the special
	 * hybrid mode (accept_ra=2) is enabled.
	 */
	return idev->cnf.forwarding ? idev->cnf.accept_ra == 2 :
	    idev->cnf.accept_ra;
	return READ_ONCE(idev->cnf.forwarding) ? accept_ra == 2 :
		accept_ra;
}

#define IPV6_FRAG_HIGH_THRESH	(4 * 1024*1024)	/* 4194304 */
+1 −1
Original line number Diff line number Diff line
@@ -5988,7 +5988,7 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
		return -ENODEV;

	idev = __in6_dev_get_safely(dev);
	if (unlikely(!idev || !idev->cnf.forwarding))
	if (unlikely(!idev || !READ_ONCE(idev->cnf.forwarding)))
		return BPF_FIB_LKUP_RET_FWD_DISABLED;

	if (flags & BPF_FIB_LOOKUP_OUTPUT) {
+6 −4
Original line number Diff line number Diff line
@@ -551,7 +551,8 @@ static int inet6_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
		goto out;

	if ((all || type == NETCONFA_FORWARDING) &&
	    nla_put_s32(skb, NETCONFA_FORWARDING, devconf->forwarding) < 0)
	    nla_put_s32(skb, NETCONFA_FORWARDING,
			READ_ONCE(devconf->forwarding)) < 0)
		goto nla_put_failure;
#ifdef CONFIG_IPV6_MROUTE
	if ((all || type == NETCONFA_MC_FORWARDING) &&
@@ -869,7 +870,8 @@ static void addrconf_forward_change(struct net *net, __s32 newf)
		idev = __in6_dev_get(dev);
		if (idev) {
			int changed = (!idev->cnf.forwarding) ^ (!newf);
			idev->cnf.forwarding = newf;

			WRITE_ONCE(idev->cnf.forwarding, newf);
			if (changed)
				dev_forward_change(idev);
		}
@@ -886,7 +888,7 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf)

	net = (struct net *)table->extra2;
	old = *p;
	*p = newf;
	WRITE_ONCE(*p, newf);

	if (p == &net->ipv6.devconf_dflt->forwarding) {
		if ((!newf) ^ (!old))
@@ -901,7 +903,7 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf)
	if (p == &net->ipv6.devconf_all->forwarding) {
		int old_dflt = net->ipv6.devconf_dflt->forwarding;

		net->ipv6.devconf_dflt->forwarding = newf;
		WRITE_ONCE(net->ipv6.devconf_dflt->forwarding, newf);
		if ((!newf) ^ (!old_dflt))
			inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
						     NETCONFA_FORWARDING,
+1 −1
Original line number Diff line number Diff line
@@ -501,7 +501,7 @@ int ip6_forward(struct sk_buff *skb)
	u32 mtu;

	idev = __in6_dev_get_safely(dev_get_by_index_rcu(net, IP6CB(skb)->iif));
	if (net->ipv6.devconf_all->forwarding == 0)
	if (READ_ONCE(net->ipv6.devconf_all->forwarding) == 0)
		goto error;

	if (skb->pkt_type != PACKET_HOST)
Loading