Commit 9f436938c5 for qemu.org

commit 9f436938c52125324e36cf9c13b877aa8aada096
Author: Marc-André Lureau <marcandre.lureau@redhat.com>
Date:   Wed Jul 15 11:27:22 2026 +0400

    hw/display/qxl: validate monitors_config heads[] in phys2virt

    The qxl_phys2virt() call for guest_monitors_config only validates
    sizeof(QXLMonitorsConfig), which covers the fixed header (count and
    max_allowed) since commit 8efec0ef8bbc ("hw/display/qxl: Pass requested
    buffer size to qxl_phys2virt()"), but not the flexible array member
    heads[]. When count == 1, heads[0] is accessed without its memory being
    validated, allowing a guest to cause an out-of-bounds read.

    Include sizeof(QXLHead) in the size passed to qxl_phys2virt() so that
    the first head entry is validated within the guest memory slot, preventing
    guest-visible memory reading.

    Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4027
    Reported-by: Tristan @TristanInSec
    Signed-off-by: Marc-Andre Lureau <marcandre.lureau@redhat.com>
    Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
    Message-ID: <20260715072722.1643289-1-marcandre.lureau@redhat.com>
    Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>

diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index 74258afa58..3df796175c 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -270,7 +270,7 @@ static void qxl_spice_monitors_config_async(PCIQXLDevice *qxl, int replay)
     }

     cfg = qxl_phys2virt(qxl, qxl->guest_monitors_config, MEMSLOT_GROUP_GUEST,
-                        sizeof(QXLMonitorsConfig));
+                        sizeof(QXLMonitorsConfig) + sizeof(QXLHead));
     if (cfg != NULL && cfg->count == 1) {
         qxl->guest_primary.resized = 1;
         qxl->guest_head0_width  = cfg->heads[0].width;