[PATCH v2] usbip: fix number_of_packets for non-iso transfers
flat view
DORMANTno replies
From: Markus Mikonsaari <hidden>
Date: 2026-09-09 12:06:28
Subsystem:
the rest, usb over ip driver, usb subsystem · Maintainers:
Linus Torvalds, Valentina Manea, Shuah Khan, Shuah Khan, Greg Kroah-Hartman
In the USB/IP protocol, number_of_packets is set to 0xffffffff (-1) by sender when the transfer is not isochronous. usbip_pack_pdu() copies this value into urb->number_of_packets. A host controller driver may compute the iso_frame_desc size directly from number_of_packets without independently validating it against the pipe type which produces an undersized allocation. For example on a Raspberry Pi, the dwc_otg driver panics with a slab-out-of-bounds write in dwc_otg_hcd_urb_alloc() during a USB/IP attach involving a non-isochronous transfer. Correct the number_of_packets to the value the urb was actually allocated for immediately after usbip_pack_pdu() overwrites it. Assisted-by: LLM Signed-off-by: Markus Mikonsaari <redacted> --- v2: - Moved fix and comment into a static helper - Shortened summary - Added Assisted-by tag drivers/usb/usbip/stub_rx.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/drivers/usb/usbip/stub_rx.c b/drivers/usb/usbip/stub_rx.c
index 1e9ae578810d..d592fd8edd87 100644
--- a/drivers/usb/usbip/stub_rx.c
+++ b/drivers/usb/usbip/stub_rx.c@@ -461,6 +461,20 @@ static int stub_recv_xbuff(struct usbip_device *ud, struct stub_priv *priv) return ret; } +/* + * number_of_packets is set to -1 by the USB/IP sender when the transfer + * is not isochronous. + * usbip_pack_pdu() copies this value into urb->number_of_packets. + * Leaving the number_of_packets at -1 can lead to + * downstream consumers of this urb (e.g. host-controller drivers) + * to allocate negative iso_frame_desc storage. + * Set it to what the urb was actually allocated for. + */ +static inline void stub_fixup_urb_number_of_packets(struct urb *urb, int np) +{ + urb->number_of_packets = np; +} + static void stub_recv_cmd_submit(struct stub_device *sdev, struct usbip_header *pdu) {
@@ -567,6 +581,7 @@ static void stub_recv_cmd_submit(struct stub_device *sdev, } usbip_pack_pdu(pdu, priv->urbs[0], USBIP_CMD_SUBMIT, 0); + stub_fixup_urb_number_of_packets(priv->urbs[0], np); } else { for_each_sg(sgl, sg, nents, i) { priv->urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
@@ -579,6 +594,7 @@ static void stub_recv_cmd_submit(struct stub_device *sdev, usbip_pack_pdu(pdu, priv->urbs[i], USBIP_CMD_SUBMIT, 0); priv->urbs[i]->transfer_buffer = sg_virt(sg); priv->urbs[i]->transfer_buffer_length = sg->length; + stub_fixup_urb_number_of_packets(priv->urbs[i], 0); } priv->sgl = sgl; }
--
2.55.0