[PATCH 2/2] usb: usbfs: clamp the copied length to transfer_buffer_length
From: Cheng Yongkang
Date: Thu Oct 29 2026 - 10:20:19 EST
copy_urb_data_to_user() uses urb->actual_length as the number of bytes to
copy to userspace for non-isochronous URBs. The usbfs contract is that a
driver must not report more data than the transfer buffer holds, but
usbfs cannot rely on every HCD or device implementation to honor it; a
malicious usbip peer can already set actual_length beyond
transfer_buffer_length and trigger an out-of-bounds read:
BUG: KASAN: slab-out-of-bounds in _copy_to_user+0x79/0xb0
Read of size 88 at addr ...
copy_urb_data_to_user+0x36f/0x480
Clamp the non-isochronous length to transfer_buffer_length before the
copy. Normal URBs are unaffected; the isochronous path already uses
transfer_buffer_length.
Fixes: 3d97ff63f899 ("usbdevfs: Use scatter-gather lists for large bulk transfers")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: LLM
Signed-off-by: Cheng Yongkang <teel4res@xxxxxxxxx>
---
drivers/usb/core/devio.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 101cb94..9554b6a 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -557,10 +557,13 @@ static int copy_urb_data_to_user(u8 __user *userbuffer, struct urb *urb)
{
unsigned i, len, size;
- if (urb->number_of_packets > 0) /* Isochronous */
+ if (urb->number_of_packets > 0) { /* Isochronous */
len = urb->transfer_buffer_length;
- else /* Non-Isoc */
+ } else { /* Non-Isoc */
len = urb->actual_length;
+ if (len > urb->transfer_buffer_length)
+ len = urb->transfer_buffer_length;
+ }
if (urb->num_sgs == 0) {
if (copy_to_user(userbuffer, urb->transfer_buffer, len))
--
2.34.1