Re: [PATCH 1/2] usbip: clear actual_length after a failed receive

From: Cheng Yongkang

Date: Fri Oct 30 2026 - 00:13:34 EST


Hi Shuah,

Without this change the URB is still completed to usbfs, with status
-EPROTO but with the peer-supplied actual_length intact:

vhci_recv_ret_submit()
usbip_pack_pdu() -> usbip_pack_ret_submit():
urb->actual_length = rpdu->actual_length; (usbip_common.c:471)
usbip_recv_xbuff():
size = urb->actual_length; (usbip_common.c:849)
if (size > urb->transfer_buffer_length) (usbip_common.c:856)
goto error; /* rejects the packet, returns < 0 */
urb->status = -EPROTO; goto error;
error:
usb_hcd_giveback_urb(hcd, urb, urb->status); (vhci_rx.c:107)
-> urb->complete(urb) (hcd.c:1657)
-> usbfs async_completed() (devio.c:1911)

usbfs copies data on reap whenever actual_length is non-zero, and does
not look at the URB status:

processcompl():
if (as->userbuffer && urb->actual_length) (devio.c:2050)
copy_urb_data_to_user(as->userbuffer, urb);
copy_urb_data_to_user():
len = urb->actual_length; /* non-isochronous */ (devio.c:563)

That is deliberate: a legitimate HCD can complete with a short read and
a non-zero status, and userspace still gets the partial data. But here
the length came from the peer and was already rejected as invalid, so it
must not reach usbfs. -EPROTO alone does not stop the copy; zeroing
actual_length makes the copy condition false and userspace observes a
failed, zero-length transfer.

I'll fold this into the commit message for the next version.

Thanks,
Cheng Yongkang