From: "Michael S. Tsirkin" <[email protected]>

virtio-mmio reports VIRTQUEUE_MAX_SIZE (1024) as QUEUE_NUM_MAX for every
queue, regardless of the size the device passes to virtio_add_queue().

This works by accident because QEMU mostly does not care about the ring
size - the guest is the one allocating memory here.  But this changes
with in-order vqs where qemu is the one allocating resources.
Now, specifying a larger vq than allocated causes an OOB memory access.

To fix:
- for new machine types, report the actual max queue size to guest
- for old machine types, use a compat property to allocate 1k sized
  queues

Fixes: CVE-2026-50626
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3882
Cc: Peter Maydell <[email protected]>
Message-ID: 
<8715acbb9516e67e2a776cda6f9edf105343f788.1784930765.git....@redhat.com>
Acked-by: Yonggang Luo <[email protected]>
Reported-by: Miku Hatsune <[email protected]>
Signed-off-by: Michael S. Tsirkin <[email protected]>
(cherry picked from commit a5cff318f06cd06b37224e15ee74d64d1df8b12b)
(Mjt: for qemu versions <11.1, always allocate 1k-sized queues,  so whole
 change reduces to one-liner queue size override.  This becomes sufficient to
 fix CVE-2026-50626 for <11.1.  See discussin after this patch pull request at
 
https://lore.kernel.org/qemu-devel/a5cff318f06cd06b37224e15ee74d64d1df8b12b.1785179875.git....@redhat.com/
)
Signed-off-by: Michael Tokarev <[email protected]>

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index c20dc5767cd..b2ac868a4b9 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -2561,6 +2561,12 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int 
queue_size,
     if (i == VIRTIO_QUEUE_MAX || queue_size > VIRTQUEUE_MAX_SIZE)
         abort();
 
+    /*
+     * Always set to max queue size for qemu <11.1.  See discussion starting
+     * 
https://lore.kernel.org/qemu-devel/a5cff318f06cd06b37224e15ee74d64d1df8b12b.1785179875.git....@redhat.com/
+     */
+    queue_size = VIRTQUEUE_MAX_SIZE;
+
     vdev->vq[i].vring.num = queue_size;
     vdev->vq[i].vring.num_default = queue_size;
     vdev->vq[i].vring.align = VIRTIO_PCI_VRING_ALIGN;
-- 
2.47.3


Reply via email to