@samitouri / QOSamiQemu / commits / 15700a66ec

hw/usb/dev-uas: Don't abort if guest provided an undersized buffer for status

QEMU currently aborts if the guest provides an undersized buffer for the status packet (8 bytes): hw/usb/core.c:623: usb_packet_copy: Assertion `p->actual_length + bytes <= iov->size' failed. If we hit this situation, log a guest error and continue by simply only providing the bytes that the guest asked for. (Note: This is e.g. similar to the UAS_PIPE_ID_COMMAND case that also clamps the length with: length = MIN(sizeof(iu), p->iov.size)) Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3900 Reported-by: Feifan Qian <bea1e@proton.me> Signed-off-by: Thomas Huth <thuth@redhat.com> Message-ID: <20260730163901.1154791-1-thuth@redhat.com>

Thomas Huth committed Jul 30, 2026 at 18:39 UTC 15700a66ecb53c52717c913c2c4501372c0115ab
1 file changed +17 -2
hw/usb/dev-uas.c
+17 -2
@@ -359,6 +359,7 @@ static void usb_uas_send_status_bh(void *opaque)
359 UASDevice *uas = opaque;
360 UASStatus *st;
361 USBPacket *p;
362 + uint32_t length;
363
364 while ((st = QTAILQ_FIRST(&uas->results)) != NULL) {
365 if (uas_using_streams(uas)) {
@@ -373,7 +374,14 @@ static void usb_uas_send_status_bh(void *opaque)
374 break;
375 }
376
376 - usb_packet_copy(p, &st->status, st->length);
377 + length = st->length;
378 + if (length > p->iov.size) {
379 + qemu_log_mask(LOG_GUEST_ERROR,
380 + "usb uas: packet (%zd) too small for status (%d)\n",
381 + p->iov.size, length);
382 + length = p->iov.size;
383 + }
384 + usb_packet_copy(p, &st->status, length);
385 QTAILQ_REMOVE(&uas->results, st, next);
386 g_free(st);
387
@@ -875,7 +883,14 @@ static void usb_uas_handle_data(USBDevice *dev, USBPacket *p)
883 break;
884 }
885 }
878 - usb_packet_copy(p, &st->status, st->length);
886 + length = st->length;
887 + if (length > p->iov.size) {
888 + qemu_log_mask(LOG_GUEST_ERROR,
889 + "usb uas: packet (%zd) too small for status (%d)\n",
890 + p->iov.size, length);
891 + length = p->iov.size;
892 + }
893 + usb_packet_copy(p, &st->status, length);
894 QTAILQ_REMOVE(&uas->results, st, next);
895 g_free(st);
896 break;