* [PATCH net v1 1/2] net: tunnel: fix stale transport header after GRE/TEB decap
@ 2026-04-16 3:46 Jiayuan Chen
2026-04-16 3:46 ` [PATCH net-next v1 2/2] net: add DEBUG_NET_WARN_ON_ONCE for negative transport offset Jiayuan Chen
2026-04-16 7:04 ` [syzbot ci] Re: net: tunnel: fix stale transport header after GRE/TEB decap syzbot ci
0 siblings, 2 replies; 4+ messages in thread
From: Jiayuan Chen @ 2026-04-16 3:46 UTC (permalink / raw)
To: netdev
Cc: Jiayuan Chen, syzbot+83181a31faf9455499c5, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
David Ahern, Pravin B Shelar, Tom Herbert, linux-kernel
syzbot reported a BUG.
I found that after GRE decapsulation in gretap/ip6gretap paths, the
transport_header becomes stale with a negative offset. The sequence is:
1. Before decap, transport_header points to the outer L4 (GRE) header.
2. __iptunnel_pull_header() calls skb_pull_rcsum() to advance skb->data
past the GRE header, but does not update transport_header.
3. For TEB (gretap/ip6gretap), eth_type_trans() in ip_tunnel_rcv() /
__ip6_tnl_rcv() further pulls ETH_HLEN (14 bytes) from skb->data.
After these two pulls, skb->data has moved forward while transport_header
still points to the old (now behind skb->data) position, resulting in a
negative skb_transport_offset(): typically -4 after GRE pull alone, or
-18 after GRE + inner Ethernet pull.
In the normal case where the inner frame is a recognizable protocol
(e.g., IPv4/TCP), inet_gro_receive() in net/ipv4/af_inet.c corrects the
transport_header via skb_set_transport_header() during GRO processing.
However, if the inner frame cannot be parsed (e.g., eth_type_trans()
classifies it as ETH_P_802_2 due to a zero/invalid inner Ethernet
header), no GRO callback resets the transport_header, and the stale
offset persists into __netif_receive_skb_core().
When this stale offset is combined with contradictory GSO metadata (e.g.,
SKB_GSO_TCPV4 injected via virtio_net_hdr from a tun device),
qdisc_pkt_len_segs_init() trusts the negative offset: the unsigned
wraparound makes pskb_may_pull() effectively a no-op, and __tcp_hdrlen()
then reads from an invalid memory location, causing a use-after-free.
Fix this by introducing iptunnel_rebuild_transport_header() which resets
and re-probes the transport header after tunnel decapsulation. If the
transport header cannot be rebuilt and the skb carries GSO metadata, the
inconsistent GSO fields are cleared to prevent downstream consumers from
trusting stale offsets.
reproducer: https://gist.github.com/mrpre/5ba943fd86367af748b70de99263da4b
Link: https://syzkaller.appspot.com/bug?extid=83181a31faf9455499c5
Fixes: c54419321455 ("GRE: Refactor GRE tunneling code.")
Fixes: 0d3c703a9d17 ("ipv6: Cleanup IPv6 tunnel receive path")
Reported-by: syzbot+83181a31faf9455499c5@syzkaller.appspotmail.com
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
---
include/net/ip_tunnels.h | 14 ++++++++++++++
net/ipv4/ip_tunnel.c | 2 ++
net/ipv6/ip6_tunnel.c | 2 ++
3 files changed, 18 insertions(+)
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index d708b66e55cd..f160d82e6196 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -662,6 +662,20 @@ static inline int iptunnel_pull_offloads(struct sk_buff *skb)
return 0;
}
+static inline void iptunnel_rebuild_transport_header(struct sk_buff *skb)
+{
+ skb->transport_header = (typeof(skb->transport_header))~0U;
+ skb_probe_transport_header(skb);
+
+ if (!skb_transport_header_was_set(skb) && skb_is_gso(skb)) {
+ struct skb_shared_info *shinfo = skb_shinfo(skb);
+
+ shinfo->gso_type = 0;
+ shinfo->gso_size = 0;
+ shinfo->gso_segs = 0;
+ }
+}
+
static inline void iptunnel_xmit_stats(struct net_device *dev, int pkt_len)
{
if (pkt_len > 0) {
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index 50d0f5fe4e4c..c46be68cfafa 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -445,6 +445,8 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
if (tun_dst)
skb_dst_set(skb, (struct dst_entry *)tun_dst);
+ iptunnel_rebuild_transport_header(skb);
+
gro_cells_receive(&tunnel->gro_cells, skb);
return 0;
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 46bc06506470..f95348cf3c77 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -879,6 +879,8 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,
if (tun_dst)
skb_dst_set(skb, (struct dst_entry *)tun_dst);
+ iptunnel_rebuild_transport_header(skb);
+
gro_cells_receive(&tunnel->gro_cells, skb);
return 0;
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH net-next v1 2/2] net: add DEBUG_NET_WARN_ON_ONCE for negative transport offset
2026-04-16 3:46 [PATCH net v1 1/2] net: tunnel: fix stale transport header after GRE/TEB decap Jiayuan Chen
@ 2026-04-16 3:46 ` Jiayuan Chen
2026-04-16 7:04 ` [syzbot ci] Re: net: tunnel: fix stale transport header after GRE/TEB decap syzbot ci
1 sibling, 0 replies; 4+ messages in thread
From: Jiayuan Chen @ 2026-04-16 3:46 UTC (permalink / raw)
To: netdev
Cc: Jiayuan Chen, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, David Ahern, Pravin B Shelar,
Tom Herbert, linux-kernel
skb_transport_offset() can silently return a negative
value when the transport_header becomes stale after tunnel
decapsulation. A negative offset is never valid — it means
transport_header points before skb->data, which will cause unsigned
wraparound in any caller that assigns the result to an unsigned
variable.
Add a DEBUG_NET_WARN_ON_ONCE(off < 0) check so that such cases are
caught early in CONFIG_DEBUG_NET=y builds (e.g., syzkaller, kernel test
bots) with a full stack trace pointing to the caller, rather than
silently propagating a bogus offset until something crashes downstream.
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
---
include/linux/skbuff.h | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 2bcf78a4de7b..0b1aeacc25f7 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -3234,7 +3234,10 @@ static inline unsigned char *skb_checksum_start(const struct sk_buff *skb)
static inline int skb_transport_offset(const struct sk_buff *skb)
{
- return skb_transport_header(skb) - skb->data;
+ int off = skb_transport_header(skb) - skb->data;
+
+ DEBUG_NET_WARN_ON_ONCE(off < 0);
+ return off;
}
static inline u32 skb_network_header_len(const struct sk_buff *skb)
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [syzbot ci] Re: net: tunnel: fix stale transport header after GRE/TEB decap
2026-04-16 3:46 [PATCH net v1 1/2] net: tunnel: fix stale transport header after GRE/TEB decap Jiayuan Chen
2026-04-16 3:46 ` [PATCH net-next v1 2/2] net: add DEBUG_NET_WARN_ON_ONCE for negative transport offset Jiayuan Chen
@ 2026-04-16 7:04 ` syzbot ci
2026-04-16 7:49 ` Jiayuan Chen
1 sibling, 1 reply; 4+ messages in thread
From: syzbot ci @ 2026-04-16 7:04 UTC (permalink / raw)
To: davem, dsahern, edumazet, horms, jiayuan.chen, kuba, linux-kernel,
netdev, pabeni, pshelar, syzbot, tom
Cc: syzbot, syzkaller-bugs
syzbot ci has tested the following series
[v1] net: tunnel: fix stale transport header after GRE/TEB decap
https://lore.kernel.org/all/20260416034610.8873-1-jiayuan.chen@linux.dev
* [PATCH net v1 1/2] net: tunnel: fix stale transport header after GRE/TEB decap
* [PATCH net-next v1 2/2] net: add DEBUG_NET_WARN_ON_ONCE for negative transport offset
and found the following issue:
WARNING in udpv6_err
Full report is available here:
https://ci.syzbot.org/series/3886f2f1-a6d5-4c5c-8dc8-bc1cec577567
***
WARNING in udpv6_err
tree: net
URL: https://kernel.googlesource.com/pub/scm/linux/kernel/git/netdev/net.git
base: 1f5ffc672165ff851063a5fd044b727ab2517ae3
arch: amd64
compiler: Debian clang version 21.1.8 (++20251221033036+2078da43e25a-1~exp1~20251221153213.50), Debian LLD 21.1.8
config: https://ci.syzbot.org/builds/06cf41a2-60fe-4f9b-8f68-57eb6d1e48cc/config
------------[ cut here ]------------
off < 0
WARNING: ./include/linux/skbuff.h:3239 at udpv6_err+0x1521/0x16d0, CPU#0: kworker/u9:2/51
Modules linked in:
CPU: 0 UID: 0 PID: 51 Comm: kworker/u9:2 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
Workqueue: wg-kex-wg0 wg_packet_handshake_send_worker
RIP: 0010:udpv6_err+0x1521/0x16d0
Code: f7 b0 01 89 44 24 30 49 bf 00 00 00 00 00 fc ff df e9 ea ef ff ff e8 8e f2 66 f7 90 0f 0b 90 e9 2a f9 ff ff e8 80 f2 66 f7 90 <0f> 0b 90 e9 bb f9 ff ff e8 72 f2 66 f7 90 0f 0b 90 e9 1a fa ff ff
RSP: 0018:ffffc900000074e0 EFLAGS: 00010246
RAX: ffffffff8a5e6c30 RBX: 0000000080000000 RCX: ffff888106e91d80
RDX: 0000000000000100 RSI: 0000000080000000 RDI: 0000000000000000
RBP: ffffc90000007670 R08: ffff88810be30ae0 R09: 000000000000234e
R10: 000000000000003c R11: ffffffff8a5e5710 R12: ffff888116513390
R13: ffff888114c38900 R14: fffffffffffffff8 R15: dffffc0000000000
FS: 0000000000000000(0000) GS:ffff88818dc43000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000555561513898 CR3: 000000016fad2000 CR4: 00000000000006f0
Call Trace:
<IRQ>
icmpv6_notify+0x407/0x850
icmpv6_rcv+0x13b0/0x1d80
ip6_protocol_deliver_rcu+0xe37/0x1610
ip6_input_finish+0x191/0x370
NF_HOOK+0x336/0x3c0
ip6_input+0x16a/0x270
NF_HOOK+0x336/0x3c0
process_backlog+0x7dd/0x1950
__napi_poll+0xae/0x340
net_rx_action+0x627/0xf70
handle_softirqs+0x22a/0x840
do_softirq+0x76/0xd0
</IRQ>
<TASK>
__local_bh_enable_ip+0xf8/0x130
wg_socket_send_skb_to_peer+0x16b/0x1d0
wg_packet_handshake_send_worker+0x203/0x350
process_scheduled_works+0xb5d/0x1860
***
If these findings have caused you to resend the series or submit a
separate fix, please add the following tag to your commit message:
Tested-by: syzbot@syzkaller.appspotmail.com
---
This report is generated by a bot. It may contain errors.
syzbot ci engineers can be reached at syzkaller@googlegroups.com.
To test a patch for this bug, please reply with `#syz test`
(should be on a separate line).
The patch should be attached to the email.
Note: arguments like custom git repos and branches are not supported.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [syzbot ci] Re: net: tunnel: fix stale transport header after GRE/TEB decap
2026-04-16 7:04 ` [syzbot ci] Re: net: tunnel: fix stale transport header after GRE/TEB decap syzbot ci
@ 2026-04-16 7:49 ` Jiayuan Chen
0 siblings, 0 replies; 4+ messages in thread
From: Jiayuan Chen @ 2026-04-16 7:49 UTC (permalink / raw)
To: davem, dsahern, edumazet, horms, kuba, linux-kernel, netdev,
pabeni, pshelar, syzbot, tom
Cc: syzkaller-bugs
On 4/16/26 3:04 PM, syzbot ci wrote:
> syzbot ci has tested the following series
>
> [v1] net: tunnel: fix stale transport header after GRE/TEB decap
> https://lore.kernel.org/all/20260416034610.8873-1-jiayuan.chen@linux.dev
> * [PATCH net v1 1/2] net: tunnel: fix stale transport header after GRE/TEB decap
> * [PATCH net-next v1 2/2] net: add DEBUG_NET_WARN_ON_ONCE for negative transport offset
>
> and found the following issue:
> WARNING in udpv6_err
>
> Full report is available here:
> https://ci.syzbot.org/series/3886f2f1-a6d5-4c5c-8dc8-bc1cec577567
>
> ***
>
> WARNING in udpv6_err
>
> tree: net
> URL: https://kernel.googlesource.com/pub/scm/linux/kernel/git/netdev/net.git
> base: 1f5ffc672165ff851063a5fd044b727ab2517ae3
> arch: amd64
> compiler: Debian clang version 21.1.8 (++20251221033036+2078da43e25a-1~exp1~20251221153213.50), Debian LLD 21.1.8
> config: https://ci.syzbot.org/builds/06cf41a2-60fe-4f9b-8f68-57eb6d1e48cc/config
>
> ------------[ cut here ]------------
> off < 0
> WARNING: ./include/linux/skbuff.h:3239 at udpv6_err+0x1521/0x16d0, CPU#0: kworker/u9:2/51
> Modules linked in:
icmpv6_rcv
pskb_pull ==> skb_transport_offset() = -8
icmpv6_notify
udpv6_err
__udp6_lib_err_encap(skb) ==> WARNING
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-04-16 7:50 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-16 3:46 [PATCH net v1 1/2] net: tunnel: fix stale transport header after GRE/TEB decap Jiayuan Chen
2026-04-16 3:46 ` [PATCH net-next v1 2/2] net: add DEBUG_NET_WARN_ON_ONCE for negative transport offset Jiayuan Chen
2026-04-16 7:04 ` [syzbot ci] Re: net: tunnel: fix stale transport header after GRE/TEB decap syzbot ci
2026-04-16 7:49 ` Jiayuan Chen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox