[PATCH] net: gre: complete lockless access to dev->needed_headroom

From: Xiaochen Zou
Date: Thu Jan 04 2024 - 18:28:11 EST


According to 4b397c06cb9 (net: tunnels: annotate lockless
accesses to dev->needed_headroom), we need to use lockless
access to protect dev->needed_headroom from data racing.
This patch complete the changes in ip(6)_gre.

More changes in other modules might be needed for completeness.

Signed-off-by: Xiaochen Zou <xzou017@xxxxxxx>
---
net/ipv4/ip_gre.c | 12 ++++++------
net/ipv6/ip6_gre.c | 12 ++++++------
2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 5169c3c72cff..8c979c421d79 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -491,7 +491,7 @@ static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,
key = &tun_info->key;
tunnel_hlen = gre_calc_hlen(key->tun_flags);

- if (skb_cow_head(skb, dev->needed_headroom))
+ if (skb_cow_head(skb, READ_ONCE(dev->needed_headroom)))
goto err_free_skb;

/* Push Tunnel header. */
@@ -541,7 +541,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
version = md->version;
tunnel_hlen = 8 + erspan_hdr_len(version);

- if (skb_cow_head(skb, dev->needed_headroom))
+ if (skb_cow_head(skb, READ_ONCE(dev->needed_headroom)))
goto err_free_skb;

if (gre_handle_offloads(skb, false))
@@ -653,7 +653,7 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
skb_checksum_start(skb) < skb->data)
goto free_skb;
} else {
- if (skb_cow_head(skb, dev->needed_headroom))
+ if (skb_cow_head(skb, READ_ONCE(dev->needed_headroom)))
goto free_skb;

tnl_params = &tunnel->parms.iph;
@@ -689,7 +689,7 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,
if (gre_handle_offloads(skb, false))
goto free_skb;

- if (skb_cow_head(skb, dev->needed_headroom))
+ if (skb_cow_head(skb, READ_ONCE(dev->needed_headroom)))
goto free_skb;

if (skb->len > dev->mtu + dev->hard_header_len) {
@@ -742,7 +742,7 @@ static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,
if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM)))
goto free_skb;

- if (skb_cow_head(skb, dev->needed_headroom))
+ if (skb_cow_head(skb, READ_ONCE(dev->needed_headroom)))
goto free_skb;

__gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB));
@@ -768,7 +768,7 @@ static void ipgre_link_update(struct net_device *dev, bool set_mtu)
if (dev->header_ops)
dev->hard_header_len += len;
else
- dev->needed_headroom += len;
+ WRITE_ONCE(dev->needed_headroom, dev->needed_headroom + len);

if (set_mtu)
dev->mtu = max_t(int, dev->mtu - len, 68);
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 070d87abf7c0..8c060591641d 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -782,7 +782,7 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
(TUNNEL_CSUM | TUNNEL_KEY | TUNNEL_SEQ);
tun_hlen = gre_calc_hlen(flags);

- if (skb_cow_head(skb, dev->needed_headroom ?: tun_hlen + tunnel->encap_hlen))
+ if (skb_cow_head(skb, READ_ONCE(dev->needed_headroom) ?: tun_hlen + tunnel->encap_hlen))
return -ENOMEM;

gre_build_header(skb, tun_hlen,
@@ -792,7 +792,7 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
: 0);

} else {
- if (skb_cow_head(skb, dev->needed_headroom ?: tunnel->hlen))
+ if (skb_cow_head(skb, READ_ONCE(dev->needed_headroom) ?: tunnel->hlen))
return -ENOMEM;

flags = tunnel->parms.o_flags;
@@ -976,7 +976,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
truncate = true;
}

- if (skb_cow_head(skb, dev->needed_headroom ?: t->hlen))
+ if (skb_cow_head(skb, READ_ONCE(dev->needed_headroom) ?: t->hlen))
goto tx_err;

t->parms.o_flags &= ~TUNNEL_KEY;
@@ -1153,7 +1153,7 @@ static void ip6gre_tnl_link_config_route(struct ip6_tnl *t, int set_mtu,
if (t->dev->header_ops)
dev->hard_header_len = dst_len;
else
- dev->needed_headroom = dst_len;
+ WRITE_ONCE(dev->needed_headroom, dst_len);

if (set_mtu) {
int mtu = rt->dst.dev->mtu - t_hlen;
@@ -1184,7 +1184,7 @@ static int ip6gre_calc_hlen(struct ip6_tnl *tunnel)
if (tunnel->dev->header_ops)
tunnel->dev->hard_header_len = LL_MAX_HEADER + t_hlen;
else
- tunnel->dev->needed_headroom = LL_MAX_HEADER + t_hlen;
+ WRITE_ONCE(tunnel->dev->needed_headroom, LL_MAX_HEADER + t_hlen);

return t_hlen;
}
@@ -1864,7 +1864,7 @@ static int ip6erspan_calc_hlen(struct ip6_tnl *tunnel)
erspan_hdr_len(tunnel->parms.erspan_ver);

t_hlen = tunnel->hlen + sizeof(struct ipv6hdr);
- tunnel->dev->needed_headroom = LL_MAX_HEADER + t_hlen;
+ WRITE_ONCE(tunnel->dev->needed_headroom, LL_MAX_HEADER + t_hlen);
return t_hlen;
}

--
2.25.1