public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [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