[PATCH net] net: usb: cdc_ncm: reject negative chained NDP offsets

Greg Kroah-Hartman
2026-04-11T10:53:41Z

cdc_ncm_rx_fixup() reads dwNextNdpIndex from each NDP32 to chain to the
next one. The 32-bit value from the device is stored into the signed
int ndpoffset so that means values with the high bit set become
negative. The first time this is read, the value is properly tested for
a negative value BUT the next time through the loop, this type of check
is missed entirely.

Fix this up by checking for a negative value when dwNextNdpIndex is read
again in the bottom of the loop to match the top check.

Commit 8d2b1a1ec9f5 ("CDC-NCM: avoid overflow in sanity checking") fixed
a similar signed-overflow issue in the datagram offset checks of the
same function.

Cc: Oliver Neukum <oliver@neukum.org>
Cc: Andrew Lunn <andrew+netdev@lunn.ch>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Fixes: 0fa81b304a79 ("cdc_ncm: Implement the 32-bit version of NCM Transfer Block")
Cc: stable <stable@kernel.org>
Assisted-by: gregkh_clanker_t1000
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/usb/cdc_ncm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index bb9929727eb9..b2d08c4aae54 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -1835,7 +1835,7 @@ int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
else
ndpoffset = le32_to_cpu(ndp.ndp32->dwNextNdpIndex);

- if (ndpoffset && loopcount--)
+ if (ndpoffset > 0 && loopcount--)
goto next_ndp;

/* update stats */
--
2.53.0