From: Weiming Shi <bestswngs@gmail.com>
To: "David S . Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Simon Horman <horms@kernel.org>,
Jamal Hadi Salim <jhs@mojatatu.com>,
Jiri Pirko <jiri@resnulli.us>, Shuah Khan <shuah@kernel.org>
Cc: netdev@vger.kernel.org, linux-kselftest@vger.kernel.org,
linux-kernel@vger.kernel.org, Xiang Mei <xmei5@asu.edu>,
co+1fe9b56e2c61be5e@bugs.sh, Weiming Shi <bestswngs@gmail.com>,
stable@vger.kernel.org
Subject: [PATCH 1/2] net: gso: validate TCP headers before segment length checks
Date: Mon, 28 Sep 2026 00:31:16 +0800 [thread overview]
Message-ID: <20260927163117.746432-2-bestswngs@gmail.com> (raw)
skb_gso_transport_seglen() derives the TCP header length with
tcp_hdrlen() or inner_tcp_hdrlen(). Both helpers dereference transport
header metadata without validating it first.
A TUN user can supply a TCP GSO packet without NEEDS_CSUM and with an
invalid IP header. The skb remains GSO while transport_header keeps the
unset sentinel. TBF and police can then reach the length validator and
read tcp->doff outside the skb head.
On the RX path, CONFIG_DEBUG_NET currently lets the unset marker survive
to ingress while non-debug builds still apply a temporary compatibility
reset. Validate the consumer instead of relying on that reset.
Validate TCP header ordering, linear bounds and fixed header presence
before either public GSO length check. For encapsulated TCP, validate the
inner offsets while allowing the outer and inner transport offsets to be
equal, as required by IPIP. Also validate the MAC header for the MAC
length variant.
Leave non-TCP GSO behavior unchanged. Those paths do not dereference a
TCP header, and valid FCoE skbs can have no transport header.
KASAN reports:
BUG: KASAN: slab-out-of-bounds in skb_gso_transport_seglen
Read of size 2 by task poc/133
skb_gso_transport_seglen (net/core/gso.c:155)
skb_gso_validate_mac_len (net/core/gso.c:270)
tbf_enqueue (net/sched/sch_tbf.c:260)
dev_qdisc_enqueue (net/core/dev.c:4227)
__dev_queue_xmit (net/core/dev.c:4884)
Cc: stable@vger.kernel.org
Fixes: 4d0820cf6a55 ("sch_tbf: handle too small burst")
Reported-by: <co+1fe9b56e2c61be5e@bugs.sh>
Assisted-by: LLM
Signed-off-by: Weiming Shi <bestswngs@gmail.com>
---
net/core/gso.c | 33 ++++++++++++++++++++++++++++++++-
1 file changed, 32 insertions(+), 1 deletion(-)
diff --git a/net/core/gso.c b/net/core/gso.c
index bcd156372f4df..7c76f721fe24e 100644
--- a/net/core/gso.c
+++ b/net/core/gso.c
@@ -240,6 +240,29 @@ static inline bool skb_gso_size_check(const struct sk_buff *skb,
return true;
}
+/* TCP segment length reads doff, so validate its header offsets first. */
+static bool skb_gso_tcp_header_valid(const struct sk_buff *skb)
+{
+ unsigned int transport = skb->transport_header;
+ unsigned int tail = skb_tail_pointer(skb) - skb->head;
+
+ if (!skb_is_gso_tcp(skb))
+ return true;
+
+ if (!skb_transport_header_was_set(skb) ||
+ transport <= skb->network_header || transport > tail)
+ return false;
+
+ if (skb->encapsulation) {
+ transport = skb->inner_transport_header;
+ if (transport <= skb->inner_network_header ||
+ transport < skb->transport_header || transport > tail)
+ return false;
+ }
+
+ return sizeof(struct tcphdr) <= tail - transport;
+}
+
/**
* skb_gso_validate_network_len - Will a split GSO skb fit into a given MTU?
*
@@ -252,6 +275,9 @@ static inline bool skb_gso_size_check(const struct sk_buff *skb,
*/
bool skb_gso_validate_network_len(const struct sk_buff *skb, unsigned int mtu)
{
+ if (unlikely(!skb_gso_tcp_header_valid(skb)))
+ return false;
+
return skb_gso_size_check(skb, skb_gso_network_seglen(skb), mtu);
}
EXPORT_SYMBOL_GPL(skb_gso_validate_network_len);
@@ -267,7 +293,12 @@ EXPORT_SYMBOL_GPL(skb_gso_validate_network_len);
*/
bool skb_gso_validate_mac_len(const struct sk_buff *skb, unsigned int len)
{
+ if (unlikely(!skb_gso_tcp_header_valid(skb) ||
+ (skb_is_gso_tcp(skb) &&
+ (!skb_mac_header_was_set(skb) ||
+ skb->transport_header <= skb->mac_header))))
+ return false;
+
return skb_gso_size_check(skb, skb_gso_mac_seglen(skb), len);
}
EXPORT_SYMBOL_GPL(skb_gso_validate_mac_len);
-
--
2.55.0
next reply other threads:[~2026-09-27 16:31 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-27 16:31 Weiming Shi [this message]
2026-09-27 16:31 ` [PATCH 2/2] selftests: tc-testing: cover unset TCP transport header in TBF Weiming Shi
2026-09-27 17:10 ` [PATCH 1/2] net: gso: validate TCP headers before segment length checks Eric Dumazet
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=20260927163117.746432-2-bestswngs@gmail.com \
--to=bestswngs@gmail.com \
--cc=co+1fe9b56e2c61be5e@bugs.sh \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=jhs@mojatatu.com \
--cc=jiri@resnulli.us \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=shuah@kernel.org \
--cc=stable@vger.kernel.org \
--cc=xmei5@asu.edu \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®