All of lore.kernel.org
 help / color / mirror / Atom feed
From: Fred Li <dracodingfly@gmail.com>
To: willemdebruijn.kernel@gmail.com
Cc: aleksander.lobakin@intel.com, andrii@kernel.org, ast@kernel.org,
	bpf@vger.kernel.org, daniel@iogearbox.net, davem@davemloft.net,
	dracodingfly@gmail.com, edumazet@google.com, haoluo@google.com,
	hawk@kernel.org, herbert@gondor.apana.org.au,
	john.fastabend@gmail.com, jolsa@kernel.org, kpsingh@kernel.org,
	kuba@kernel.org, linux-kernel@vger.kernel.org,
	linux@weissschuh.net, martin.lau@linux.dev,
	mkhalfella@purestorage.com, nbd@nbd.name, netdev@vger.kernel.org,
	pabeni@redhat.com, sashal@kernel.org, sdf@google.com,
	song@kernel.org, yonghong.song@linux.dev
Subject: [PATCH] net: linearizing skb when downgrade gso_size
Date: Mon,  8 Jul 2024 22:31:28 +0800	[thread overview]
Message-ID: <20240708143128.49949-1-dracodingfly@gmail.com> (raw)
In-Reply-To: <6689541517901_12869e29412@willemb.c.googlers.com.notmuch>

Here is a patch that linearizing skb when downgrade
gso_size and sg should disabled, If there are no issues,
I will submit a formal patch shortly.

Signed-off-by: Fred Li <dracodingfly@gmail.com>
---
 include/linux/skbuff.h | 22 ++++++++++++++++++++++
 net/core/filter.c      | 16 ++++++++++++----
 net/core/skbuff.c      | 19 ++-----------------
 3 files changed, 36 insertions(+), 21 deletions(-)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 5f11f9873341..99b7fc1e826a 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -2400,6 +2400,28 @@ static inline unsigned int skb_headlen(const struct sk_buff *skb)
 	return skb->len - skb->data_len;
 }
 
+static inline bool skb_is_nonsg(const struct sk_buff *skb)
+{
+	struct sk_buff *list_skb = skb_shinfo(skb)->frag_list;
+	struct sk_buff *check_skb;
+	for (check_skb = list_skb; check_skb; check_skb = check_skb->next) {
+		if (skb_headlen(check_skb) && !check_skb->head_frag) {
+			/* gso_size is untrusted, and we have a frag_list with
+                         * a linear non head_frag item.
+                         *
+                         * If head_skb's headlen does not fit requested gso_size,
+                         * it means that the frag_list members do NOT terminate
+                         * on exact gso_size boundaries. Hence we cannot perform
+                         * skb_frag_t page sharing. Therefore we must fallback to
+                         * copying the frag_list skbs; we do so by disabling SG.
+                         */
+			return true;
+		}
+	}
+
+	return false;
+}
+
 static inline unsigned int __skb_pagelen(const struct sk_buff *skb)
 {
 	unsigned int i, len = 0;
diff --git a/net/core/filter.c b/net/core/filter.c
index df4578219e82..c0e6e7f28635 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3525,13 +3525,21 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 off, u32 len_diff,
 	if (skb_is_gso(skb)) {
 		struct skb_shared_info *shinfo = skb_shinfo(skb);
 
-		/* Due to header grow, MSS needs to be downgraded. */
-		if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO))
-			skb_decrease_gso_size(shinfo, len_diff);
-
 		/* Header must be checked, and gso_segs recomputed. */
 		shinfo->gso_type |= gso_type;
 		shinfo->gso_segs = 0;
