ipv6: annotate data-races around cnf.mtu6
[linux-block.git] / net / ipv6 / ndisc.c
index a19999b30bc07d50a83c41d5a985a69cf565db08..e96d79cd34d27ca304c5f71b6db41b99d2dd8856 100644 (file)
@@ -1237,6 +1237,7 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb)
        struct ndisc_options ndopts;
        struct fib6_info *rt = NULL;
        struct inet6_dev *in6_dev;
+       struct fib6_table *table;
        u32 defrtr_usr_metric;
        unsigned int pref = 0;
        __u32 old_if_flags;
@@ -1382,7 +1383,8 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb)
                        neigh_release(neigh);
 
                rt = rt6_add_dflt_router(net, &ipv6_hdr(skb)->saddr,
-                                        skb->dev, pref, defrtr_usr_metric);
+                                        skb->dev, pref, defrtr_usr_metric,
+                                        lifetime);
                if (!rt) {
                        ND_PRINTK(0, err,
                                  "RA: %s failed to add default route\n",
@@ -1409,8 +1411,15 @@ static enum skb_drop_reason ndisc_router_discovery(struct sk_buff *skb)
                inet6_rt_notify(RTM_NEWROUTE, rt, &nlinfo, NLM_F_REPLACE);
        }
 
-       if (rt)
+       if (rt) {
+               table = rt->fib6_table;
+               spin_lock_bh(&table->tb6_lock);
+
                fib6_set_expires(rt, jiffies + (HZ * lifetime));
+               fib6_add_gc_list(rt);
+
+               spin_unlock_bh(&table->tb6_lock);
+       }
        if (in6_dev->cnf.accept_ra_min_hop_limit < 256 &&
            ra_msg->icmph.icmp6_hop_limit) {
                if (in6_dev->cnf.accept_ra_min_hop_limit <= ra_msg->icmph.icmp6_hop_limit) {
@@ -1569,8 +1578,8 @@ skip_routeinfo:
 
                if (mtu < IPV6_MIN_MTU || mtu > skb->dev->mtu) {
                        ND_PRINTK(2, warn, "RA: invalid mtu: %d\n", mtu);
-               } else if (in6_dev->cnf.mtu6 != mtu) {
-                       in6_dev->cnf.mtu6 = mtu;
+               } else if (READ_ONCE(in6_dev->cnf.mtu6) != mtu) {
+                       WRITE_ONCE(in6_dev->cnf.mtu6, mtu);
                        fib6_metric_set(rt, RTAX_MTU, mtu);
                        rt6_mtu_change(skb->dev, mtu);
                }
@@ -1966,7 +1975,7 @@ int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, void *buffer,
                if (ctl->data == &NEIGH_VAR(idev->nd_parms, BASE_REACHABLE_TIME))
                        idev->nd_parms->reachable_time =
                                        neigh_rand_reach_time(NEIGH_VAR(idev->nd_parms, BASE_REACHABLE_TIME));
-               idev->tstamp = jiffies;
+               WRITE_ONCE(idev->tstamp, jiffies);
                inet6_ifinfo_notify(RTM_NEWLINK, idev);
                in6_dev_put(idev);
        }