Skip to content

Commit 32f7541

Browse files
edumazetdavem330
authored andcommitted
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: Eric Dumazet <edumazet@google.com> Reviewed-by: Jiri Pirko <jiri@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent e0bb267 commit 32f7541

7 files changed

Lines changed: 22 additions & 17 deletions

File tree

drivers/net/usb/cdc_mbim.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ static void do_neigh_solicit(struct usbnet *dev, u8 *buf, u16 tci)
339339
in6_dev = in6_dev_get(netdev);
340340
if (!in6_dev)
341341
goto out;
342-
is_router = !!in6_dev->cnf.forwarding;
342+
is_router = !!READ_ONCE(in6_dev->cnf.forwarding);
343343
in6_dev_put(in6_dev);
344344

345345
/* ipv6_stub != NULL if in6_dev_get returned an inet6_dev */

include/net/ipv6.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -534,13 +534,15 @@ static inline int ipv6_hopopt_jumbo_remove(struct sk_buff *skb)
534534
return 0;
535535
}
536536

537-
static inline bool ipv6_accept_ra(struct inet6_dev *idev)
537+
static inline bool ipv6_accept_ra(const struct inet6_dev *idev)
538538
{
539+
s32 accept_ra = READ_ONCE(idev->cnf.accept_ra);
540+
539541
/* If forwarding is enabled, RA are not accepted unless the special
540542
* hybrid mode (accept_ra=2) is enabled.
541543
*/
542-
return idev->cnf.forwarding ? idev->cnf.accept_ra == 2 :
543-
idev->cnf.accept_ra;
544+
return READ_ONCE(idev->cnf.forwarding) ? accept_ra == 2 :
545+
accept_ra;
544546
}
545547

546548
#define IPV6_FRAG_HIGH_THRESH (4 * 1024*1024) /* 4194304 */

net/core/filter.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5988,7 +5988,7 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
59885988
return -ENODEV;
59895989

59905990
idev = __in6_dev_get_safely(dev);
5991-
if (unlikely(!idev || !idev->cnf.forwarding))
5991+
if (unlikely(!idev || !READ_ONCE(idev->cnf.forwarding)))
59925992
return BPF_FIB_LKUP_RET_FWD_DISABLED;
59935993

59945994
if (flags & BPF_FIB_LOOKUP_OUTPUT) {

net/ipv6/addrconf.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,8 @@ static int inet6_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
551551
goto out;
552552

553553
if ((all || type == NETCONFA_FORWARDING) &&
554-
nla_put_s32(skb, NETCONFA_FORWARDING, devconf->forwarding) < 0)
554+
nla_put_s32(skb, NETCONFA_FORWARDING,
555+
READ_ONCE(devconf->forwarding)) < 0)
555556
goto nla_put_failure;
556557
#ifdef CONFIG_IPV6_MROUTE
557558
if ((all || type == NETCONFA_MC_FORWARDING) &&
@@ -869,7 +870,8 @@ static void addrconf_forward_change(struct net *net, __s32 newf)
869870
idev = __in6_dev_get(dev);
870871
if (idev) {
871872
int changed = (!idev->cnf.forwarding) ^ (!newf);
872-
idev->cnf.forwarding = newf;
873+
874+
WRITE_ONCE(idev->cnf.forwarding, newf);
873875
if (changed)
874876
dev_forward_change(idev);
875877
}
@@ -886,7 +888,7 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf)
886888

887889
net = (struct net *)table->extra2;
888890
old = *p;
889-
*p = newf;
891+
WRITE_ONCE(*p, newf);
890892

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

904-
net->ipv6.devconf_dflt->forwarding = newf;
906+
WRITE_ONCE(net->ipv6.devconf_dflt->forwarding, newf);
905907
if ((!newf) ^ (!old_dflt))
906908
inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
907909
NETCONFA_FORWARDING,

net/ipv6/ip6_output.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ int ip6_forward(struct sk_buff *skb)
501501
u32 mtu;
502502

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

507507
if (skb->pkt_type != PACKET_HOST)

net/ipv6/ndisc.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -903,7 +903,7 @@ static enum skb_drop_reason ndisc_recv_ns(struct sk_buff *skb)
903903
}
904904

905905
if (ipv6_chk_acast_addr(net, dev, &msg->target) ||
906-
(idev->cnf.forwarding &&
906+
(READ_ONCE(idev->cnf.forwarding) &&
907907
(net->ipv6.devconf_all->proxy_ndp || idev->cnf.proxy_ndp) &&
908908
(is_router = pndisc_is_router(&msg->target, dev)) >= 0)) {
909909
if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) &&
@@ -929,7 +929,7 @@ static enum skb_drop_reason ndisc_recv_ns(struct sk_buff *skb)
929929
}
930930

931931
if (is_router < 0)
932-
is_router = idev->cnf.forwarding;
932+
is_router = READ_ONCE(idev->cnf.forwarding);
933933

934934
if (dad) {
935935
ndisc_send_na(dev, &in6addr_linklocal_allnodes, &msg->target,
@@ -1080,7 +1080,7 @@ static enum skb_drop_reason ndisc_recv_na(struct sk_buff *skb)
10801080
* Note that we don't do a (daddr == all-routers-mcast) check.
10811081
*/
10821082
new_state = msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE;
1083-
if (!neigh && lladdr && idev && idev->cnf.forwarding) {
1083+
if (!neigh && lladdr && idev && READ_ONCE(idev->cnf.forwarding)) {
10841084
if (accept_untracked_na(dev, saddr)) {
10851085
neigh = neigh_create(&nd_tbl, &msg->target, dev);
10861086
new_state = NUD_STALE;
@@ -1100,7 +1100,8 @@ static enum skb_drop_reason ndisc_recv_na(struct sk_buff *skb)
11001100
* has already sent a NA to us.
11011101
*/
11021102
if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) &&
1103-
net->ipv6.devconf_all->forwarding && net->ipv6.devconf_all->proxy_ndp &&
1103+
READ_ONCE(net->ipv6.devconf_all->forwarding) &&
1104+
net->ipv6.devconf_all->proxy_ndp &&
11041105
pneigh_lookup(&nd_tbl, net, &msg->target, dev, 0)) {
11051106
/* XXX: idev->cnf.proxy_ndp */
11061107
goto out;
@@ -1148,7 +1149,7 @@ static enum skb_drop_reason ndisc_recv_rs(struct sk_buff *skb)
11481149
}
11491150

11501151
/* Don't accept RS if we're not in router mode */
1151-
if (!idev->cnf.forwarding)
1152+
if (!READ_ONCE(idev->cnf.forwarding))
11521153
goto out;
11531154

11541155
/*

net/ipv6/route.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2220,7 +2220,7 @@ struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
22202220

22212221
strict |= flags & RT6_LOOKUP_F_IFACE;
22222222
strict |= flags & RT6_LOOKUP_F_IGNORE_LINKSTATE;
2223-
if (net->ipv6.devconf_all->forwarding == 0)
2223+
if (READ_ONCE(net->ipv6.devconf_all->forwarding) == 0)
22242224
strict |= RT6_LOOKUP_F_REACHABLE;
22252225

22262226
rcu_read_lock();
@@ -4149,7 +4149,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
41494149
in6_dev = __in6_dev_get(skb->dev);
41504150
if (!in6_dev)
41514151
return;
4152-
if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_redirects)
4152+
if (READ_ONCE(in6_dev->cnf.forwarding) || !in6_dev->cnf.accept_redirects)
41534153
return;
41544154

41554155
/* RFC2461 8.1:

0 commit comments

Comments
 (0)