From: Dong Chenchen <dongchenchen2@huawei.com>
To: <pablo@netfilter.org>, <laforge@gnumonks.org>,
<andrew+netdev@lunn.ch>, <davem@davemloft.net>,
<edumazet@google.com>, <kuba@kernel.org>, <pabeni@redhat.com>,
<horms@kernel.org>
Cc: <dsahern@kernel.org>, <kees@kernel.org>, <netdev@vger.kernel.org>,
<zhangchangzhong@huawei.com>,
Dong Chenchen <dongchenchen2@huawei.com>,
<syzbot+83181a31faf9455499c5@syzkaller.appspotmail.com>
Subject: [PATCH net v3] net: iptunnel: fix stale transport header during tunnel decapsulation
Date: Tue, 25 Aug 2026 20:39:09 +0800 [thread overview]
Message-ID: <20260825123909.1463121-1-dongchenchen2@huawei.com> (raw)
Syzbot reported a crash in qdisc_pkt_len_segs_init() caused by a stale
transport_header offset after tunnel decapsulation.
BUG: unable to handle page fault for address: ffffed102091a42e
Oops: Oops: 0000 [#1] SMP KASAN NOPTI
CPU: 0 UID: 0 PID: 340 Comm: qdisc_uaf_repro Not tainted 7.2.0-rc4-00061-g248951ddc14d #256 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
RIP: 0010:__asan_load2
<IRQ>
qdisc_pkt_len_segs_init (net/core/dev.c:4145)
__dev_queue_xmit (net/core/dev.c:4787)
br_dev_queue_push_xmit (net/bridge/br_forward.c:53)
br_handle_frame_finish (net/bridge/br_input.c:229)
br_handle_frame (net/bridge/br_input.c:315)
__netif_receive_skb_core.constprop.0 (net/core/dev.c:6099)
__netif_receive_skb_list_core (net/core/dev.c:6287)
netif_receive_skb_list_internal (net/core/dev.c:6445)
napi_complete_done (net/core/dev.c:6813)
gro_cell_poll (net/core/gro_cells.c:74)
__napi_poll (net/core/dev.c:7735)
net_rx_action (net/core/dev.c:7798 net/core/dev.c:7955)
handle_softirqs (kernel/softirq.c:622)
do_softirq (kernel/softirq.c:523 kernel/softirq.c:510 )
__local_bh_enable_ip (kernel/softirq.c:450)
tun_get_user (drivers/net/tun.c:1986 (discriminator 1))
tun_chr_write_iter (drivers/net/tun.c:2032)
The issue is completely latent until qdisc read transport header in
commit 7fb4c1967011 ("net: pull headers in qdisc_pkt_len_segs_init()").
The crash requires four conditions to line up:
1. The incoming packet is encapsulated and carries GSO metadata. The outer
transport header offset is stored in skb->transport_header while the
packet is still in the outer tunnel context.
2. The tunnel receiver strips the outer headers. skb->data is advanced to
the inner frame, but skb->transport_header is left pointing to the
now-removed outer L4 header, so it becomes a negative offset relative to
the new data.
3. The inner frame is not delivered to the local IP stack. Instead, it
is forwarded at L2 by a bridge or HSR, so ip_rcv_core() never runs and
the transport header is not reset to the inner L4 offset.
4. The forwarding path calls __dev_queue_xmit(), which enters
qdisc_pkt_len_segs_init(). That function computes the GSO header length
from skb_transport_offset(skb). Because the offset is negative, the
unsigned cast overflows and pskb_may_pull(skb, hdr_len +
sizeof(struct tcphdr)) reads past the end of the skb, triggering a
KASAN fault or page fault.
The issue specifically requires GSO packets (shinfo->gso_size != 0), which
are processed/aggregated through gro_cells. Fix this by clearing
transport_header to the ~0U sentinel in gro_cell for all tunnnel driver.
GTP does not support GRO/GSO, drop the evil GSO packets in GTP directly.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reported-by: syzbot+83181a31faf9455499c5@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/69de2bee.a00a0220.475f0.0041.GAE@google.com/T/
Suggested-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Dong Chenchen <dongchenchen2@huawei.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
---
v2: Consolidate scattered modifications into a common path.
v3: Correct spelling errors
---
drivers/net/gtp.c | 5 +++++
include/linux/skbuff.h | 5 +++++
net/core/gro_cells.c | 2 ++
3 files changed, 12 insertions(+)
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 9a12cc53da00..f6e47c369d62 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -312,6 +312,11 @@ static int gtp_inner_proto(struct sk_buff *skb, unsigned int hdrlen,
static int gtp_rx(struct pdp_ctx *pctx, struct sk_buff *skb,
unsigned int hdrlen, unsigned int role, __u16 inner_proto)
{
+ if (skb_is_gso(skb)) {
+ netdev_dbg(pctx->dev, "GSO is not supported in GTP\n");
+ goto err;
+ }
+
if (!gtp_check_ms(skb, pctx, hdrlen, role, inner_proto)) {
netdev_dbg(pctx->dev, "No PDP ctx for this MS\n");
return 1;
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 22eda1d54a0e..626bbb9bae1a 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -3082,6 +3082,11 @@ static inline bool skb_transport_header_was_set(const struct sk_buff *skb)
return skb->transport_header != (typeof(skb->transport_header))~0U;
}
+static inline void skb_unset_transport_header(struct sk_buff *skb)
+{
+ skb->transport_header = (typeof(skb->transport_header))~0U;
+}
+
static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
{
DEBUG_NET_WARN_ON_ONCE(!skb_transport_header_was_set(skb));
diff --git a/net/core/gro_cells.c b/net/core/gro_cells.c
index 1b84385c04bd..d8c0a2867120 100644
--- a/net/core/gro_cells.c
+++ b/net/core/gro_cells.c
@@ -22,6 +22,8 @@ int gro_cells_receive(struct gro_cells *gcells, struct sk_buff *skb)
if (unlikely(!(dev->flags & IFF_UP)))
goto drop;
+ skb_unset_transport_header(skb);
+
if (!gcells->cells || skb_cloned(skb) || netif_elide_gro(dev)) {
res = netif_rx(skb);
goto unlock;
--
2.25.1
next reply other threads:[~2026-08-25 12:30 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-25 12:39 Dong Chenchen [this message]
2026-08-28 23:10 ` [PATCH net v3] net: iptunnel: fix stale transport header during tunnel decapsulation patchwork-bot+netdevbpf
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=20260825123909.1463121-1-dongchenchen2@huawei.com \
--to=dongchenchen2@huawei.com \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=dsahern@kernel.org \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=kees@kernel.org \
--cc=kuba@kernel.org \
--cc=laforge@gnumonks.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=pablo@netfilter.org \
--cc=syzbot+83181a31faf9455499c5@syzkaller.appspotmail.com \
--cc=zhangchangzhong@huawei.com \
/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.