]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: dst: annotate data-races around dst->expires
authorEric Dumazet <edumazet@google.com>
Mon, 30 Jun 2025 12:19:26 +0000 (12:19 +0000)
committerJakub Kicinski <kuba@kernel.org>
Wed, 2 Jul 2025 21:32:29 +0000 (14:32 -0700)
(dst_entry)->expires is read and written locklessly,
add corresponding annotations.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Link: https://patch.msgid.link/20250630121934.3399505-3-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/net/dst.h
include/net/ip.h
net/ipv4/route.c
net/ipv6/route.c

index 76c30c3b22ddb8687348925d612798607377dff2..1efe1e5d51a904a0fe907687835b8e07f32afaec 100644 (file)
@@ -431,13 +431,15 @@ static inline void dst_link_failure(struct sk_buff *skb)
 
 static inline void dst_set_expires(struct dst_entry *dst, int timeout)
 {
-       unsigned long expires = jiffies + timeout;
+       unsigned long old, expires = jiffies + timeout;
 
        if (expires == 0)
                expires = 1;
 
-       if (dst->expires == 0 || time_before(expires, dst->expires))
-               dst->expires = expires;
+       old = READ_ONCE(dst->expires);
+
+       if (!old || time_before(expires, old))
+               WRITE_ONCE(dst->expires, expires);
 }
 
 static inline unsigned int dst_dev_overhead(struct dst_entry *dst,
index 375304bb99f690adb16b874abd9a562e17684f35..391af454422ebe25ba984398a2226f7ed88abe1d 100644 (file)
@@ -477,7 +477,7 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
            ip_mtu_locked(dst) ||
            !forwarding) {
                mtu = rt->rt_pmtu;
-               if (mtu && time_before(jiffies, rt->dst.expires))
+               if (mtu && time_before(jiffies, READ_ONCE(rt->dst.expires)))
                        goto out;
        }
 
index d32af8c167276781265b95542ef5b49d9d62d5ba..d7a534a5f1ff8bdaa81a14096f70ef3a83a1ab05 100644 (file)
@@ -844,7 +844,7 @@ static void ipv4_negative_advice(struct sock *sk,
 
        if ((READ_ONCE(dst->obsolete) > 0) ||
            (rt->rt_flags & RTCF_REDIRECTED) ||
-           rt->dst.expires)
+           READ_ONCE(rt->dst.expires))
                sk_dst_reset(sk);
 }
 
@@ -1033,7 +1033,8 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
        }
 
        if (rt->rt_pmtu == mtu && !lock &&
-           time_before(jiffies, dst->expires - net->ipv4.ip_rt_mtu_expires / 2))
+           time_before(jiffies, READ_ONCE(dst->expires) -
+                                net->ipv4.ip_rt_mtu_expires / 2))
                goto out;
 
        if (fib_lookup(net, fl4, &res, 0) == 0) {
@@ -3010,7 +3011,7 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src,
                }
        }
 
-       expires = rt->dst.expires;
+       expires = READ_ONCE(rt->dst.expires);
        if (expires) {
                unsigned long now = jiffies;
 
index ace2071f77bd1356a095b4d5056614b795d20b61..1014dcea1200cb4d4fc63f7b335fd2663c4844a3 100644 (file)
@@ -391,9 +391,8 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev)
 static bool __rt6_check_expired(const struct rt6_info *rt)
 {
        if (rt->rt6i_flags & RTF_EXPIRES)
-               return time_after(jiffies, rt->dst.expires);
-       else
-               return false;
+               return time_after(jiffies, READ_ONCE(rt->dst.expires));
+       return false;
 }
 
 static bool rt6_check_expired(const struct rt6_info *rt)
@@ -403,7 +402,7 @@ static bool rt6_check_expired(const struct rt6_info *rt)
        from = rcu_dereference(rt->from);
 
        if (rt->rt6i_flags & RTF_EXPIRES) {
-               if (time_after(jiffies, rt->dst.expires))
+               if (time_after(jiffies, READ_ONCE(rt->dst.expires)))
                        return true;
        } else if (from) {
                return READ_ONCE(rt->dst.obsolete) != DST_OBSOLETE_FORCE_CHK ||
@@ -2139,7 +2138,7 @@ static void rt6_age_examine_exception(struct rt6_exception_bucket *bucket,
                        rt6_remove_exception(bucket, rt6_ex);
                        return;
                }
-       } else if (time_after(jiffies, rt->dst.expires)) {
+       } else if (time_after(jiffies, READ_ONCE(rt->dst.expires))) {
                pr_debug("purging expired route %p\n", rt);
                rt6_remove_exception(bucket, rt6_ex);
                return;
@@ -2870,7 +2869,7 @@ static void rt6_update_expires(struct rt6_info *rt0, int timeout)
                rcu_read_lock();
                from = rcu_dereference(rt0->from);
                if (from)
-                       rt0->dst.expires = from->expires;
+                       WRITE_ONCE(rt0->dst.expires, from->expires);
                rcu_read_unlock();
        }
 
@@ -5903,7 +5902,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
        }
 
        if (rt6_flags & RTF_EXPIRES) {
-               expires = dst ? dst->expires : rt->expires;
+               expires = dst ? READ_ONCE(dst->expires) : rt->expires;
                expires -= jiffies;
        }