diff mbox series

net: gre: complete lockless access to dev->needed_headroom

Message ID 20240104232714.619657-1-xzou017@ucr.edu (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series net: gre: complete lockless access to dev->needed_headroom | expand

Checks

Context Check Description
netdev/series_format warning Single patches do not need cover letters; Target tree name not specified in the subject
netdev/tree_selection success Guessed tree name to be net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 1113 this patch: 1113
netdev/cc_maintainers success CCed 5 of 5 maintainers
netdev/build_clang success Errors and warnings before: 1140 this patch: 1140
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 1140 this patch: 1140
netdev/checkpatch warning WARNING: line length of 104 exceeds 80 columns WARNING: line length of 81 exceeds 80 columns WARNING: line length of 87 exceeds 80 columns
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Xiaochen Zou Jan. 4, 2024, 11:27 p.m. UTC
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@ucr.edu>
---
 net/ipv4/ip_gre.c  | 12 ++++++------
 net/ipv6/ip6_gre.c | 12 ++++++------
 2 files changed, 12 insertions(+), 12 deletions(-)

Comments

Eric Dumazet Jan. 8, 2024, 10:18 a.m. UTC | #1
On Fri, Jan 5, 2024 at 12:26 AM Xiaochen Zou <xzou017@ucr.edu> wrote:
>
> 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@ucr.edu>
> ---
>  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);

Can the updates here happen while packets are in flight ?

ip6_tnl_xmit() updates definitely could happen while packets are in
flight, this is why we needed

if (max_headroom > READ_ONCE(dev->needed_headroom))
     WRITE_ONCE(dev->needed_headroom, max_headroom);

Do you have a KCSAN stack trace or something ?

Normally, dev->needed_headroom is only set at setup time,

Commit 8eb30be0352d ("ipv6: Create ip6_tnl_xmit") violated this rule.
diff mbox series

Patch

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;
 }