I also faced such issue Acked-by: Yonggang Luo <[email protected]>
I Can this be in qemu 11.1? On Sat, Jul 25, 2026 at 6:14 AM Michael S. Tsirkin <[email protected]> wrote: > > 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: 525d82e323 ("virtio: fix queue size validation against allocated maximum") > Fixes: CVE-2026-50626 > Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3882 > Cc: Peter Maydell <[email protected]> > Signed-off-by: Michael S. Tsirkin <[email protected]> > --- > include/hw/virtio/virtio-bus.h | 1 + > include/hw/virtio/virtio-mmio.h | 1 + > hw/core/machine.c | 1 + > hw/virtio/virtio-mmio.c | 7 +++---- > hw/virtio/virtio.c | 11 +++++++++++ > 5 files changed, 17 insertions(+), 4 deletions(-) > > diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h > index 1a2d396156..f80fd71424 100644 > --- a/include/hw/virtio/virtio-bus.h > +++ b/include/hw/virtio/virtio-bus.h > @@ -30,6 +30,7 @@ > #include "qom/object.h" > > #define TYPE_VIRTIO_BUS "virtio-bus" > +#define VIRTIO_QUEUE_SIZE_OVERRIDE "x-override-queue-size" > typedef struct VirtioBusClass VirtioBusClass; > typedef struct VirtioBusState VirtioBusState; > DECLARE_OBJ_CHECKERS(VirtioBusState, VirtioBusClass, > diff --git a/include/hw/virtio/virtio-mmio.h b/include/hw/virtio/virtio-mmio.h > index 1644d09810..0a9069868c 100644 > --- a/include/hw/virtio/virtio-mmio.h > +++ b/include/hw/virtio/virtio-mmio.h > @@ -69,6 +69,7 @@ struct VirtIOMMIOProxy { > /* Fields only used for non-legacy (v2) devices */ > uint32_t guest_features[2]; > VirtIOMMIOQueue vqs[VIRTIO_QUEUE_MAX]; > + uint16_t override_queue_size; > }; > > #endif > diff --git a/hw/core/machine.c b/hw/core/machine.c > index 805148678d..73b4d82b4a 100644 > --- a/hw/core/machine.c > +++ b/hw/core/machine.c > @@ -41,6 +41,7 @@ > #include "hw/arm/smmuv3.h" > > GlobalProperty hw_compat_11_0[] = { > + { "virtio-mmio", VIRTIO_QUEUE_SIZE_OVERRIDE, "1024" }, > { "chardev-vc", "encoding", "cp437" }, > { "tpm-crb", "cap-chunk", "off" }, > { "tpm-crb", "x-allow-chunk-migration", "off" }, > diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c > index 58c6d46aab..55ceaeef5f 100644 > --- a/hw/virtio/virtio-mmio.c > +++ b/hw/virtio/virtio-mmio.c > @@ -172,10 +172,7 @@ static uint64_t virtio_mmio_read(void *opaque, hwaddr offset, unsigned size) > >> (32 * proxy->host_features_sel); > } > case VIRTIO_MMIO_QUEUE_NUM_MAX: > - if (!virtio_queue_get_num(vdev, vdev->queue_sel)) { > - return 0; > - } > - return VIRTQUEUE_MAX_SIZE; > + return virtio_queue_get_max_num(vdev, vdev->queue_sel); > case VIRTIO_MMIO_QUEUE_PFN: > if (!proxy->legacy) { > qemu_log_mask(LOG_GUEST_ERROR, > @@ -738,6 +735,8 @@ static const Property virtio_mmio_properties[] = { > DEFINE_PROP_BOOL("force-legacy", VirtIOMMIOProxy, legacy, true), > DEFINE_PROP_BIT("ioeventfd", VirtIOMMIOProxy, flags, > VIRTIO_IOMMIO_FLAG_USE_IOEVENTFD_BIT, true), > + DEFINE_PROP_UINT16(VIRTIO_QUEUE_SIZE_OVERRIDE, VirtIOMMIOProxy, > + override_queue_size, 0), > }; > > static void virtio_mmio_realizefn(DeviceState *d, Error **errp) > diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c > index 340bac2607..35f2a50ddb 100644 > --- a/hw/virtio/virtio.c > +++ b/hw/virtio/virtio.c > @@ -2590,6 +2590,17 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size, > if (i == VIRTIO_QUEUE_MAX || queue_size > VIRTQUEUE_MAX_SIZE) > abort(); > > + BusState *qbus = qdev_get_parent_bus(DEVICE(vdev)); > + if (qbus && qbus->parent && > + object_property_find(OBJECT(qbus->parent), VIRTIO_QUEUE_SIZE_OVERRIDE)) { > + int override = object_property_get_int(OBJECT(qbus->parent), > + VIRTIO_QUEUE_SIZE_OVERRIDE, > + &error_abort); > + if (override) { > + queue_size = override; > + } > + } > + > vdev->vq[i].vring.num = queue_size; > vdev->vq[i].vring.num_default = queue_size; > vdev->vq[i].vring.align = VIRTIO_PCI_VRING_ALIGN; > -- > MST > > -- 此致 礼 罗勇刚 Yours sincerely, Yonggang Luo
