[PULL 4/6] hw/usb/dev-uas: Don't abort if guest provided an undersized buffer for status

Thomas Huth <[email protected]>
Newsgroups org.nongnu.qemu-devel
Message-ID <[email protected]>
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 <[email protected]>
Signed-off-by: Thomas Huth <[email protected]>
Message-ID: <[email protected]>
---
 hw/usb/dev-uas.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
index 963c0433b38..be8c3667e83 100644
--- a/hw/usb/dev-uas.c
+++ b/hw/usb/dev-uas.c
@@ -359,6 +359,7 @@ static void usb_uas_send_status_bh(void *opaque)
     UASDevice *uas = opaque;
     UASStatus *st;
     USBPacket *p;
+    uint32_t length;
 
     while ((st = QTAILQ_FIRST(&uas->results)) != NULL) {
         if (uas_using_streams(uas)) {
@@ -373,7 +374,14 @@ static void usb_uas_send_status_bh(void *opaque)
             break;
         }
 
-        usb_packet_copy(p, &st->status, st->length);
+        length = st->length;
+        if (length > p->iov.size) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "usb uas: packet (%zd) too small for status (%d)\n",
+                          p->iov.size, length);
+            length = p->iov.size;
+        }
+        usb_packet_copy(p, &st->status, length);
         QTAILQ_REMOVE(&uas->results, st, next);
         g_free(st);
 
@@ -875,7 +883,14 @@ static void usb_uas_handle_data(USBDevice *dev, USBPacket *p)
                 break;
             }
         }
-        usb_packet_copy(p, &st->status, st->length);
+        length = st->length;
+        if (length > p->iov.size) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "usb uas: packet (%zd) too small for status (%d)\n",
+                          p->iov.size, length);
+            length = p->iov.size;
+        }
+        usb_packet_copy(p, &st->status, length);
         QTAILQ_REMOVE(&uas->results, st, next);
         g_free(st);
         break;
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.