ip_tunnel_xmit() runs locklessly (dev->lltx == true). ipgre_err() and ipip_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 --- net/ipv4/ip_gre.c | 8 ++++---- net/ipv4/ip_tunnel.c | 13 ++++++++----- net/ipv4/ipip.c | 8 ++++---- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 169e2921a851d55bb67f5a7cf3f005ded1ed2655..208dd48012d963b9df0eddbdda73dd319930e48f 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -207,11 +207,11 @@ static int ipgre_err(struct sk_buff *skb, u32 info, if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) return 0; - 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); return 0; } diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 50d0f5fe4e4c6d83ef18cdea3ca25aed582839f0..9d114bd575f928b0ab46ef3007e456692d82b497 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -679,6 +679,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi4 fl4; bool md = false; bool connected; + int err_count; u8 tos, ttl; __be32 dst; __be16 df; @@ -807,14 +808,16 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, goto tx_error; } - 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); + } } tos = ip_tunnel_ecn_encap(tos, inner_iph, skb); diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index ff95b1b9908e9f4ba4bff207a5bd2c5d5670215a..4f89a03e0b49b8fb328077a68fb72d7e4f5768ca 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -190,11 +190,11 @@ static int ipip_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; -- 2.54.0.1136.gdb2ca164c4-goog