From: Li RongQing <[email protected]>

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: 07536ddda73a07 ("qmp: add QMP commands for virtio/vhost queue-status")
Signed-off-by: Li RongQing <[email protected]>
---
 hw/virtio/virtio-qmp.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/hw/virtio/virtio-qmp.c b/hw/virtio/virtio-qmp.c
index 8b7cd7a..8d190c4 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;
 }
-- 
2.9.4


Reply via email to