mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: netdev-bot+sashiko@kernel.org
To: xujiahao@cmss.chinamobile.com
Cc: oliver@neukum.org, netdev@vger.kernel.org, andrew+netdev@lunn.ch,
	davem@davemloft.net, edumazet@kernel.org, kuba@kernel.org,
	pabeni@redhat.com, linux-usb@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	syzbot+1994e2ecf323ed90f255@syzkaller.appspotmail.com
Subject: Re: [PATCH net] net: usb: cdc_ncm: don't underflow the NDP room check
Date: Tue, 10 Nov 2026 14:08:27 +0000	[thread overview]
Message-ID: <179431970794.994134.5397680174063039863@kernel.org> (raw)
In-Reply-To: <20261109060913.526268-1-xujiahao@cmss.chinamobile.com>

Thank you for your contribution! Sashiko AI review found 2 potential
issue(s) to consider.

Critical: 0 · High: 0 · Medium: 1 · Low: 1

If you believe none of the issues are legitimate, please reply to each
issue of Medium severity or higher and explain why the AI is wrong.
If any of them are legitimate and you plan to respin, please let patchwork
know by including "pw-bot: cr" as a separate line at the end of your reply
(one such reply per series is enough).

- [Medium] The code change is correct.
- [Low] The patch fixes a syzbot-reported skb_over_panic() (BUG() in
  net/core/skbuff.c) in the cdc_ncm/cdc_mbim TX path but has no Fixes:…

--

net: usb: cdc_ncm: don't underflow the NDP room check

This patch rewrites the NDP room check in cdc_ncm_ndp16() and
cdc_ncm_ndp32() as an addition instead of an unsigned subtraction. The
check can then no longer wrap and let the following skb_put_zero() of
max_ndp_size bytes overrun the NTB, which was reported by syzbot as an
skb_over_panic() in cdc_ncm_fill_tx_frame().

Closes: https://syzkaller.appspot.com/bug?extid=1994e2ecf323ed90f255

> tx_max is only clamped to max_datagram_size + max_ndp_size + the NTH
> header size, so tx_curr_size is just big enough for one datagram and
> one NDP.  A second datagram in the same NTB is therefore exactly the
> case this check has to reject, and that is also the case where
> skb->len + reserve exceeds tx_curr_size: 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 buffer:

[Severity: Medium]
The code change looks right, but does this paragraph describe the
trigger and the root cause accurately?

Can a second datagram in the same NTB reach this check at all? Before
the room check, cdc_ncm_ndp16() walks the NDP chain and returns any
existing NDP that has the same signature:

drivers/net/usb/cdc_ncm.c:cdc_ncm_ndp16() {
    ...
	while (ndpoffset) {
		ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb->data + ndpoffset);
		if  (ndp16->dwSignature == sign)
			return ndp16;
		ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex);
	}
    ...
}

cdc_ncm_tx_fixup() always passes one fixed signature
(USB_CDC_NCM_NDP16_NOCRC_SIGN or USB_CDC_NCM_NDP32_NOCRC_SIGN). On plain
cdc_ncm the check therefore only runs for the first datagram of each
NTB.

As far as I can tell, the only way to add another NDP to an NTB that
already holds datagrams is cdc_mbim_tx_fixup()->cdc_ncm_fill_tx_frame().
That path uses a different signature for each MBIM session.

The clamp also doesn't seem to guarantee room for one datagram plus one
NDP. cdc_ncm_setup() clamps tx_max before it sets the datagram size:

drivers/net/usb/cdc_ncm.c:cdc_ncm_setup() {
    ...
	/* clamp rx_max and tx_max and inform device */
	cdc_ncm_update_rxtx_max(dev, def_rx, def_tx);

	/* sanitize the modulus and remainder values */
	cdc_ncm_fix_modulus(dev);

	/* set max datagram size */
	cdc_ncm_set_dgram_size(dev, cdc_ncm_max_dgram_size(dev));
    ...
}

ctx is allocated with kzalloc() in cdc_ncm_bind_common(), so
ctx->max_datagram_size is still 0 when cdc_ncm_check_tx_max() computes:

	min = ctx->max_datagram_size + ctx->max_ndp_size + sizeof(struct usb_cdc_ncm_nth16);

That makes the floor only 172 + 12 = 184 bytes. def_tx is
min(CDC_NCM_NTB_DEF_SIZE_TX, dwNtbOutMaxSize), so a device that reports
dwNtbOutMaxSize = 320 gets tx_max = 320. That matches end:0x140.

With that tx_max, the reported len:428 put:172 (skb_out->len is 256 when
the NDP is pushed) could come from either of two paths:

  - an NDP for a second MBIM session on cdc_mbim

  - the first datagram on plain cdc_ncm, when the device reports
    wNdpOutAlignment = 256. cdc_ncm_fix_modulus() accepts this because
    256 < tx_max. cdc_ncm_align_tail() then pads the 12-byte NTH up to
    256 before the room check.

> Here end is 0x140 = 320 = 140 + 172 + 8, i.e. the one-datagram minimum.

Where do the 140 and the 8 come from? sizeof(struct usb_cdc_ncm_nth16)
is 12, and 8 is sizeof(struct usb_cdc_ncm_ndp16). max_datagram_size
doesn't appear to ever be 140, and it is 0 when the tx_max floor is
computed.

Could the commit message be updated to describe the actual triggers?
Those are a device-controlled dwNtbOutMaxSize/wNdpOutAlignment, or MBIM
multi-session NDPs. It could also mention that cdc_ncm_setup() clamps
tx_max before max_datagram_size is set.

> Reported-by: syzbot+1994e2ecf323ed90f255@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=1994e2ecf323ed90f255
> Signed-off-by: xujiahao <xujiahao@cmss.chinamobile.com>

[Severity: Low]
Should this have a Fixes: tag? The patch fixes a kernel BUG that can be
reached from the cdc_ncm and cdc_mbim TX paths. netdev expects a Fixes:
tag on fixes, and stable backports rely on it.

According to blame, the subtraction-based room check in cdc_ncm_ndp16()
was added by:

  c78b7c586657 ("net: cdc_ncm: refactoring for tx multiplexing")

and its current tx_curr_size form comes from:

  e1069bbfcf3b ("net: cdc_ncm: Reduce memory use when kernel memory low")

cdc_ncm_ndp32() has the same check.

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261109060913.526268-1-xujiahao%40cmss.chinamobile.com

      parent reply	other threads:[~2026-11-10 14:08 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-09  6:09 xujiahao
2026-11-10  7:16 ` [PATCH net v2] " xujiahao
2026-11-10 14:08 ` netdev-bot+sashiko [this message]

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=179431970794.994134.5397680174063039863@kernel.org \
    --to=netdev-bot+sashiko@kernel.org \
    --cc=andrew+netdev@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=edumazet@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=oliver@neukum.org \
    --cc=pabeni@redhat.com \
    --cc=syzbot+1994e2ecf323ed90f255@syzkaller.appspotmail.com \
    --cc=xujiahao@cmss.chinamobile.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®