Commit ddea75d3 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

ipv6: annotate data-races in ndisc_router_discovery()

Annotate reads from in6_dev->cnf.XXX fields, as they could
change concurrently.
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 32f75417
...@@ -1319,7 +1319,7 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb) ...@@ -1319,7 +1319,7 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb)
if (old_if_flags != in6_dev->if_flags) if (old_if_flags != in6_dev->if_flags)
send_ifinfo_notify = true; send_ifinfo_notify = true;
if (!in6_dev->cnf.accept_ra_defrtr) { if (!READ_ONCE(in6_dev->cnf.accept_ra_defrtr)) {
ND_PRINTK(2, info, ND_PRINTK(2, info,
"RA: %s, defrtr is false for dev: %s\n", "RA: %s, defrtr is false for dev: %s\n",
__func__, skb->dev->name); __func__, skb->dev->name);
...@@ -1327,7 +1327,8 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb) ...@@ -1327,7 +1327,8 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb)
} }
lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime); lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime);
if (lifetime != 0 && lifetime < in6_dev->cnf.accept_ra_min_lft) { if (lifetime != 0 &&
lifetime < READ_ONCE(in6_dev->cnf.accept_ra_min_lft)) {
ND_PRINTK(2, info, ND_PRINTK(2, info,
"RA: router lifetime (%ds) is too short: %s\n", "RA: router lifetime (%ds) is too short: %s\n",
lifetime, skb->dev->name); lifetime, skb->dev->name);
...@@ -1338,7 +1339,7 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb) ...@@ -1338,7 +1339,7 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb)
* accept_ra_from_local is set to true. * accept_ra_from_local is set to true.
*/ */
net = dev_net(in6_dev->dev); net = dev_net(in6_dev->dev);
if (!in6_dev->cnf.accept_ra_from_local && if (!READ_ONCE(in6_dev->cnf.accept_ra_from_local) &&
ipv6_chk_addr(net, &ipv6_hdr(skb)->saddr, in6_dev->dev, 0)) { ipv6_chk_addr(net, &ipv6_hdr(skb)->saddr, in6_dev->dev, 0)) {
ND_PRINTK(2, info, ND_PRINTK(2, info,
"RA from local address detected on dev: %s: default router ignored\n", "RA from local address detected on dev: %s: default router ignored\n",
...@@ -1350,7 +1351,7 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb) ...@@ -1350,7 +1351,7 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb)
pref = ra_msg->icmph.icmp6_router_pref; pref = ra_msg->icmph.icmp6_router_pref;
/* 10b is handled as if it were 00b (medium) */ /* 10b is handled as if it were 00b (medium) */
if (pref == ICMPV6_ROUTER_PREF_INVALID || if (pref == ICMPV6_ROUTER_PREF_INVALID ||
!in6_dev->cnf.accept_ra_rtr_pref) !READ_ONCE(in6_dev->cnf.accept_ra_rtr_pref))
pref = ICMPV6_ROUTER_PREF_MEDIUM; pref = ICMPV6_ROUTER_PREF_MEDIUM;
#endif #endif
/* routes added from RAs do not use nexthop objects */ /* routes added from RAs do not use nexthop objects */
...@@ -1421,10 +1422,12 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb) ...@@ -1421,10 +1422,12 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb)
spin_unlock_bh(&table->tb6_lock); spin_unlock_bh(&table->tb6_lock);
} }
if (in6_dev->cnf.accept_ra_min_hop_limit < 256 && if (READ_ONCE(in6_dev->cnf.accept_ra_min_hop_limit) < 256 &&
ra_msg->icmph.icmp6_hop_limit) { ra_msg->icmph.icmp6_hop_limit) {
if (in6_dev->cnf.accept_ra_min_hop_limit <= ra_msg->icmph.icmp6_hop_limit) { if (READ_ONCE(in6_dev->cnf.accept_ra_min_hop_limit) <=
WRITE_ONCE(in6_dev->cnf.hop_limit, ra_msg->icmph.icmp6_hop_limit); ra_msg->icmph.icmp6_hop_limit) {
WRITE_ONCE(in6_dev->cnf.hop_limit,
ra_msg->icmph.icmp6_hop_limit);
fib6_metric_set(rt, RTAX_HOPLIMIT, fib6_metric_set(rt, RTAX_HOPLIMIT,
ra_msg->icmph.icmp6_hop_limit); ra_msg->icmph.icmp6_hop_limit);
} else { } else {
...@@ -1506,7 +1509,7 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb) ...@@ -1506,7 +1509,7 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb)
} }
#ifdef CONFIG_IPV6_ROUTE_INFO #ifdef CONFIG_IPV6_ROUTE_INFO
if (!in6_dev->cnf.accept_ra_from_local && if (!READ_ONCE(in6_dev->cnf.accept_ra_from_local) &&
ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr, ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr,
in6_dev->dev, 0)) { in6_dev->dev, 0)) {
ND_PRINTK(2, info, ND_PRINTK(2, info,
...@@ -1515,7 +1518,7 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb) ...@@ -1515,7 +1518,7 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb)
goto skip_routeinfo; goto skip_routeinfo;
} }
if (in6_dev->cnf.accept_ra_rtr_pref && ndopts.nd_opts_ri) { if (READ_ONCE(in6_dev->cnf.accept_ra_rtr_pref) && ndopts.nd_opts_ri) {
struct nd_opt_hdr *p; struct nd_opt_hdr *p;
for (p = ndopts.nd_opts_ri; for (p = ndopts.nd_opts_ri;
p; p;
...@@ -1527,14 +1530,14 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb) ...@@ -1527,14 +1530,14 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb)
continue; continue;
#endif #endif
if (ri->prefix_len == 0 && if (ri->prefix_len == 0 &&
!in6_dev->cnf.accept_ra_defrtr) !READ_ONCE(in6_dev->cnf.accept_ra_defrtr))
continue; continue;
if (ri->lifetime != 0 && if (ri->lifetime != 0 &&
ntohl(ri->lifetime) < in6_dev->cnf.accept_ra_min_lft) ntohl(ri->lifetime) < READ_ONCE(in6_dev->cnf.accept_ra_min_lft))
continue; continue;
if (ri->prefix_len < in6_dev->cnf.accept_ra_rt_info_min_plen) if (ri->prefix_len < READ_ONCE(in6_dev->cnf.accept_ra_rt_info_min_plen))
continue; continue;
if (ri->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen) if (ri->prefix_len > READ_ONCE(in6_dev->cnf.accept_ra_rt_info_max_plen))
continue; continue;
rt6_route_rcv(skb->dev, (u8 *)p, (p->nd_opt_len) << 3, rt6_route_rcv(skb->dev, (u8 *)p, (p->nd_opt_len) << 3,
&ipv6_hdr(skb)->saddr); &ipv6_hdr(skb)->saddr);
...@@ -1554,7 +1557,7 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb) ...@@ -1554,7 +1557,7 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb)
} }
#endif #endif
if (in6_dev->cnf.accept_ra_pinfo && ndopts.nd_opts_pi) { if (READ_ONCE(in6_dev->cnf.accept_ra_pinfo) && ndopts.nd_opts_pi) {
struct nd_opt_hdr *p; struct nd_opt_hdr *p;
for (p = ndopts.nd_opts_pi; for (p = ndopts.nd_opts_pi;
p; p;
...@@ -1565,7 +1568,7 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb) ...@@ -1565,7 +1568,7 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb)
} }
} }
if (ndopts.nd_opts_mtu && in6_dev->cnf.accept_ra_mtu) { if (ndopts.nd_opts_mtu && READ_ONCE(in6_dev->cnf.accept_ra_mtu)) {
__be32 n; __be32 n;
u32 mtu; u32 mtu;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment