Commit 7ad318fe01 for qemu.org

commit 7ad318fe014443e8894f1e78b545a09885d2807a
Author: Li RongQing <lirongqing@baidu.com>
Date:   Sat Sep 12 12:23:43 2026 +0800

    virtio-qmp: Fix out-of-bounds vqs index in vhost queue status

    qmp_x_query_virtio_vhost_queue_status() validates the queue number
    against the vhost device's global range (queue < hdev->vq_index +
    hdev->nvqs), confirming that 'queue' is a global index.  But it then
    indexes hdev->vqs[] directly with that global index.

    hdev->vqs is allocated as g_new0(struct vhost_virtqueue, hdev->nvqs),
    so valid local indices are 0..nvqs-1.  When hdev->vq_index > 0
    (multiqueue vhost-net queue pairs other than the first), every access
    hdev->vqs[queue] reads past the end of the array.

    Use queue - hdev->vq_index to compute the local index, consistent with
    the rest of vhost.c (e.g. vhost_virtqueue_pending/mask).

    Fixes: 07536ddda73a ("qmp: add QMP commands for virtio/vhost queue-status")
    Signed-off-by: Li RongQing <lirongqing@baidu.com>
    Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
    Message-ID: <20260912042343.2362-1-lirongqing@baidu.com>

diff --git a/hw/virtio/virtio-qmp.c b/hw/virtio/virtio-qmp.c
index 8b7cd7a310..8d190c4c70 100644
--- a/hw/virtio/virtio-qmp.c
+++ b/hw/virtio/virtio-qmp.c
@@ -789,6 +789,7 @@ VirtVhostQueueStatus *qmp_x_query_virtio_vhost_queue_status(const char *path,

     VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
     struct vhost_dev *hdev = vdc->get_vhost(vdev);
+    int vq = queue - hdev->vq_index;

     if (queue < hdev->vq_index || queue >= hdev->vq_index + hdev->nvqs) {
         error_setg(errp, "Invalid vhost virtqueue number %d", queue);
@@ -797,15 +798,15 @@ VirtVhostQueueStatus *qmp_x_query_virtio_vhost_queue_status(const char *path,

     status = g_new0(VirtVhostQueueStatus, 1);
     status->name = g_strdup(vdev->name);
-    status->kick = hdev->vqs[queue].kick;
-    status->call = hdev->vqs[queue].call;
-    status->num = hdev->vqs[queue].num;
-    status->desc_phys = hdev->vqs[queue].desc_phys;
-    status->desc_size = hdev->vqs[queue].desc_size;
-    status->avail_phys = hdev->vqs[queue].avail_phys;
-    status->avail_size = hdev->vqs[queue].avail_size;
-    status->used_phys = hdev->vqs[queue].used_phys;
-    status->used_size = hdev->vqs[queue].used_size;
+    status->kick = hdev->vqs[vq].kick;
+    status->call = hdev->vqs[vq].call;
+    status->num = hdev->vqs[vq].num;
+    status->desc_phys = hdev->vqs[vq].desc_phys;
+    status->desc_size = hdev->vqs[vq].desc_size;
+    status->avail_phys = hdev->vqs[vq].avail_phys;
+    status->avail_size = hdev->vqs[vq].avail_size;
+    status->used_phys = hdev->vqs[vq].used_phys;
+    status->used_size = hdev->vqs[vq].used_size;

     return status;
 }