]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ip6_tunnel: annotate data-races around t->err_count and t->err_time
authorEric Dumazet <edumazet@google.com>
Wed, 10 Jun 2026 17:14:58 +0000 (17:14 +0000)
committerJakub Kicinski <kuba@kernel.org>
Fri, 12 Jun 2026 02:12:40 +0000 (19:12 -0700)
ip6_tnl_xmit() and ipip6_tunnel_xmit() run locklessly (dev->lltx == true).

ip6gre_err() and ipip6_err() also run locklessly.

We need to add READ_ONCE() and WRITE_ONCE() annotations
around t->err_count and t->err_time.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20260610171458.1359630-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/ipv6/ip6_gre.c
net/ipv6/ip6_tunnel.c
net/ipv6/sit.c

index 48039f00b4bc4321c1502714a98dbf209a7ea398..795be59946f7210bfae55d20500d18c83c01ede9 100644 (file)
@@ -445,11 +445,11 @@ static int ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                return 0;
        }
 
-       if (time_before(jiffies, t->err_time + IP6TUNNEL_ERR_TIMEO))
-               t->err_count++;
+       if (time_before(jiffies, READ_ONCE(t->err_time) + IP6TUNNEL_ERR_TIMEO))
+               WRITE_ONCE(t->err_count, READ_ONCE(t->err_count) + 1);
        else
-               t->err_count = 1;
-       t->err_time = jiffies;
+               WRITE_ONCE(t->err_count, 1);
+       WRITE_ONCE(t->err_time, jiffies);
 
        return 0;
 }
index bf5cd5d4adcdfa86eb7a3c0a27db3cadb69499ae..73fc5a0b8203a0109bce022b46c92f31da674ae0 100644 (file)
@@ -1104,7 +1104,7 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
        struct ipv6_tel_txoption opt;
        struct dst_entry *dst = NULL, *ndst = NULL;
        struct net_device *tdev;
-       int mtu;
+       int err_count, mtu;
        unsigned int eth_hlen = t->dev->type == ARPHRD_ETHER ? ETH_HLEN : 0;
        unsigned int psh_hlen = sizeof(struct ipv6hdr) + t->encap_hlen;
        unsigned int max_headroom = psh_hlen;
@@ -1214,14 +1214,15 @@ route_lookup:
                goto tx_err_dst_release;
        }
 
-       if (t->err_count > 0) {
+       err_count = READ_ONCE(t->err_count);
+       if (err_count > 0) {
                if (time_before(jiffies,
-                               t->err_time + IP6TUNNEL_ERR_TIMEO)) {
-                       t->err_count--;
+                               READ_ONCE(t->err_time) + IP6TUNNEL_ERR_TIMEO)) {
+                       WRITE_ONCE(t->err_count, err_count - 1);
 
                        dst_link_failure(skb);
                } else {
-                       t->err_count = 0;
+                       WRITE_ONCE(t->err_count, 0);
                }
        }
 
index b41e231a669bec99cd15affcd85e66be328a281d..64f0d1b622d3f2f03b54fd4f51e3209f3a789e73 100644 (file)
@@ -595,11 +595,11 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
        if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
                goto out;
 
-       if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
-               t->err_count++;
+       if (time_before(jiffies, READ_ONCE(t->err_time) + IPTUNNEL_ERR_TIMEO))
+               WRITE_ONCE(t->err_count, READ_ONCE(t->err_count) + 1);
        else
-               t->err_count = 1;
-       t->err_time = jiffies;
+               WRITE_ONCE(t->err_count, 1);
+       WRITE_ONCE(t->err_time, jiffies);
 out:
        return err;
 }
@@ -909,8 +909,8 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
        struct net_device *tdev;        /* Device to other host */
        unsigned int max_headroom;      /* The extra header space needed */
        __be32 dst = tiph->daddr;
+       int err_count, mtu;
        struct flowi4 fl4;
-       int    mtu;
        u8 ttl;
        u8 protocol = IPPROTO_IPV6;
        int t_hlen = tunnel->hlen + sizeof(struct iphdr);
@@ -987,13 +987,15 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
                }
        }
 
-       if (tunnel->err_count > 0) {
+       err_count = READ_ONCE(tunnel->err_count);
+       if (err_count > 0) {
                if (time_before(jiffies,
-                               tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
-                       tunnel->err_count--;
+                               READ_ONCE(tunnel->err_time) + IPTUNNEL_ERR_TIMEO)) {
+                       WRITE_ONCE(tunnel->err_count, err_count - 1);
                        dst_link_failure(skb);
-               } else
-                       tunnel->err_count = 0;
+               } else {
+                       WRITE_ONCE(tunnel->err_count,  0);
+               }
        }
 
        /*