From: Thomas Huth <[email protected]> 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 <[email protected]> Signed-off-by: Thomas Huth <[email protected]> Message-ID: <[email protected]> --- hw/usb/core.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/hw/usb/core.c b/hw/usb/core.c index d71204c5c80..43653c26cae 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -26,6 +26,7 @@ #include "qemu/osdep.h" #include "hw/usb/usb.h" #include "qemu/iov.h" +#include "qemu/log.h" #include "trace.h" void usb_pick_speed(USBPort *port) @@ -288,6 +289,15 @@ static void do_parameter(USBDevice *s, USBPacket *p) p->status = USB_RET_STALL; return; } + if ((p->pid == USB_TOKEN_OUT || p->pid == USB_TOKEN_IN) && + setup_len > p->iov.size) { + qemu_log_mask(LOG_GUEST_ERROR, + "xhci: setup state param length %u > iov size %zu\n", + setup_len, p->iov.size); + p->status = USB_RET_STALL; + return; + } + s->setup_len = setup_len; if (p->pid == USB_TOKEN_OUT) { -- 2.55.0
