* [PATCH net v3] net: usb: cdc_ncm: don't underflow the NDP room check
@ 2026-11-11 4:41 Jiahao Xu
2026-11-12 19:00 ` patchwork-bot+netdevbpf
0 siblings, 1 reply; 2+ messages in thread
From: Jiahao Xu @ 2026-11-11 4:41 UTC (permalink / raw)
To: Oliver Neukum, netdev
Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, linux-usb, linux-kernel, syzbot+1994e2ecf323ed90f255,
xujiahao
cdc_ncm_ndp16() and cdc_ncm_ndp32() verify that the new NDP and the
datagram fit into the NTB with an unsigned subtraction:
if ((ctx->tx_curr_size - skb->len - reserve) < ctx->max_ndp_size)
return NULL;
Nothing guarantees that skb->len plus the reserve stays below
tx_curr_size, and when it does not the subtraction wraps around to a
huge value, the check passes, and the skb_put_zero() of max_ndp_size
bytes that follows overruns the NTB:
skbuff: skb_over_panic: text:ffff80000db33558 len:428 put:172
head:ffff0000c2c66100 tail:0x1ac end:0x140
kernel BUG at net/core/skbuff.c:200
skb_put_zero include/linux/skbuff.h:2595 [inline]
cdc_ncm_ndp16 drivers/net/usb/cdc_ncm.c:1132 [inline]
cdc_ncm_fill_tx_frame+0xdf0/0x30e0 drivers/net/usb/cdc_ncm.c:1309
Here tx_curr_size is 0x140 = 320, skb->len is already 256 and the
skb_put_zero() wants another 172 bytes.
Two device controlled settings make this reachable:
- dwNtbOutMaxSize = 320 caps tx_max at 320. The lower bound computed
in cdc_ncm_check_tx_max() is max_datagram_size + max_ndp_size + the
NTH header, but cdc_ncm_setup() clamps tx_max before
cdc_ncm_set_dgram_size() runs, so max_datagram_size is still 0 and
the bound is only max_ndp_size + the NTH header. It does not
reserve room for one datagram plus one NDP.
- wNdpOutAlignment = 256 is accepted by cdc_ncm_fix_modulus() as long
as it is smaller than tx_max, and cdc_ncm_align_tail() then pads the
12 byte NTH header up to 256 bytes right before this check.
An NDP can also be added to an NTB that already holds datagrams through
cdc_mbim_tx_fixup(), which uses a different signature per MBIM session.
On plain cdc_ncm the chain lookup in cdc_ncm_ndp16() returns the
existing NDP for the single signature, so there the create path is
normally reached for the first datagram of each NTB.
Rewrite the test as an addition, which cannot underflow and gives the
same answer whenever the original subtraction did not wrap.
Fixes: c78b7c586657 ("net: cdc_ncm: refactoring for tx multiplexing")
Fixes: 0fa81b304a79 ("cdc_ncm: Implement the 32-bit version of NCM Transfer Block")
Reported-by: syzbot+1994e2ecf323ed90f255@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=1994e2ecf323ed90f255
Signed-off-by: Jiahao Xu <xujiahao@cmss.chinamobile.com>
---
v3:
- Correct the description of the trigger and of the tx_max lower bound,
as pointed out by sashiko-bot. No code change.
v2:
- Add the Fixes: tags. No code change.
---
drivers/net/usb/cdc_ncm.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index 19db5a668..e92dc7f01 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -1125,7 +1125,7 @@ static struct usb_cdc_ncm_ndp16 *cdc_ncm_ndp16(struct cdc_ncm_ctx *ctx, struct s
cdc_ncm_align_tail(skb, ctx->tx_ndp_modulus, 0, ctx->tx_curr_size);
/* verify that there is room for the NDP and the datagram (reserve) */
- if ((ctx->tx_curr_size - skb->len - reserve) < ctx->max_ndp_size)
+ if (skb->len + reserve + ctx->max_ndp_size > ctx->tx_curr_size)
return NULL;
/* link to it */
@@ -1180,7 +1180,7 @@ static struct usb_cdc_ncm_ndp32 *cdc_ncm_ndp32(struct cdc_ncm_ctx *ctx, struct s
cdc_ncm_align_tail(skb, ctx->tx_ndp_modulus, 0, ctx->tx_curr_size);
/* verify that there is room for the NDP and the datagram (reserve) */
- if ((ctx->tx_curr_size - skb->len - reserve) < ctx->max_ndp_size)
+ if (skb->len + reserve + ctx->max_ndp_size > ctx->tx_curr_size)
return NULL;
/* link to it */
--
2.43.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH net v3] net: usb: cdc_ncm: don't underflow the NDP room check
2026-11-11 4:41 [PATCH net v3] net: usb: cdc_ncm: don't underflow the NDP room check Jiahao Xu
@ 2026-11-12 19:00 ` patchwork-bot+netdevbpf
0 siblings, 0 replies; 2+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-11-12 19:00 UTC (permalink / raw)
To: Jiahao Xu
Cc: oliver, netdev, andrew+netdev, davem, edumazet, kuba, pabeni,
linux-usb, linux-kernel, syzbot+1994e2ecf323ed90f255
Hello:
This patch was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Wed, 11 Nov 2026 12:41:56 +0800 you wrote:
> cdc_ncm_ndp16() and cdc_ncm_ndp32() verify that the new NDP and the
> datagram fit into the NTB with an unsigned subtraction:
>
> if ((ctx->tx_curr_size - skb->len - reserve) < ctx->max_ndp_size)
> return NULL;
>
> Nothing guarantees that skb->len plus the reserve stays below
> tx_curr_size, and when it does not the subtraction wraps around to a
> huge value, the check passes, and the skb_put_zero() of max_ndp_size
> bytes that follows overruns the NTB:
>
> [...]
Here is the summary with links:
- [net,v3] net: usb: cdc_ncm: don't underflow the NDP room check
https://git.kernel.org/netdev/net/c/b507828c7b61
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-11-12 19:00 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-11 4:41 [PATCH net v3] net: usb: cdc_ncm: don't underflow the NDP room check Jiahao Xu
2026-11-12 19:00 ` patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox