]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ipv6: annotate data-races in net/ipv6/route.c
authorEric Dumazet <edumazet@google.com>
Thu, 15 Jan 2026 09:41:41 +0000 (09:41 +0000)
committerJakub Kicinski <kuba@kernel.org>
Mon, 19 Jan 2026 17:56:43 +0000 (09:56 -0800)
sysctls are read while their values can change,
add READ_ONCE() annotations.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260115094141.3124990-9-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/ipv6/route.c

index ddeb9cd7f383739fdc1c73c1e5c824dd7de5fbea..3cfa7ae1294b59d14e030fb7a4ceabd4e9b673a8 100644 (file)
@@ -2895,7 +2895,7 @@ static void rt6_do_update_pmtu(struct rt6_info *rt, u32 mtu)
 
        dst_metric_set(&rt->dst, RTAX_MTU, mtu);
        rt->rt6i_flags |= RTF_MODIFIED;
-       rt6_update_expires(rt, net->ipv6.sysctl.ip6_rt_mtu_expires);
+       rt6_update_expires(rt, READ_ONCE(net->ipv6.sysctl.ip6_rt_mtu_expires));
 }
 
 static bool rt6_cache_allowed_for_pmtu(const struct rt6_info *rt)
@@ -3256,8 +3256,8 @@ static unsigned int ip6_default_advmss(const struct dst_entry *dst)
        rcu_read_lock();
 
        net = dst_dev_net_rcu(dst);
-       if (mtu < net->ipv6.sysctl.ip6_rt_min_advmss)
-               mtu = net->ipv6.sysctl.ip6_rt_min_advmss;
+       mtu = max_t(unsigned int, mtu,
+                   READ_ONCE(net->ipv6.sysctl.ip6_rt_min_advmss));
 
        rcu_read_unlock();
 
@@ -3359,10 +3359,10 @@ out:
 static void ip6_dst_gc(struct dst_ops *ops)
 {
        struct net *net = container_of(ops, struct net, ipv6.ip6_dst_ops);
-       int rt_min_interval = net->ipv6.sysctl.ip6_rt_gc_min_interval;
-       int rt_elasticity = net->ipv6.sysctl.ip6_rt_gc_elasticity;
-       int rt_gc_timeout = net->ipv6.sysctl.ip6_rt_gc_timeout;
-       unsigned long rt_last_gc = net->ipv6.ip6_rt_last_gc;
+       int rt_min_interval = READ_ONCE(net->ipv6.sysctl.ip6_rt_gc_min_interval);
+       int rt_elasticity = READ_ONCE(net->ipv6.sysctl.ip6_rt_gc_elasticity);
+       int rt_gc_timeout = READ_ONCE(net->ipv6.sysctl.ip6_rt_gc_timeout);
+       unsigned long rt_last_gc = READ_ONCE(net->ipv6.ip6_rt_last_gc);
        unsigned int val;
        int entries;
 
@@ -5005,7 +5005,7 @@ void rt6_sync_down_dev(struct net_device *dev, unsigned long event)
        };
        struct net *net = dev_net(dev);
 
-       if (net->ipv6.sysctl.skip_notify_on_dev_down)
+       if (READ_ONCE(net->ipv6.sysctl.skip_notify_on_dev_down))
                fib6_clean_all_skip_notify(net, fib6_ifdown, &arg);
        else
                fib6_clean_all(net, fib6_ifdown, &arg);
@@ -6405,6 +6405,7 @@ errout:
 void fib6_info_hw_flags_set(struct net *net, struct fib6_info *f6i,
                            bool offload, bool trap, bool offload_failed)
 {
+       u8 fib_notify_on_flag_change;
        struct sk_buff *skb;
        int err;
 
@@ -6416,8 +6417,9 @@ void fib6_info_hw_flags_set(struct net *net, struct fib6_info *f6i,
        WRITE_ONCE(f6i->offload, offload);
        WRITE_ONCE(f6i->trap, trap);
 
+       fib_notify_on_flag_change = READ_ONCE(net->ipv6.sysctl.fib_notify_on_flag_change);
        /* 2 means send notifications only if offload_failed was changed. */
-       if (net->ipv6.sysctl.fib_notify_on_flag_change == 2 &&
+       if (fib_notify_on_flag_change == 2 &&
            READ_ONCE(f6i->offload_failed) == offload_failed)
                return;
 
@@ -6429,7 +6431,7 @@ void fib6_info_hw_flags_set(struct net *net, struct fib6_info *f6i,
                 */
                return;
 
-       if (!net->ipv6.sysctl.fib_notify_on_flag_change)
+       if (!fib_notify_on_flag_change)
                return;
 
        skb = nlmsg_new(rt6_nlmsg_size(f6i), GFP_KERNEL);
@@ -6526,7 +6528,7 @@ static int ipv6_sysctl_rtcache_flush(const struct ctl_table *ctl, int write,
                return ret;
 
        net = (struct net *)ctl->extra1;
-       delay = net->ipv6.sysctl.flush_delay;
+       delay = READ_ONCE(net->ipv6.sysctl.flush_delay);
        fib6_run_gc(delay <= 0 ? 0 : (unsigned long)delay, net, delay > 0);
        return 0;
 }