From: Tobi Gaertner Date: Sat, 14 Mar 2026 05:46:40 +0000 (-0700) Subject: net: usb: cdc_ncm: add ndpoffset to NDP32 nframes bounds check X-Git-Tag: v7.0-rc5~31^2~22^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=77914255155e68a20aa41175edeecf8121dac391;p=thirdparty%2Fkernel%2Flinux.git net: usb: cdc_ncm: add ndpoffset to NDP32 nframes bounds check The same bounds-check bug fixed for NDP16 in the previous patch also exists in cdc_ncm_rx_verify_ndp32(). The DPE array size is validated against the total skb length without accounting for ndpoffset, allowing out-of-bounds reads when the NDP32 is placed near the end of the NTB. Add ndpoffset to the nframes bounds check and use struct_size_t() to express the NDP-plus-DPE-array size more clearly. Compile-tested only. Fixes: 0fa81b304a79 ("cdc_ncm: Implement the 32-bit version of NCM Transfer Block") Signed-off-by: Tobi Gaertner Link: https://patch.msgid.link/20260314054640.2895026-3-tob.gaertner@me.com Signed-off-by: Jakub Kicinski --- diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 21e53b20e239..bb9929727eb9 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -1693,6 +1693,7 @@ int cdc_ncm_rx_verify_ndp32(struct sk_buff *skb_in, int ndpoffset) struct usbnet *dev = netdev_priv(skb_in->dev); struct usb_cdc_ncm_ndp32 *ndp32; int ret = -EINVAL; + size_t ndp_len; if ((ndpoffset + sizeof(struct usb_cdc_ncm_ndp32)) > skb_in->len) { netif_dbg(dev, rx_err, dev->net, "invalid NDP offset <%u>\n", @@ -1712,8 +1713,8 @@ int cdc_ncm_rx_verify_ndp32(struct sk_buff *skb_in, int ndpoffset) sizeof(struct usb_cdc_ncm_dpe32)); ret--; /* we process NDP entries except for the last one */ - if ((sizeof(struct usb_cdc_ncm_ndp32) + - ret * (sizeof(struct usb_cdc_ncm_dpe32))) > skb_in->len) { + ndp_len = struct_size_t(struct usb_cdc_ncm_ndp32, dpe32, ret); + if (ndpoffset + ndp_len > skb_in->len) { netif_dbg(dev, rx_err, dev->net, "Invalid nframes = %d\n", ret); ret = -EINVAL; }