+
+		/* Due to header grow, MSS needs to be downgraded.
+		 * There is BUG_ON When segment the frag_list with
+		 * head_frag true so linearize skb after downgrade
+		 * the MSS.
+		 */
+		if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO)) {
+			skb_decrease_gso_size(shinfo, len_diff);
+			if (skb_is_nonsg(skb))
+				return skb_linearize(skb) ? : 0;
+		}
+
 	}
 
 	return 0;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index b1dab1b071fc..81e018185527 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -4458,23 +4458,8 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
 
 	if ((skb_shinfo(head_skb)->gso_type & SKB_GSO_DODGY) &&
 	    mss != GSO_BY_FRAGS && mss != skb_headlen(head_skb)) {
-		struct sk_buff *check_skb;
-
-		for (check_skb = list_skb; check_skb; check_skb = check_skb->next) {
-			if (skb_headlen(check_skb) && !check_skb->head_frag) {
-				/* gso_size is untrusted, and we have a frag_list with
-				 * a linear non head_frag item.
-				 *
-				 * If head_skb's headlen does not fit requested gso_size,
-				 * it means that the frag_list members do NOT terminate
-				 * on exact gso_size boundaries. Hence we cannot perform
-				 * skb_frag_t page sharing. Therefore we must fallback to
-				 * copying the frag_list skbs; we do so by disabling SG.
-				 */
-				features &= ~NETIF_F_SG;
-				break;
-			}
-		}
+		if (skb_is_nonsg(head_skb))
+			features &= ~NETIF_F_SG;
 	}
 
 	__skb_push(head_skb, doffset);
-- 
2.33.0


  reply	other threads:[~2024-07-08 14:31 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-06-26  6:55 [PATCH v2 2/2] test_bpf: Introduce an skb_segment test for frag_list whose head_frag=true and gso_size was mangled Fred Li
2024-06-26  6:55 ` [PATCH v2 1/2] net: Fix skb_segment when splitting gso_size mangled skb having linear-headed frag_list whose head_frag=true Fred Li
2024-07-02  9:23   ` Paolo Abeni
2024-07-03 12:21     ` Fred Li
2024-07-06 14:26       ` Willem de Bruijn
2024-07-08 14:31         ` Fred Li [this message]
2024-07-09 15:53           ` [PATCH] net: linearizing skb when downgrade gso_size Willem de Bruijn
2024-07-09 20:16             ` Herbert Xu
2024-07-09 21:29               ` Willem de Bruijn
2024-07-10 23:06                 ` Herbert Xu
2024-07-12  8:17             ` Fred Li
2024-07-17  5:35         ` [PATCH v3] " Fred Li
2024-07-17 16:32           ` Willem de Bruijn
2024-07-18  7:42             ` Fred Li
2024-07-19  2:46         ` [PATCH v4] bpf: Fixed a segment issue " Fred Li
2024-07-19 18:22           ` Willem de Bruijn
2024-07-23  1:12           ` bot+bpf-ci
2024-07-22  3:08         ` [PATCH bpf v5] bpf: Fixed " Fred Li
2024-07-22  3:34           ` bot+bpf-ci
2024-07-22 16:29           ` Willem de Bruijn
2024-07-24 13:37             ` Fred Li
2024-07-25 10:09               ` Daniel Borkmann
2024-06-26  6:55 ` [PATCH v2 0/2] net: Fix BUG_ON for segment frag_list with mangled gso_size and head_frag is true Fred Li

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240708143128.49949-1-dracodingfly@gmail.com \
    --to=dracodingfly@gmail.com \
    --cc=aleksander.lobakin@intel.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=haoluo@google.com \
    --cc=hawk@kernel.org \
    --cc=herbert@gondor.apana.org.au \
    --cc=john.fastabend@gmail.com \
    --cc=jolsa@kernel.org \
    --cc=kpsingh@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@weissschuh.net \
    --cc=martin.lau@linux.dev \
    --cc=mkhalfella@purestorage.com \
    --cc=nbd@nbd.name \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=sashal@kernel.org \
    --cc=sdf@google.com \
    --cc=song@kernel.org \
    --cc=willemdebruijn.kernel@gmail.com \
    --cc=yonghong.song@linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.