hw/usb/core: Avoid possible assert() in do_parameter() --> usb_packet_copy()
usb_packet_copy() uses assert(p->actual_length + bytes <= iov->size) to make sure that there is enough space in the the iov. This assert() can be triggered from do_parameter() if the guest programs the XHCI in a weird way. Avoid the hard error by checking for the condition in do_parameter() first and signalling a USB_RET_STALL to the guest, just like it is done for another error condition here already some lines earlier. Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3746 Reported-by: Yunhe Wang <yunhewwww@163.com> Signed-off-by: Thomas Huth <thuth@redhat.com> Message-ID: <20260721185140.247775-1-thuth@redhat.com>
Thomas Huth committed
Jul 21, 2026 at 20:51 UTC
68809288c7e5bf2a9a9edeb55af8c368f52442ad
1 file changed
+10
hw/usb/core.c
+10
@@ -26,6 +26,7 @@
26
#include "qemu/osdep.h"
27
#include "hw/usb/usb.h"
28
#include "qemu/iov.h"
29
+#include "qemu/log.h"
30
#include "trace.h"
31
32
void usb_pick_speed(USBPort *port)
@@ -288,6 +289,15 @@ static void do_parameter(USBDevice *s, USBPacket *p)
289
p->status = USB_RET_STALL;
290
return;
291
}
292
+ if ((p->pid == USB_TOKEN_OUT || p->pid == USB_TOKEN_IN) &&
293
+ setup_len > p->iov.size) {
294
+ qemu_log_mask(LOG_GUEST_ERROR,
295
+ "xhci: setup state param length %u > iov size %zu\n",
296
+ setup_len, p->iov.size);
297
+ p->status = USB_RET_STALL;
298
+ return;
299
+ }
300
+
301
s->setup_len = setup_len;
302
303
if (p->pid == USB_TOKEN_OUT) {