* [PATCH net 1/1] net: nsh: handle nested NSH headers during GSO
[not found] <cover.1776597597.git.caoruide123@gmail.com>
@ 2026-04-20 3:31 ` Ren Wei
2026-04-20 8:12 ` [syzbot ci] " syzbot ci
0 siblings, 1 reply; 2+ messages in thread
From: Ren Wei @ 2026-04-20 3:31 UTC (permalink / raw)
To: netdev
Cc: davem, edumazet, kuba, pabeni, horms, jbenc, yuantan098,
yifanwucs, tomapufckgml, bird, lx24, caoruide123, n05ec
From: Ruide Cao <caoruide123@gmail.com>
nsh_gso_segment() currently redispatches the inner payload through
skb_mac_gso_segment() after stripping one NSH header. For nested NSH
payloads, including Ethernet-encapsulated NSH payloads, this can cause
repeated re-entry into nsh_gso_segment().
The existing validation added by commit af50e4ba34f4 ("nsh: fix infinite
loop") only covers invalid header lengths and does not address repeated
self-dispatch across nested NSH payload chains.
Handle nested NSH headers iteratively in a single nsh_gso_segment()
invocation. Unwrap consecutive NSH headers until the first non-NSH payload
is reached, including the case where the next redispatch target is reached
through ETH_P_TEB, segment that payload once, and then restore the full
outer encapsulation on each output segment. Also route validation failures
through the same unwind path so the skb state is restored after any partial
unwrap.
This keeps nested NSH GSO handling correct while avoiding recursive
redispatch.
Fixes: c411ed854584 ("nsh: add GSO support")
Cc: stable@kernel.org
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Co-developed-by: Xiao Liu <lx24@stu.ynu.edu.cn>
Signed-off-by: Xiao Liu <lx24@stu.ynu.edu.cn>
Signed-off-by: Ruide Cao <caoruide123@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
---
net/nsh/nsh.c | 75 ++++++++++++++++++++++++++++++++++++---------------
1 file changed, 54 insertions(+), 21 deletions(-)
diff --git a/net/nsh/nsh.c b/net/nsh/nsh.c
index bfb7758063f3..89c240c2ed7c 100644
--- a/net/nsh/nsh.c
+++ b/net/nsh/nsh.c
@@ -77,7 +77,7 @@ EXPORT_SYMBOL_GPL(nsh_pop);
static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
netdev_features_t features)
{
- unsigned int outer_hlen, mac_len, nsh_len;
+ unsigned int outer_hlen, mac_len, nsh_len, total_pull_len = 0;
struct sk_buff *segs = ERR_PTR(-EINVAL);
u16 mac_offset = skb->mac_header;
__be16 outer_proto, proto;
@@ -88,40 +88,73 @@ static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
outer_hlen = skb_mac_header_len(skb);
mac_len = skb->mac_len;
- if (unlikely(!pskb_may_pull(skb, NSH_BASE_HDR_LEN)))
- goto out;
- nsh_len = nsh_hdr_len(nsh_hdr(skb));
- if (nsh_len < NSH_BASE_HDR_LEN)
- goto out;
- if (unlikely(!pskb_may_pull(skb, nsh_len)))
- goto out;
+ while (true) {
+ if (unlikely(!pskb_may_pull(skb, NSH_BASE_HDR_LEN)))
+ goto err;
+ nsh_len = nsh_hdr_len(nsh_hdr(skb));
+ if (nsh_len < NSH_BASE_HDR_LEN)
+ goto err;
+ if (unlikely(!pskb_may_pull(skb, nsh_len)))
+ goto err;
- proto = tun_p_to_eth_p(nsh_hdr(skb)->np);
- if (!proto)
- goto out;
+ proto = tun_p_to_eth_p(nsh_hdr(skb)->np);
+ if (!proto)
+ goto err;
- __skb_pull(skb, nsh_len);
+ __skb_pull(skb, nsh_len);
+ total_pull_len += nsh_len;
- skb_reset_mac_header(skb);
- skb->mac_len = proto == htons(ETH_P_TEB) ? ETH_HLEN : 0;
- skb->protocol = proto;
+ skb_reset_mac_header(skb);
+ skb->mac_len = proto == htons(ETH_P_TEB) ? ETH_HLEN : 0;
+ skb->protocol = proto;
+
+ /* Keep unwrapping any payload that would redispatch back into
+ * nsh_gso_segment(), including Ethernet-encapsulated NSH.
+ */
+ if (proto == htons(ETH_P_NSH))
+ continue;
+
+ if (proto == htons(ETH_P_TEB)) {
+ int depth = skb->mac_len;
+
+ proto = skb_network_protocol(skb, &depth);
+ if (!proto)
+ goto err;
+
+ if (proto == htons(ETH_P_NSH)) {
+ __skb_pull(skb, depth);
+ total_pull_len += depth;
+
+ skb_reset_mac_header(skb);
+ skb->mac_len = 0;
+ skb->protocol = proto;
+ continue;
+ }
+ }
+
+ break;
+ }
features &= NETIF_F_SG;
segs = skb_mac_gso_segment(skb, features);
- if (IS_ERR_OR_NULL(segs)) {
- skb_gso_error_unwind(skb, htons(ETH_P_NSH), nsh_len,
- mac_offset, mac_len);
- goto out;
- }
+ if (IS_ERR_OR_NULL(segs))
+ goto err;
for (skb = segs; skb; skb = skb->next) {
skb->protocol = outer_proto;
- __skb_push(skb, nsh_len + outer_hlen);
+ __skb_push(skb, total_pull_len + outer_hlen);
skb_reset_mac_header(skb);
skb_set_network_header(skb, outer_hlen);
skb->mac_len = mac_len;
}
+ goto out;
+
+err:
+ if (total_pull_len)
+ skb_gso_error_unwind(skb, outer_proto, total_pull_len,
+ mac_offset, mac_len);
+
out:
return segs;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* [syzbot ci] Re: net: nsh: handle nested NSH headers during GSO
2026-04-20 3:31 ` [PATCH net 1/1] net: nsh: handle nested NSH headers during GSO Ren Wei
@ 2026-04-20 8:12 ` syzbot ci
0 siblings, 0 replies; 2+ messages in thread
From: syzbot ci @ 2026-04-20 8:12 UTC (permalink / raw)
To: bird, caoruide123, davem, edumazet, horms, jbenc, kuba, lx24,
n05ec, netdev, pabeni, tomapufckgml, yifanwucs, yuantan098
Cc: syzbot, syzkaller-bugs
syzbot ci has tested the following series
[v1] net: nsh: handle nested NSH headers during GSO
https://lore.kernel.org/all/6112cce99b4e3571444a616d0fb19e91e2fcca72.1776597598.git.caoruide123@gmail.com
* [PATCH net 1/1] net: nsh: handle nested NSH headers during GSO
and found the following issue:
WARNING in nsh_gso_segment
Full report is available here:
https://ci.syzbot.org/series/13f77bac-014d-4059-9187-fbdbcb6a6540
***
WARNING in nsh_gso_segment
tree: net
URL: https://kernel.googlesource.com/pub/scm/linux/kernel/git/netdev/net.git
base: 0cf004ffb61cd32d140531c3a84afe975f9fc7ea
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/193058cd-cd88-4bb0-a6e6-b43b6179fcd9/config
syz repro: https://ci.syzbot.org/findings/446db72d-a630-471c-b369-2ef1f7b3b6ed/syz_repro
------------[ cut here ]------------
offset != (typeof(skb->mac_header))offset
WARNING: ./include/linux/skbuff.h:3173 at skb_reset_mac_header include/linux/skbuff.h:3173 [inline], CPU#1: syz.1.20/5978
WARNING: ./include/linux/skbuff.h:3173 at nsh_gso_segment+0x833/0x12d0 net/nsh/nsh.c:107, CPU#1: syz.1.20/5978
Modules linked in:
CPU: 1 UID: 0 PID: 5978 Comm: syz.1.20 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
RIP: 0010:skb_reset_mac_header include/linux/skbuff.h:3173 [inline]
RIP: 0010:nsh_gso_segment+0x833/0x12d0 net/nsh/nsh.c:107
Code: 2f 08 00 00 48 8b 7c 24 60 44 89 f6 e8 46 83 e4 fd 48 85 c0 0f 84 20 08 00 00 e8 48 af 31 f6 e9 ab fb ff ff e8 3e af 31 f6 90 <0f> 0b 90 e9 43 fd ff ff e8 30 af 31 f6 90 0f 0b 90 e9 39 fe ff ff
RSP: 0018:ffffc90004847220 EFLAGS: 00010293
RAX: ffffffff8b93aeb2 RBX: ffff88817362a6d8 RCX: ffff88810f088000
RDX: 0000000000000000 RSI: 0000000000010040 RDI: 0000000000010000
RBP: ffffc90004847390 R08: ffff88810f088000 R09: 0000000000000005
R10: 0000000000000005 R11: 0000000000000000 R12: 0000000000000000
R13: 0000000000010040 R14: dffffc0000000000 R15: 0000000000000074
FS: 00007f28e9ed36c0(0000) GS:ffff8882a9245000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000200000010000 CR3: 0000000170f06000 CR4: 00000000000006f0
Call Trace:
<TASK>
skb_mac_gso_segment+0x31c/0x690 net/core/gso.c:53
__skb_gso_segment+0x376/0x540 net/core/gso.c:124
skb_gso_segment include/net/gso.h:83 [inline]
validate_xmit_skb+0xa21/0x14a0 net/core/dev.c:4039
validate_xmit_skb_list+0x84/0x120 net/core/dev.c:4089
sch_direct_xmit+0xdf/0x4c0 net/sched/sch_generic.c:357
__dev_xmit_skb net/core/dev.c:4209 [inline]
__dev_queue_xmit+0x180f/0x3950 net/core/dev.c:4831
packet_snd net/packet/af_packet.c:3077 [inline]
packet_sendmsg+0x3ebc/0x50f0 net/packet/af_packet.c:3109
sock_sendmsg_nosec net/socket.c:787 [inline]
__sock_sendmsg net/socket.c:802 [inline]
__sys_sendto+0x672/0x710 net/socket.c:2265
__do_sys_sendto net/socket.c:2272 [inline]
__se_sys_sendto net/socket.c:2268 [inline]
__x64_sys_sendto+0xde/0x100 net/socket.c:2268
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x15f/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f28e8f9c819
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f28e9ed3028 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
RAX: ffffffffffffffda RBX: 00007f28e9216090 RCX: 00007f28e8f9c819
RDX: 00000000000100a6 RSI: 0000200000000180 RDI: 0000000000000005
RBP: 00007f28e9032c91 R08: 0000200000000140 R09: 0000000000000014
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f28e9216128 R14: 00007f28e9216090 R15: 00007ffd50249d78
</TASK>
***
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] 2+ messages in thread
end of thread, other threads:[~2026-04-20 8:12 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <cover.1776597597.git.caoruide123@gmail.com>
2026-04-20 3:31 ` [PATCH net 1/1] net: nsh: handle nested NSH headers during GSO Ren Wei
2026-04-20 8:12 ` [syzbot ci] " syzbot ci
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox