All of lore.kernel.org
 help / color / mirror / Atom feed
* [GIT PULL 00/19] Various fixes
@ 2026-08-25 11:20 Marc-André Lureau
  2026-08-25 11:20 ` [GIT PULL 01/19] hw/misc: fix trace-events Marc-André Lureau
                   ` (19 more replies)
  0 siblings, 20 replies; 25+ messages in thread
From: Marc-André Lureau @ 2026-08-25 11:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: richard.henderson

The following changes since commit 2be159078ea26feac4c9c9902acf8906f1a05c2a:

  Merge tag 'pull-riscv-to-apply-20260824-1' of https://github.com/alistair23/qemu into staging (2026-08-23 23:04:09 -0700)

are available in the Git repository at:

  https://gitlab.com/marcandre.lureau/qemu.git tags/fixes-pr-v1

for you to fetch changes up to a88191a0caecdfba440682e3c120b439681ccaca:

  hw/input/ps2: say why unknown keyboard commands draw a resend (2026-08-25 15:20:44 +0400)

----------------------------------------------------------------
Various fixes

Collect various graphics & chardev fixes, and some others.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

----------------------------------------------------------------
Akihiko Odaki (5):
      hw/display/virtio-gpu: Avoid creating empty udmabuf
      hw/display/virtio-gpu: Avoid mmap() for empty blob
      hw/display/virtio-gpu: Propagate udmabuf errors
      hw/display/virtio-gpu: Check cursor data presence
      hw/display/virtio-gpu: Validate resource per command

Christian Quante (2):
      hw/input/ps2: answer unknown mouse commands with a resend
      hw/input/ps2: say why unknown keyboard commands draw a resend

Fabiano Rosas (1):
      chardev: Don't unregister yank upon async path connection failure

Marc-André Lureau (10):
      hw/misc: fix trace-events
      migration/multifd: fix Error leak in multifd_recv_terminate_threads()
      hw/core/machine: fix fdt memory leak
      hw/display/qxl: validate primary surface stride against width
      virtio-gpu: use g_try_malloc to avoid guest-triggered abort
      crypto: fix build against nettle >= 4
      tests: tag slow tests with 'slow' suite for easy filtering
      ui/egl: fix render node cleanup order
      ui/egl: fix qemu_egl_display type
      tests/functional: fix pylint false positives for cv2 module

Warisjeet Singh (1):
      hw/display/vga: fix text-mode OOB write after a graphics surface switch

 chardev/char-socket.c                   |   5 -
 contrib/vhost-user-gpu/vhost-user-gpu.c |  25 ++--
 contrib/vhost-user-gpu/virgl.c          |   6 +-
 contrib/vhost-user-gpu/vugbm.c          |   5 +-
 crypto/hash-nettle.c                    |   3 +-
 hw/core/machine.c                       |   1 +
 hw/display/qxl-render.c                 |  66 +++++----
 hw/display/qxl.c                        |  59 +++++++++
 hw/display/qxl.h                        |   2 +
 hw/display/vga.c                        |  37 +++---
 hw/display/vga_int.h                    |   3 +-
 hw/display/virtio-gpu-rutabaga.c        |  14 +-
 hw/display/virtio-gpu-udmabuf-stubs.c   |   3 +-
 hw/display/virtio-gpu-udmabuf.c         |  17 ++-
 hw/display/virtio-gpu-virgl.c           |   6 +-
 hw/display/virtio-gpu.c                 | 228 ++++++++++++++++++++------------
 hw/input/ps2.c                          |  10 ++
 hw/misc/trace-events                    |   6 +
 include/hw/virtio/virtio-gpu.h          |   2 +-
 include/ui/egl-helpers.h                |   2 +-
 migration/multifd.c                     |   1 +
 tests/functional/pylintrc               |   6 +
 tests/qtest/meson.build                 |   3 +-
 tests/unit/meson.build                  |   9 +-
 ui/egl-helpers.c                        |  17 ++-
 25 files changed, 372 insertions(+), 164 deletions(-)



^ permalink raw reply	[flat|nested] 25+ messages in thread

* [GIT PULL 01/19] hw/misc: fix trace-events
  2026-08-25 11:20 [GIT PULL 00/19] Various fixes Marc-André Lureau
@ 2026-08-25 11:20 ` Marc-André Lureau
  2026-08-25 11:20 ` [GIT PULL 02/19] migration/multifd: fix Error leak in multifd_recv_terminate_threads() Marc-André Lureau
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2026-08-25 11:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: richard.henderson

The commit 8041d1730871 accidentally removed the vmlaunchupdate.c
trace events.

Fixes: 8041d1730871 ("tests/qtest: add test for K230 gsdma")
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Luigi Leonardi <leonardi@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260825074114.853069-1-marcandre.lureau@redhat.com>
---
 hw/misc/trace-events | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index 16db4ba0cc17..0b8be3d0f226 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -446,3 +446,9 @@ iommu_testdev_dma_armed(bool armed) "armed=%d"
 # k230_decomp_gzip.c
 k230_decomp_gzip_read(uint64_t offset, unsigned int size, uint64_t value) "K230 DECOMP GZIP read: [0x%"PRIx64"] size %u -> 0x%"PRIx64
 k230_decomp_gzip_write(uint64_t offset, unsigned int size, uint64_t value) "K230 DECOMP GZIP write: [0x%"PRIx64"] size %u <- 0x%"PRIx64
+
+# vmlaunchupdate.c
+launch_update_write(void) ""
+vmlaunch_reset_enter(void) ""
+vm_launchupdate_finalize(void) ""
+restore_host_x86_igvm(void) ""

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [GIT PULL 02/19] migration/multifd: fix Error leak in multifd_recv_terminate_threads()
  2026-08-25 11:20 [GIT PULL 00/19] Various fixes Marc-André Lureau
  2026-08-25 11:20 ` [GIT PULL 01/19] hw/misc: fix trace-events Marc-André Lureau
@ 2026-08-25 11:20 ` Marc-André Lureau
  2026-08-25 11:20 ` [GIT PULL 03/19] hw/core/machine: fix fdt memory leak Marc-André Lureau
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2026-08-25 11:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: richard.henderson, Peter Xu, Fabiano Rosas

If err != NULL, free it.

Fixes: 11dd7be57524 ("migration/multifd: Remove p->quit from recv side")
Reviewed-by: Fabiano Rosas <farosas@suse.de>
Reviewed-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260727-fix2-v2-11-d0c4831ed7ea@redhat.com>
---
 migration/multifd.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/migration/multifd.c b/migration/multifd.c
index dbad525d2a28..503014f76ba5 100644
--- a/migration/multifd.c
+++ b/migration/multifd.c
@@ -1056,6 +1056,7 @@ static void multifd_recv_terminate_threads(Error *err)
     trace_multifd_recv_terminate_threads(err != NULL);
 
     if (qatomic_xchg(&multifd_recv_state->exiting, 1)) {
+        error_free(err);
         return;
     }
 

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [GIT PULL 03/19] hw/core/machine: fix fdt memory leak
  2026-08-25 11:20 [GIT PULL 00/19] Various fixes Marc-André Lureau
  2026-08-25 11:20 ` [GIT PULL 01/19] hw/misc: fix trace-events Marc-André Lureau
  2026-08-25 11:20 ` [GIT PULL 02/19] migration/multifd: fix Error leak in multifd_recv_terminate_threads() Marc-André Lureau
@ 2026-08-25 11:20 ` Marc-André Lureau
  2026-08-25 11:20 ` [GIT PULL 04/19] hw/display/qxl: validate primary surface stride against width Marc-André Lureau
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2026-08-25 11:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: richard.henderson, Philippe Mathieu-Daudé, Zhao Liu

The MachineState fdt field is allocated by various machine types via
create_device_tree(), load_device_tree(), or similar, but was never
freed in machine_finalize(). Add the missing g_free() call.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260709111249.1107640-1-marcandre.lureau@redhat.com>
---
 hw/core/machine.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index e617f7804d4e..8939ae16666c 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -1314,6 +1314,7 @@ static void machine_finalize(Object *obj)
     g_free(ms->nvdimms_state);
     g_free(ms->numa_state);
     g_free(ms->audiodev);
+    g_free(ms->fdt);
 }
 
 bool machine_usb(MachineState *machine)

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [GIT PULL 04/19] hw/display/qxl: validate primary surface stride against width
  2026-08-25 11:20 [GIT PULL 00/19] Various fixes Marc-André Lureau
                   ` (2 preceding siblings ...)
  2026-08-25 11:20 ` [GIT PULL 03/19] hw/core/machine: fix fdt memory leak Marc-André Lureau
@ 2026-08-25 11:20 ` Marc-André Lureau
  2026-08-25 11:20 ` [GIT PULL 05/19] virtio-gpu: use g_try_malloc to avoid guest-triggered abort Marc-André Lureau
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2026-08-25 11:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: richard.henderson

The existing validation in qxl_create_guest_primary() checks that
abs(stride) * height fits in vgamem_size and that stride is 4-byte
aligned, but never checks that abs(stride) is large enough to hold one
row of pixels for the declared width and format.

A malicious guest can create a primary surface with a stride much
smaller than width * bytes_per_pixel (e.g. stride=4 for a 64-wide 32bpp
surface). The spice server rejects this via red_validate_surface(), but
the return is void and QEMU unconditionally proceeds to set up the local
rendering state. On the next display refresh, VNC or SDL reads width *
bytes_pp per scanline from a region backed by only stride bytes per
row, causing a host-side out-of-bounds read.

Add three checks in qxl_create_guest_primary() before creating the
surface:
 - reject unknown surface formats
 - reject zero width or height
 - reject surfaces where abs(stride) < width * bytes_per_pixel

Also fix three related issues in qxl-render.c:
 - qxl_blit() used abs_stride to advance the dst pointer into the
   DisplaySurface, but when stride is negative the DisplaySurface is a
   packed buffer whose stride may be smaller. Use surface_stride()
   instead.
 - qxl_render_update_area_unlocked() uses guest_head0_width (set via
   QXL_IO_MONITORS_CONFIG_ASYNC) without validating it against
   abs_stride, bypassing the new validation. Clamp the effective width
   to abs_stride / bytes_pp to prevent out-of-bounds access while
   tolerating the normal transient where the monitor config arrives
   before the primary surface is resized to match.
 - Similarly, guest_head0_height bypasses qxl_create_guest_primary()
   validation. Without clamping, abs_stride * height can overrun
   vgamem_size, and the product can also overflow 32 bits (e.g.
   abs_stride=16 MiB, height=256 wraps to zero), defeating the
   qxl_phys2virt() bounds check. Clamp height to
   vgamem_size / abs_stride to prevent both.

While touch it, fix some endianness issues.

Fixes: CVE-2026-16271
Fixes: a19cbfb34642 ("spice: add qxl device")
Fixes: 979f7ef8966b ("qxl: use guest_monitor_config for local renderer.")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3637
Reported-by: huntr bubble
Signed-off-by: Marc-Andre Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Message-ID: <20260806094028.640676-1-marcandre.lureau@redhat.com>
---
 hw/display/qxl-render.c | 66 ++++++++++++++++++++++++++++++-------------------
 hw/display/qxl.c        | 59 +++++++++++++++++++++++++++++++++++++++++++
 hw/display/qxl.h        |  2 ++
 3 files changed, 101 insertions(+), 26 deletions(-)

diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c
index 4799c9e8befd..348ddba76890 100644
--- a/hw/display/qxl-render.c
+++ b/hw/display/qxl-render.c
@@ -27,6 +27,7 @@
 static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect)
 {
     DisplaySurface *surface = qemu_console_surface(qxl->vga.con);
+    int dst_stride = surface_stride(surface);
     uint8_t *dst = surface_data(surface);
     uint8_t *src;
     int len, i;
@@ -45,14 +46,14 @@ static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect)
     } else {
         src += rect->top * qxl->guest_primary.abs_stride;
     }
-    dst += rect->top  * qxl->guest_primary.abs_stride;
+    dst += rect->top  * dst_stride;
     src += rect->left * qxl->guest_primary.bytes_pp;
     dst += rect->left * qxl->guest_primary.bytes_pp;
     len  = (rect->right - rect->left) * qxl->guest_primary.bytes_pp;
 
     for (i = rect->top; i < rect->bottom; i++) {
         memcpy(dst, src, len);
-        dst += qxl->guest_primary.abs_stride;
+        dst += dst_stride;
         src += qxl->guest_primary.qxl_stride;
     }
 }
@@ -61,30 +62,13 @@ void qxl_render_resize(PCIQXLDevice *qxl)
 {
     QXLSurfaceCreate *sc = &qxl->guest_primary.surface;
 
-    qxl->guest_primary.qxl_stride = sc->stride;
-    qxl->guest_primary.abs_stride = abs(sc->stride);
+    qxl->guest_primary.qxl_stride = le32_to_cpu(sc->stride);
+    qxl->guest_primary.abs_stride = abs(qxl->guest_primary.qxl_stride);
     qxl->guest_primary.resized++;
-    switch (sc->format) {
-    case SPICE_SURFACE_FMT_16_555:
-        qxl->guest_primary.bytes_pp = 2;
-        qxl->guest_primary.bits_pp = 15;
-        break;
-    case SPICE_SURFACE_FMT_16_565:
-        qxl->guest_primary.bytes_pp = 2;
-        qxl->guest_primary.bits_pp = 16;
-        break;
-    case SPICE_SURFACE_FMT_32_xRGB:
-    case SPICE_SURFACE_FMT_32_ARGB:
-        qxl->guest_primary.bytes_pp = 4;
-        qxl->guest_primary.bits_pp = 32;
-        break;
-    default:
-        fprintf(stderr, "%s: unhandled format: %x\n", __func__,
-                qxl->guest_primary.surface.format);
-        qxl->guest_primary.bytes_pp = 4;
-        qxl->guest_primary.bits_pp = 32;
-        break;
-    }
+    /* fallback to default bpp if format is unknown */
+    qxl_format_bpp(qxl, le32_to_cpu(sc->format),
+                   &qxl->guest_primary.bytes_pp,
+                   &qxl->guest_primary.bits_pp);
 }
 
 static void qxl_set_rect_to_surface(PCIQXLDevice *qxl, QXLRect *area)
@@ -101,15 +85,45 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
     DisplaySurface *surface;
     int width = qxl->guest_head0_width ?: qxl->guest_primary.surface.width;
     int height = qxl->guest_head0_height ?: qxl->guest_primary.surface.height;
+    uint64_t map_height;
     int i;
 
+    if (width <= 0 || height <= 0) {
+        goto end;
+    }
+
+    if (qxl->guest_primary.bytes_pp > 0) {
+        int max_width = qxl->guest_primary.abs_stride
+                        / qxl->guest_primary.bytes_pp;
+        width = MIN(width, max_width);
+    }
+
+    if (qxl->guest_primary.qxl_stride < 0) {
+        /* qxl_blit() uses the primary height to find the first scanline. */
+        height = MIN(height, (int)qxl->guest_primary.surface.height);
+    }
+
+    if (qxl->guest_primary.abs_stride > 0) {
+        int max_height = qxl->vgamem_size / qxl->guest_primary.abs_stride;
+        height = MIN(height, max_height);
+    }
+
+    /*
+     * height limits the visible update, while map_height is the guest memory
+     * span validated by qxl_phys2virt().  With a negative stride qxl_blit()
+     * addresses scanlines from the declared primary height, so a shorter
+     * monitor still requires validating the full primary surface.
+     */
+    map_height = qxl->guest_primary.qxl_stride < 0 ?
+                 qxl->guest_primary.surface.height : height;
+
     if (qxl->guest_primary.resized) {
         qxl->guest_primary.resized = 0;
         qxl->guest_primary.data = qxl_phys2virt(qxl,
                                                 qxl->guest_primary.surface.mem,
                                                 MEMSLOT_GROUP_GUEST,
                                                 qxl->guest_primary.abs_stride
-                                                * height);
+                                                * map_height);
         if (!qxl->guest_primary.data) {
             goto end;
         }
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index b7d871b9ee33..384b8767b8e6 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -1489,6 +1489,47 @@ static void qxl_create_guest_primary_complete(PCIQXLDevice *qxl)
     qxl_render_resize(qxl);
 }
 
+/*
+ * Convert a SpiceSurfaceFormat to bytes per pixel and bits per pixel.
+ *
+ * Only valid for surface suitable for rendering.
+ */
+bool qxl_format_bpp(PCIQXLDevice *qxl, SpiceSurfaceFmt format,
+                    uint32_t *bytes_pp, uint32_t *bits_pp)
+{
+    uint32_t bypp = 4;
+    uint32_t bipp = 32;
+    bool ret = true;
+
+    switch (format) {
+    case SPICE_SURFACE_FMT_16_555:
+        bypp = 2;
+        bipp = 15;
+        break;
+    case SPICE_SURFACE_FMT_16_565:
+        bypp = 2;
+        bipp = 16;
+        break;
+    case SPICE_SURFACE_FMT_32_xRGB:
+    case SPICE_SURFACE_FMT_32_ARGB:
+        bypp = 4;
+        bipp = 32;
+        break;
+    default:
+        ret = false;
+        qxl_set_guest_bug(qxl, "%s: unhandled format: %x", __func__, format);
+    }
+
+    if (bytes_pp != NULL) {
+        *bytes_pp = bypp;
+    }
+    if (bits_pp != NULL) {
+        *bits_pp = bipp;
+    }
+
+    return ret;
+}
+
 static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm,
                                      qxl_async_io async)
 {
@@ -1496,6 +1537,7 @@ static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm,
     QXLSurfaceCreate *sc = &qxl->guest_primary.surface;
     uint32_t requested_height = le32_to_cpu(sc->height);
     int requested_stride = le32_to_cpu(sc->stride);
+    uint32_t bytes_pp;
 
     if (requested_stride == INT32_MIN ||
         abs(requested_stride) * (uint64_t)requested_height
@@ -1532,6 +1574,23 @@ static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm,
         return;
     }
 
+    if (!qxl_format_bpp(qxl, surface.format, &bytes_pp, NULL)) {
+        return;
+    }
+
+    if (surface.width == 0 || surface.height == 0) {
+        qxl_set_guest_bug(qxl, "%s: zero dimension %ux%u",
+                          __func__, surface.width, surface.height);
+        return;
+    }
+
+    if ((uint64_t)surface.width * bytes_pp > abs(surface.stride)) {
+        qxl_set_guest_bug(qxl, "%s: stride too small for width:"
+                          " stride %d width %u bpp %u",
+                          __func__, surface.stride, surface.width, bytes_pp);
+        return;
+    }
+
     surface.mouse_mode = true;
     surface.group_id   = MEMSLOT_GROUP_GUEST;
     if (loadvm) {
diff --git a/hw/display/qxl.h b/hw/display/qxl.h
index 48d664f77736..6f5b96fe86cc 100644
--- a/hw/display/qxl.h
+++ b/hw/display/qxl.h
@@ -181,6 +181,8 @@ void qxl_spice_oom(PCIQXLDevice *qxl);
 void qxl_spice_reset_memslots(PCIQXLDevice *qxl);
 void qxl_spice_reset_image_cache(PCIQXLDevice *qxl);
 void qxl_spice_reset_cursor(PCIQXLDevice *qxl);
+bool qxl_format_bpp(PCIQXLDevice *qxl, SpiceSurfaceFmt format,
+                    uint32_t *bytes_pp, uint32_t *bits_pp);
 
 /* qxl-logger.c */
 int qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id);

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [GIT PULL 05/19] virtio-gpu: use g_try_malloc to avoid guest-triggered abort
  2026-08-25 11:20 [GIT PULL 00/19] Various fixes Marc-André Lureau
                   ` (3 preceding siblings ...)
  2026-08-25 11:20 ` [GIT PULL 04/19] hw/display/qxl: validate primary surface stride against width Marc-André Lureau
@ 2026-08-25 11:20 ` Marc-André Lureau
  2026-09-03 19:36   ` Peter Maydell
  2026-08-25 11:20 ` [GIT PULL 06/19] crypto: fix build against nettle >= 4 Marc-André Lureau
                   ` (14 subsequent siblings)
  19 siblings, 1 reply; 25+ messages in thread
From: Marc-André Lureau @ 2026-08-25 11:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: richard.henderson, Michael S. Tsirkin, Stefano Garzarella,
	Marc-André Lureau, Alex Bennée, Akihiko Odaki,
	Dmitry Osipenko

Use g_try_malloc/g_try_new0 for guest-controlled allocation, so failure
returns an error to the guest rather than crashing the host (glib
behaviour).

Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3898
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260805130141.211398-1-marcandre.lureau@redhat.com>
---
 contrib/vhost-user-gpu/vhost-user-gpu.c | 25 +++++++++++++-------
 contrib/vhost-user-gpu/virgl.c          |  6 ++++-
 contrib/vhost-user-gpu/vugbm.c          |  5 +++-
 hw/display/virtio-gpu-rutabaga.c        | 14 +++++++++--
 hw/display/virtio-gpu-udmabuf.c         |  7 ++++--
 hw/display/virtio-gpu-virgl.c           |  6 ++++-
 hw/display/virtio-gpu.c                 | 42 ++++++++++++++++++++++++---------
 7 files changed, 79 insertions(+), 26 deletions(-)

diff --git a/contrib/vhost-user-gpu/vhost-user-gpu.c b/contrib/vhost-user-gpu/vhost-user-gpu.c
index 786488150932..933bdbb671c0 100644
--- a/contrib/vhost-user-gpu/vhost-user-gpu.c
+++ b/contrib/vhost-user-gpu/vhost-user-gpu.c
@@ -487,7 +487,7 @@ vg_create_mapping_iov(VuGpu *g,
                       struct virtio_gpu_ctrl_command *cmd,
                       struct iovec **iov)
 {
-    struct virtio_gpu_mem_entry *ents;
+    g_autofree struct virtio_gpu_mem_entry *ents = NULL;
     size_t esize, s;
     int i;
 
@@ -498,17 +498,22 @@ vg_create_mapping_iov(VuGpu *g,
     }
 
     esize = sizeof(*ents) * ab->nr_entries;
-    ents = g_malloc(esize);
+    ents = g_try_malloc(esize);
+    if (!ents && esize) {
+        return -1;
+    }
     s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
                    sizeof(*ab), ents, esize);
     if (s != esize) {
         g_critical("%s: command data size incorrect %zu vs %zu",
                    __func__, s, esize);
-        g_free(ents);
         return -1;
     }
 
-    *iov = g_new0(struct iovec, ab->nr_entries);
+    *iov = g_try_new0(struct iovec, ab->nr_entries);
+    if (!*iov && ab->nr_entries) {
+        return -1;
+    }
     for (i = 0; i < ab->nr_entries; i++) {
         uint64_t len = ents[i].length;
         (*iov)[i].iov_len = ents[i].length;
@@ -517,12 +522,10 @@ vg_create_mapping_iov(VuGpu *g,
             g_critical("%s: resource %d element %d",
                        __func__, ab->resource_id, i);
             g_free(*iov);
-            g_free(ents);
             *iov = NULL;
             return -1;
         }
     }
-    g_free(ents);
     return 0;
 }
 
@@ -828,8 +831,14 @@ vg_resource_flush(VuGpu *g,
                 PIXMAN_FORMAT_BPP(pixman_image_get_format(res->image)) / 8;
             size_t size = width * height * bpp;
 
-            void *p = g_malloc(VHOST_USER_GPU_HDR_SIZE +
-                               sizeof(VhostUserGpuUpdate) + size);
+            void *p = g_try_malloc(VHOST_USER_GPU_HDR_SIZE +
+                                   sizeof(VhostUserGpuUpdate) + size);
+            if (!p) {
+                pixman_region_fini(&region);
+                pixman_region_fini(&finalregion);
+                cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
+                break;
+            }
             VhostUserGpuMsg *msg = p;
             msg->request = VHOST_USER_GPU_UPDATE;
             msg->size = sizeof(VhostUserGpuUpdate) + size;
diff --git a/contrib/vhost-user-gpu/virgl.c b/contrib/vhost-user-gpu/virgl.c
index 550fd03bf5c4..20bae57d0fe4 100644
--- a/contrib/vhost-user-gpu/virgl.c
+++ b/contrib/vhost-user-gpu/virgl.c
@@ -209,7 +209,11 @@ virgl_cmd_submit_3d(VuGpu *g,
         return;
     }
 
-    buf = g_malloc(cs.size);
+    buf = g_try_malloc(cs.size);
+    if (!buf && cs.size) {
+        cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
+        return;
+    }
     s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
                    sizeof(cs), buf, cs.size);
     if (s != cs.size) {
diff --git a/contrib/vhost-user-gpu/vugbm.c b/contrib/vhost-user-gpu/vugbm.c
index 710d54529779..e2d8385fd857 100644
--- a/contrib/vhost-user-gpu/vugbm.c
+++ b/contrib/vhost-user-gpu/vugbm.c
@@ -13,7 +13,10 @@
 static bool
 mem_alloc_bo(struct vugbm_buffer *buf)
 {
-    buf->mmap = g_malloc((uint64_t)buf->width * buf->height * 4);
+    buf->mmap = g_try_malloc((uint64_t)buf->width * buf->height * 4);
+    if (!buf->mmap && buf->width && buf->height) {
+        return false;
+    }
     buf->stride = buf->width * 4;
     return true;
 }
diff --git a/hw/display/virtio-gpu-rutabaga.c b/hw/display/virtio-gpu-rutabaga.c
index a054f8117f14..041216a10d04 100644
--- a/hw/display/virtio-gpu-rutabaga.c
+++ b/hw/display/virtio-gpu-rutabaga.c
@@ -366,10 +366,20 @@ rutabaga_cmd_submit_3d(VirtIOGPU *g,
         return;
     }
 
-    buf = g_new0(uint8_t, cs.size);
+    buf = g_try_new0(uint8_t, cs.size);
+    if (!buf && cs.size) {
+        cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
+        return;
+    }
     s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
                    sizeof(cs), buf, cs.size);
-    CHECK(s == cs.size, cmd);
+    if (s != cs.size) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: size mismatch (%zu/%u)\n",
+                      __func__, s, cs.size);
+        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+        return;
+    }
 
     rutabaga_cmd.ctx_id = cs.hdr.ctx_id;
     rutabaga_cmd.cmd = buf;
diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c
index 5f08c855dde1..816f52a51457 100644
--- a/hw/display/virtio-gpu-udmabuf.c
+++ b/hw/display/virtio-gpu-udmabuf.c
@@ -39,8 +39,11 @@ static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res)
         return;
     }
 
-    list = g_malloc0(sizeof(struct udmabuf_create_list) +
-                     sizeof(struct udmabuf_create_item) * res->iov_cnt);
+    list = g_try_malloc0(sizeof(struct udmabuf_create_list) +
+                         sizeof(struct udmabuf_create_item) * res->iov_cnt);
+    if (!list) {
+        return;
+    }
 
     for (i = 0; i < res->iov_cnt; i++) {
         rcu_read_lock();
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 6e298f997d66..9bda572426b2 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -620,7 +620,11 @@ static void virgl_cmd_submit_3d(VirtIOGPU *g,
         return;
     }
 
-    buf = g_malloc(cs.size);
+    buf = g_try_malloc(cs.size);
+    if (!buf && cs.size) {
+        cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
+        return;
+    }
     s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
                    sizeof(cs), buf, cs.size);
     if (s != cs.size) {
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index fbb6fec7a0ad..9eb010082d0d 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -892,7 +892,10 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
     }
 
     esize = sizeof(*ents) * nr_entries;
-    ents = g_malloc(esize);
+    ents = g_try_malloc(esize);
+    if (!ents && esize) {
+        return -1;
+    }
     s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
                    offset, ents, esize);
     if (s != esize) {
@@ -913,6 +916,7 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
         hwaddr len;
         void *map;
 
+        /* TODO: a common DMA map SG helper */
         do {
             len = l;
             map = dma_memory_map(VIRTIO_DEVICE(g)->dma_as, a, &len,
@@ -921,20 +925,27 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
             if (!map) {
                 qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO memory for"
                               " element %d\n", __func__, e);
-                virtio_gpu_cleanup_mapping_iov(g, *iov, v);
-                g_free(ents);
-                *iov = NULL;
-                if (addr) {
-                    g_free(*addr);
-                    *addr = NULL;
-                }
-                return -1;
+                goto err;
             }
 
             if (!(v % 16)) {
-                *iov = g_renew(struct iovec, *iov, v + 16);
+                struct iovec *new_iov;
+                new_iov = g_try_renew(struct iovec, *iov, v + 16);
+                if (!new_iov) {
+                    dma_memory_unmap(VIRTIO_DEVICE(g)->dma_as, map, len,
+                                     DMA_DIRECTION_TO_DEVICE, len);
+                    goto err;
+                }
+                *iov = new_iov;
                 if (addr) {
-                    *addr = g_renew(uint64_t, *addr, v + 16);
+                    uint64_t *new_addr;
+                    new_addr = g_try_renew(uint64_t, *addr, v + 16);
+                    if (!new_addr) {
+                        dma_memory_unmap(VIRTIO_DEVICE(g)->dma_as, map, len,
+                                         DMA_DIRECTION_TO_DEVICE, len);
+                        goto err;
+                    }
+                    *addr = new_addr;
                 }
             }
             (*iov)[v].iov_base = map;
@@ -952,6 +963,15 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
 
     g_free(ents);
     return 0;
+
+err:
+    virtio_gpu_cleanup_mapping_iov(g, *iov, v);
+    *iov = NULL;
+    if (addr) {
+        g_clear_pointer(addr, g_free);
+    }
+    g_free(ents);
+    return -1;
 }
 
 void virtio_gpu_cleanup_mapping_iov(VirtIOGPU *g,

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [GIT PULL 06/19] crypto: fix build against nettle >= 4
  2026-08-25 11:20 [GIT PULL 00/19] Various fixes Marc-André Lureau
                   ` (4 preceding siblings ...)
  2026-08-25 11:20 ` [GIT PULL 05/19] virtio-gpu: use g_try_malloc to avoid guest-triggered abort Marc-André Lureau
@ 2026-08-25 11:20 ` Marc-André Lureau
  2026-08-25 11:54   ` Daniel P. Berrangé
  2026-08-25 11:20 ` [GIT PULL 07/19] tests: tag slow tests with 'slow' suite for easy filtering Marc-André Lureau
                   ` (13 subsequent siblings)
  19 siblings, 1 reply; 25+ messages in thread
From: Marc-André Lureau @ 2026-08-25 11:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: richard.henderson, Daniel P. Berrangé

sha.h has been deprecated. It seems we can rely on sha1.h/sha2.h
since we depend on >= 3.7.3.

Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4184
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 crypto/hash-nettle.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/crypto/hash-nettle.c b/crypto/hash-nettle.c
index 53f68301efb5..2589bbf4c10e 100644
--- a/crypto/hash-nettle.c
+++ b/crypto/hash-nettle.c
@@ -24,7 +24,8 @@
 #include "crypto/hash.h"
 #include "hashpriv.h"
 #include <nettle/md5.h>
-#include <nettle/sha.h>
+#include <nettle/sha1.h>
+#include <nettle/sha2.h>
 #include <nettle/ripemd160.h>
 #ifdef CONFIG_CRYPTO_SM3
 #include <nettle/sm3.h>

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [GIT PULL 07/19] tests: tag slow tests with 'slow' suite for easy filtering
  2026-08-25 11:20 [GIT PULL 00/19] Various fixes Marc-André Lureau
                   ` (5 preceding siblings ...)
  2026-08-25 11:20 ` [GIT PULL 06/19] crypto: fix build against nettle >= 4 Marc-André Lureau
@ 2026-08-25 11:20 ` Marc-André Lureau
  2026-08-25 11:20 ` [GIT PULL 08/19] ui/egl: fix render node cleanup order Marc-André Lureau
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2026-08-25 11:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: richard.henderson, Fabiano Rosas, Laurent Vivier, Paolo Bonzini

Add several RCU and thread-pool unit tests to the slow_tests dict,
and tag all slow tests (both qtest and unit) with a 'slow' suite so
they can be excluded or selected via meson test --suite/--no-suite.

Acked-by: Fabiano Rosas <farosas@suse.de>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260512065633.3542562-1-marcandre.lureau@redhat.com>
---
 tests/qtest/meson.build | 3 ++-
 tests/unit/meson.build  | 9 ++++++++-
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 739df71d8d0b..cbdef5a54550 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -510,6 +510,7 @@ foreach dir : target_dirs
          protocol: 'tap',
          timeout: slow_qtests.get(test, 60),
          priority: slow_qtests.get(test, 60),
-         suite: ['qtest', 'qtest-' + target_base])
+         suite: ['qtest', 'qtest-' + target_base] +
+                (slow_qtests.has_key(test) ? ['slow'] : []))
   endforeach
 endforeach
diff --git a/tests/unit/meson.build b/tests/unit/meson.build
index dc3fb954c03a..3a9866c1f2be 100644
--- a/tests/unit/meson.build
+++ b/tests/unit/meson.build
@@ -184,6 +184,12 @@ slow_tests = {
   'test-crypto-tlscredsx509': 90,
   'test-crypto-tlssession': 90,
   'test-replication': 60,
+  'rcutorture': 30,
+  'test-rcu-list': 30,
+  'test-rcu-simpleq': 30,
+  'test-rcu-tailq': 30,
+  'test-rcu-slist': 30,
+  'test-thread-pool': 30,
 }
 
 foreach test_name, extra: tests
@@ -205,5 +211,6 @@ foreach test_name, extra: tests
        protocol: 'tap',
        timeout: slow_tests.get(test_name, 30),
        priority: slow_tests.get(test_name, 30),
-       suite: ['unit'])
+       suite: ['unit'] +
+              (slow_tests.has_key(test_name) ? ['slow'] : []))
 endforeach

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [GIT PULL 08/19] ui/egl: fix render node cleanup order
  2026-08-25 11:20 [GIT PULL 00/19] Various fixes Marc-André Lureau
                   ` (6 preceding siblings ...)
  2026-08-25 11:20 ` [GIT PULL 07/19] tests: tag slow tests with 'slow' suite for easy filtering Marc-André Lureau
@ 2026-08-25 11:20 ` Marc-André Lureau
  2026-08-25 11:20 ` [GIT PULL 09/19] ui/egl: fix qemu_egl_display type Marc-André Lureau
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2026-08-25 11:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: richard.henderson, Marc-André Lureau

ASAN detected some memory leaks when terminating. Release thread-bound
EGL state first, destroy the context and terminate the display while the
GBM device is still alive, then destroy GBM and close the render-node
fd.

Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Fixes: a3cf9b55bbdc ("ui/egl: implement display and EGL cleanup")
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260820132014.2729748-1-marcandre.lureau@redhat.com>
---
 ui/egl-helpers.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
index d689f187c4e5..e89cc7c49af6 100644
--- a/ui/egl-helpers.c
+++ b/ui/egl-helpers.c
@@ -736,19 +736,22 @@ bool egl_init(const char *rendernode, DisplayGLMode mode, Error **errp)
 
 void egl_cleanup(void)
 {
+    if (qemu_egl_display) {
+        eglReleaseThread();
+    }
+
     if (qemu_egl_rn_ctx) {
         eglDestroyContext(qemu_egl_display, qemu_egl_rn_ctx);
         qemu_egl_rn_ctx = NULL;
     }
 
+    if (qemu_egl_display) {
+        eglTerminate(qemu_egl_display);
+        qemu_egl_display = NULL;
+    }
+
 #ifdef CONFIG_GBM
     g_clear_pointer(&qemu_egl_rn_gbm_dev, gbm_device_destroy);
     g_clear_fd(&qemu_egl_rn_fd, NULL);
 #endif
-
-    if (qemu_egl_display) {
-        eglReleaseThread();
-        eglTerminate(qemu_egl_display);
-        qemu_egl_display = NULL;
-    }
 }

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [GIT PULL 09/19] ui/egl: fix qemu_egl_display type
  2026-08-25 11:20 [GIT PULL 00/19] Various fixes Marc-André Lureau
                   ` (7 preceding siblings ...)
  2026-08-25 11:20 ` [GIT PULL 08/19] ui/egl: fix render node cleanup order Marc-André Lureau
@ 2026-08-25 11:20 ` Marc-André Lureau
  2026-08-25 11:21 ` [GIT PULL 10/19] tests/functional: fix pylint false positives for cv2 module Marc-André Lureau
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2026-08-25 11:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: richard.henderson, Marc-André Lureau

EGLDisplay is already a pointer type (void *), so declaring
qemu_egl_display as EGLDisplay * makes it void **, which
doesn't match any of its usages.

Fixes: 7ced9e9f6da2 ("ui: add egl-helpers")
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260820131933.2729240-1-marcandre.lureau@redhat.com>
---
 include/ui/egl-helpers.h | 2 +-
 ui/egl-helpers.c         | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h
index 405ddd912591..679c79eacd54 100644
--- a/include/ui/egl-helpers.h
+++ b/include/ui/egl-helpers.h
@@ -9,7 +9,7 @@
 #include "ui/console.h"
 #include "ui/shader.h"
 
-extern EGLDisplay *qemu_egl_display;
+extern EGLDisplay qemu_egl_display;
 extern EGLConfig qemu_egl_config;
 extern DisplayGLMode qemu_egl_mode;
 extern bool qemu_egl_angle_d3d;
diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
index e89cc7c49af6..8e3729a54d15 100644
--- a/ui/egl-helpers.c
+++ b/ui/egl-helpers.c
@@ -25,7 +25,7 @@
 #include "trace.h"
 #include "standard-headers/drm/drm_fourcc.h"
 
-EGLDisplay *qemu_egl_display;
+EGLDisplay qemu_egl_display;
 EGLConfig qemu_egl_config;
 DisplayGLMode qemu_egl_mode;
 bool qemu_egl_angle_d3d;

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [GIT PULL 10/19] tests/functional: fix pylint false positives for cv2 module
  2026-08-25 11:20 [GIT PULL 00/19] Various fixes Marc-André Lureau
                   ` (8 preceding siblings ...)
  2026-08-25 11:20 ` [GIT PULL 09/19] ui/egl: fix qemu_egl_display type Marc-André Lureau
@ 2026-08-25 11:21 ` Marc-André Lureau
  2026-08-25 11:21 ` [GIT PULL 11/19] chardev: Don't unregister yank upon async path connection failure Marc-André Lureau
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2026-08-25 11:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: richard.henderson, Thomas Huth, Philippe Mathieu-Daudé,
	Daniel P. Berrangé

Add generated-members=cv2.* to pylintrc so pylint skips member
checking on the cv2 C extension module, whose members are not
visible to static analysis.

Silence:
2026-08-15 10:42:08,710 - INFO: qemu-test.test_pylint Checking files in /home/elmarco/src/qemu.qom-qapi/tests/functional/arm with pylint
2026-08-15 10:42:10,941 - ERROR: qemu-test.test_pylint "/home/elmarco/src/qemu.qom-qapi/tests/functional/arm/test_integratorcp.py:83: E1101: Module 'cv2' has no 'imread' member (no-member)"

Note: I also tried with extension-pkg-allow-list, but that didn't work
for some reason.

Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260815072421.4117291-1-marcandre.lureau@redhat.com>
---
 tests/functional/pylintrc | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/tests/functional/pylintrc b/tests/functional/pylintrc
index 949bea611fe4..373aabd6ca3f 100644
--- a/tests/functional/pylintrc
+++ b/tests/functional/pylintrc
@@ -79,6 +79,12 @@ disable=bad-inline-option,
         useless-suppression,
 
 
+[TYPECHECK]
+
+# cv2 is a C extension module whose members are not visible to pylint
+generated-members=cv2.*
+
+
 [SIMILARITIES]
 
 # Minimum lines number of a similarity.

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [GIT PULL 11/19] chardev: Don't unregister yank upon async path connection failure
  2026-08-25 11:20 [GIT PULL 00/19] Various fixes Marc-André Lureau
                   ` (9 preceding siblings ...)
  2026-08-25 11:21 ` [GIT PULL 10/19] tests/functional: fix pylint false positives for cv2 module Marc-André Lureau
@ 2026-08-25 11:21 ` Marc-André Lureau
  2026-08-25 11:21 ` [GIT PULL 12/19] hw/display/vga: fix text-mode OOB write after a graphics surface switch Marc-André Lureau
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2026-08-25 11:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: richard.henderson, Marc-André Lureau, Paolo Bonzini

From: Fabiano Rosas <farosas@suse.de>

Commit 5c102ac9 ("chardev: Consolidate yank registration") has moved
yank registration in the tcp_chr_connect_client_async() path to after
the connection is successful. If qio_channel_socket_connect_sync()
fails early, there will be no yank registered to be unregistered in
the error path, leading to assert.

Remove the now-extraneous unregister.

Cc: qemu-stable@nongnu.org
Fixes: 5c102ac9 ("chardev: Consolidate yank registration")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3528
Signed-off-by: Fabiano Rosas <farosas@suse.de>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260603141137.1108963-1-farosas@suse.de>
---
 chardev/char-socket.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index b629575fcf80..81bac42a1587 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -1128,11 +1128,6 @@ static void qemu_chr_socket_connected(QIOTask *task, void *opaque)
 
     if (qio_task_propagate_error(task, &err)) {
         tcp_chr_change_state(s, TCP_CHARDEV_STATE_DISCONNECTED);
-        if (s->registered_yank) {
-            yank_unregister_function(CHARDEV_YANK_INSTANCE(chr->label),
-                                     char_socket_yank_iochannel,
-                                     QIO_CHANNEL(sioc));
-        }
         check_report_connect_error(chr, err);
         goto cleanup;
     }

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [GIT PULL 12/19] hw/display/vga: fix text-mode OOB write after a graphics surface switch
  2026-08-25 11:20 [GIT PULL 00/19] Various fixes Marc-André Lureau
                   ` (10 preceding siblings ...)
  2026-08-25 11:21 ` [GIT PULL 11/19] chardev: Don't unregister yank upon async path connection failure Marc-André Lureau
@ 2026-08-25 11:21 ` Marc-André Lureau
  2026-08-25 11:21 ` [GIT PULL 13/19] hw/display/virtio-gpu: Avoid creating empty udmabuf Marc-André Lureau
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2026-08-25 11:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: richard.henderson, Gerd Hoffmann

From: Warisjeet Singh <sinxx198@gmail.com>

vga_draw_text() decides whether the console surface needs a resize from
its geometry cache, but none of the cache terms observe the graphics
renderer having replaced the console surface in between:

- last_width/last_height are shared with vga_draw_graphic(), which
  stores them in pixels while the text path stores characters;
- last_depth stays 0 for legacy (non-VBE) graphics modes, because
  vga_get_bpp() only reports a depth when VBE is enabled, so the
  "s->last_depth" term that normally forces a resize after a graphics
  frame does not fire.

So a graphics frame that shrinks the console surface (e.g. 80x25
pixels) followed by a text frame with matching character geometry
(80x25 chars) skips the resize, and the glyph loop then paints
width*cw x height*cheight pixels into the smaller surface, out of
bounds, with guest-controlled (DAC palette) values, on every display
refresh.

Separate the geometry cache per renderer: text paths (vga_draw_text,
vga_update_text, and the text handling in vga_invalidate_display /
vga_common_reset) now only manipulate last_text_{width,height}, in
characters; last_{width,height} become graphics-only, in pixels.
Additionally, make the text path compare the pixel size it is about
to paint against the console surface's actual dimensions.  The
surface check is the load-bearing term: caches in either unit cannot
see the other renderer swapping the surface, the surface can.

Fixes: CVE-2026-77913
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4215
Cc: qemu-stable@nongnu.org
Signed-off-by: Warisjeet Singh (sin99xx) <sinxx198@gmail.com>
Message-ID: <vga-v3-20260824.sinxx198@gmail.com>
---
 hw/display/vga.c     | 37 ++++++++++++++++++++++---------------
 hw/display/vga_int.h |  3 ++-
 2 files changed, 24 insertions(+), 16 deletions(-)

diff --git a/hw/display/vga.c b/hw/display/vga.c
index da0c331486eb..cb0e28b79b6a 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -1241,7 +1241,10 @@ static void vga_draw_text(VGACommonState *s, int full_update)
         return;
     }
 
-    if (width != s->last_width || height != s->last_height ||
+    if (surface == NULL ||
+        surface_width(surface) != width * cw ||
+        surface_height(surface) != height * cheight ||
+        width != s->last_text_width || height != s->last_text_height ||
         cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
         s->last_scr_width = width * cw;
         s->last_scr_height = height * cheight;
@@ -1249,8 +1252,8 @@ static void vga_draw_text(VGACommonState *s, int full_update)
         surface = qemu_console_surface(s->con);
         qemu_console_text_resize(s->con, width, height);
         s->last_depth = 0;
-        s->last_width = width;
-        s->last_height = height;
+        s->last_text_width = width;
+        s->last_text_height = height;
         s->last_ch = cheight;
         s->last_cw = cw;
         full_update = 1;
@@ -1845,6 +1848,8 @@ static void vga_invalidate_display(void *opaque)
 
     s->last_width = -1;
     s->last_height = -1;
+    s->last_text_width = -1;
+    s->last_text_height = -1;
 }
 
 void vga_common_reset(VGACommonState *s)
@@ -1887,6 +1892,8 @@ void vga_common_reset(VGACommonState *s)
     s->last_ch = 0;
     s->last_width = 0;
     s->last_height = 0;
+    s->last_text_width = 0;
+    s->last_text_height = 0;
     s->last_scr_width = 0;
     s->last_scr_height = 0;
     s->cursor_start = 0;
@@ -1938,8 +1945,8 @@ static void vga_update_text(void *opaque, uint32_t *chardata)
         s->graphic_mode = graphic_mode;
         full_update = 1;
     }
-    if (s->last_width == -1) {
-        s->last_width = 0;
+    if (s->last_text_width == -1) {
+        s->last_text_width = 0;
         full_update = 1;
     }
 
@@ -1978,15 +1985,15 @@ static void vga_update_text(void *opaque, uint32_t *chardata)
             break;
         }
 
-        if (width != s->last_width || height != s->last_height ||
+        if (width != s->last_text_width || height != s->last_text_height ||
             cw != s->last_cw || cheight != s->last_ch) {
             s->last_scr_width = width * cw;
             s->last_scr_height = height * cheight;
             qemu_console_resize(s->con, s->last_scr_width, s->last_scr_height);
             qemu_console_text_resize(s->con, width, height);
             s->last_depth = 0;
-            s->last_width = width;
-            s->last_height = height;
+            s->last_text_width = width;
+            s->last_text_height = height;
             s->last_ch = cheight;
             s->last_cw = cw;
             full_update = 1;
@@ -2071,22 +2078,22 @@ static void vga_update_text(void *opaque, uint32_t *chardata)
     }
 
     /* Display a message */
-    s->last_width = 60;
-    s->last_height = height = 3;
+    s->last_text_width = 60;
+    s->last_text_height = height = 3;
     qemu_console_text_set_cursor(s->con, -1, -1);
-    qemu_console_text_resize(s->con, s->last_width, height);
+    qemu_console_text_resize(s->con, s->last_text_width, height);
 
-    for (dst = chardata, i = 0; i < s->last_width * height; i ++)
+    for (dst = chardata, i = 0; i < s->last_text_width * height; i ++)
         *dst++ = ' ';
 
     size = strlen(msg_buffer);
-    width = (s->last_width - size) / 2;
-    dst = chardata + s->last_width + width;
+    width = (s->last_text_width - size) / 2;
+    dst = chardata + s->last_text_width + width;
     for (i = 0; i < size; i ++)
         *dst++ = ATTR2CHTYPE(msg_buffer[i], QEMU_COLOR_BLUE,
                              QEMU_COLOR_BLACK, 1);
 
-    qemu_console_text_update(s->con, 0, 0, s->last_width, height);
+    qemu_console_text_update(s->con, 0, 0, s->last_text_width, height);
 }
 
 static uint64_t vga_mem_read(void *opaque, hwaddr addr,
diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h
index 5664317ecd6d..ca69ae981521 100644
--- a/hw/display/vga_int.h
+++ b/hw/display/vga_int.h
@@ -122,7 +122,8 @@ typedef struct VGACommonState {
     uint32_t plane_updated;
     uint32_t last_line_offset;
     uint8_t last_cw, last_ch;
-    uint32_t last_width, last_height; /* in chars or pixels */
+    uint32_t last_width, last_height; /* in pixels (graphics renderer) */
+    uint32_t last_text_width, last_text_height; /* in chars (text renderer) */
     uint32_t last_scr_width, last_scr_height; /* in pixels */
     uint32_t last_depth; /* in bits */
     bool last_byteswap;

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [GIT PULL 13/19] hw/display/virtio-gpu: Avoid creating empty udmabuf
  2026-08-25 11:20 [GIT PULL 00/19] Various fixes Marc-André Lureau
                   ` (11 preceding siblings ...)
  2026-08-25 11:21 ` [GIT PULL 12/19] hw/display/vga: fix text-mode OOB write after a graphics surface switch Marc-André Lureau
@ 2026-08-25 11:21 ` Marc-André Lureau
  2026-08-25 11:21 ` [GIT PULL 14/19] hw/display/virtio-gpu: Avoid mmap() for empty blob Marc-André Lureau
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2026-08-25 11:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: richard.henderson, Michael S. Tsirkin, Alex Bennée,
	Akihiko Odaki, Dmitry Osipenko

From: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>

The virtio specification allows creating a blob without backing storage
attached. However, virtio-gpu attempts to create an empty udmabuf for
such a blob. The ioctl fails with EINVAL and emits a spurious warning.
Avoid the invalid ioctl.

Fixes: e0933d91b1cd ("virtio-gpu: Add virtio_gpu_resource_create_blob")
Fixes: f66767f75c9c ("virtio-gpu: add virtio-gpu/blob vmstate subsection")
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260825-dmabuf-v2-1-b3d64d3b9a0e@rsg.ci.i.u-tokyo.ac.jp>
---
 hw/display/virtio-gpu.c | 102 +++++++++++++++++++++++++-----------------------
 1 file changed, 53 insertions(+), 49 deletions(-)

diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 9eb010082d0d..50c4dcd408bb 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -363,27 +363,29 @@ static void virtio_gpu_resource_create_blob(VirtIOGPU *g,
     res->resource_id = cblob.resource_id;
     res->blob_size = cblob.size;
 
-    ret = virtio_gpu_create_mapping_iov(g, cblob.nr_entries, sizeof(cblob),
-                                        cmd, &res->addrs, &res->iov,
-                                        &res->iov_cnt);
-    if (ret < 0) {
-        cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
-        g_free(res);
-        return;
+    if (cblob.nr_entries) {
+        ret = virtio_gpu_create_mapping_iov(g, cblob.nr_entries, sizeof(cblob),
+                                            cmd, &res->addrs, &res->iov,
+                                            &res->iov_cnt);
+        if (ret < 0) {
+            cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
+            g_free(res);
+            return;
+        }
+
+        if (iov_size(res->iov, res->iov_cnt) < res->blob_size) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: backing storage smaller than blob size\n",
+                          __func__);
+            cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+            virtio_gpu_cleanup_mapping(g, res);
+            g_free(res);
+            return;
+        }
+
+        virtio_gpu_init_udmabuf(res);
     }
 
-    if (res->iov_cnt > 0 &&
-        iov_size(res->iov, res->iov_cnt) < res->blob_size) {
-        qemu_log_mask(LOG_GUEST_ERROR,
-                      "%s: backing storage smaller than blob size\n",
-                      __func__);
-        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
-        virtio_gpu_cleanup_mapping(g, res);
-        g_free(res);
-        return;
-    }
-
-    virtio_gpu_init_udmabuf(res);
     QTAILQ_INSERT_HEAD(&g->reslist, res, next);
 }
 
@@ -1389,8 +1391,6 @@ static bool virtio_gpu_load_restore_mapping(VirtIOGPU *g,
         }
     }
 
-    QTAILQ_INSERT_HEAD(&g->reslist, res, next);
-    g->hostmem += res->hostmem;
     return true;
 }
 
@@ -1469,6 +1469,8 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
             return -EINVAL;
         }
 
+        QTAILQ_INSERT_HEAD(&g->reslist, res, next);
+        g->hostmem += hostmem;
         resource_id = qemu_get_be32(f);
     }
 
@@ -1528,36 +1530,38 @@ static int virtio_gpu_blob_load(QEMUFile *f, void *opaque, size_t size,
         res->blob_size = qemu_get_be32(f);
         res->iov_cnt = qemu_get_be32(f);
 
-        res->addrs = g_try_new(uint64_t, res->iov_cnt);
-        res->iov = g_try_new(struct iovec, res->iov_cnt);
-        if (res->iov_cnt && (!res->addrs || !res->iov)) {
-            g_free(res->addrs);
-            g_free(res->iov);
-            g_free(res);
-            return -EINVAL;
+        if (res->iov_cnt) {
+            res->addrs = g_try_new(uint64_t, res->iov_cnt);
+            res->iov = g_try_new(struct iovec, res->iov_cnt);
+            if (!res->addrs || !res->iov) {
+                g_free(res->addrs);
+                g_free(res->iov);
+                g_free(res);
+                return -EINVAL;
+            }
+
+            /* read data */
+            for (i = 0; i < res->iov_cnt; i++) {
+                res->addrs[i] = qemu_get_be64(f);
+                res->iov[i].iov_len = qemu_get_be32(f);
+            }
+
+            if (iov_size(res->iov, res->iov_cnt) < res->blob_size) {
+                g_free(res->addrs);
+                g_free(res->iov);
+                g_free(res);
+                return -EINVAL;
+            }
+
+            if (!virtio_gpu_load_restore_mapping(g, res)) {
+                g_free(res);
+                return -EINVAL;
+            }
+
+            virtio_gpu_init_udmabuf(res);
         }
 
-        /* read data */
-        for (i = 0; i < res->iov_cnt; i++) {
-            res->addrs[i] = qemu_get_be64(f);
-            res->iov[i].iov_len = qemu_get_be32(f);
-        }
-
-        if (res->iov_cnt > 0 &&
-            iov_size(res->iov, res->iov_cnt) < res->blob_size) {
-            g_free(res->addrs);
-            g_free(res->iov);
-            g_free(res);
-            return -EINVAL;
-        }
-
-        if (!virtio_gpu_load_restore_mapping(g, res)) {
-            g_free(res);
-            return -EINVAL;
-        }
-
-        virtio_gpu_init_udmabuf(res);
-
+        QTAILQ_INSERT_HEAD(&g->reslist, res, next);
         resource_id = qemu_get_be32(f);
     }
 

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [GIT PULL 14/19] hw/display/virtio-gpu: Avoid mmap() for empty blob
  2026-08-25 11:20 [GIT PULL 00/19] Various fixes Marc-André Lureau
                   ` (12 preceding siblings ...)
  2026-08-25 11:21 ` [GIT PULL 13/19] hw/display/virtio-gpu: Avoid creating empty udmabuf Marc-André Lureau
@ 2026-08-25 11:21 ` Marc-André Lureau
  2026-08-25 11:21 ` [GIT PULL 15/19] hw/display/virtio-gpu: Propagate udmabuf errors Marc-André Lureau
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2026-08-25 11:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: richard.henderson, Michael S. Tsirkin, Alex Bennée,
	Akihiko Odaki, Dmitry Osipenko

From: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>

Calling mmap() for an empty blob fails with EINVAL, causing QEMU to
emit a spurious warning.

Fixes: e0933d91b1cd ("virtio-gpu: Add virtio_gpu_resource_create_blob")
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260825-dmabuf-v2-2-b3d64d3b9a0e@rsg.ci.i.u-tokyo.ac.jp>
---
 hw/display/virtio-gpu-udmabuf.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c
index 816f52a51457..ba02ba9e8616 100644
--- a/hw/display/virtio-gpu-udmabuf.c
+++ b/hw/display/virtio-gpu-udmabuf.c
@@ -139,7 +139,7 @@ void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
     if (res->iov_cnt == 1 &&
         res->iov[0].iov_len < 4096) {
         pdata = res->iov[0].iov_base;
-    } else {
+    } else if (res->blob_size) {
         virtio_gpu_create_udmabuf(res);
         if (res->dmabuf_fd < 0) {
             return;

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [GIT PULL 15/19] hw/display/virtio-gpu: Propagate udmabuf errors
  2026-08-25 11:20 [GIT PULL 00/19] Various fixes Marc-André Lureau
                   ` (13 preceding siblings ...)
  2026-08-25 11:21 ` [GIT PULL 14/19] hw/display/virtio-gpu: Avoid mmap() for empty blob Marc-André Lureau
@ 2026-08-25 11:21 ` Marc-André Lureau
  2026-08-25 11:21 ` [GIT PULL 16/19] hw/display/virtio-gpu: Check cursor data presence Marc-André Lureau
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2026-08-25 11:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: richard.henderson, Michael S. Tsirkin, Alex Bennée,
	Akihiko Odaki, Dmitry Osipenko

From: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>

Propagate udmabuf errors so that the requested operation will be
canceled instead of producing an incomplete result and the user can
notice the failure.

Fixes: e0933d91b1cd ("virtio-gpu: Add virtio_gpu_resource_create_blob")
Fixes: f66767f75c9c ("virtio-gpu: add virtio-gpu/blob vmstate subsection")
Fixes: 4ae1c5c7d6f3 ("hw/display/virtio-gpu: Initialize blob mapping for ATTACH_BACKING")
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260825-dmabuf-v2-3-b3d64d3b9a0e@rsg.ci.i.u-tokyo.ac.jp>
---
 hw/display/virtio-gpu-udmabuf-stubs.c |  3 ++-
 hw/display/virtio-gpu-udmabuf.c       |  8 +++++---
 hw/display/virtio-gpu.c               | 18 ++++++++++++++----
 include/hw/virtio/virtio-gpu.h        |  2 +-
 4 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/hw/display/virtio-gpu-udmabuf-stubs.c b/hw/display/virtio-gpu-udmabuf-stubs.c
index 85d03935a332..0883bf05fac1 100644
--- a/hw/display/virtio-gpu-udmabuf-stubs.c
+++ b/hw/display/virtio-gpu-udmabuf-stubs.c
@@ -7,9 +7,10 @@ bool virtio_gpu_have_udmabuf(void)
     return false;
 }
 
-void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
+bool virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
 {
     /* nothing (stub) */
+    return false;
 }
 
 void virtio_gpu_fini_udmabuf(VirtIOGPU *g, struct virtio_gpu_simple_resource *res)
diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c
index ba02ba9e8616..c230509852ff 100644
--- a/hw/display/virtio-gpu-udmabuf.c
+++ b/hw/display/virtio-gpu-udmabuf.c
@@ -131,7 +131,7 @@ bool virtio_gpu_have_udmabuf(void)
     return memfd_backend;
 }
 
-void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
+bool virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
 {
     void *pdata = NULL;
 
@@ -142,17 +142,19 @@ void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
     } else if (res->blob_size) {
         virtio_gpu_create_udmabuf(res);
         if (res->dmabuf_fd < 0) {
-            return;
+            return false;
         }
         virtio_gpu_remap_udmabuf(res);
         if (!res->remapped) {
             virtio_gpu_destroy_udmabuf(res);
-            return;
+            return false;
         }
         pdata = res->remapped;
     }
 
     res->blob = pdata;
+
+    return true;
 }
 
 static void virtio_gpu_free_dmabuf(VirtIOGPU *g, VGPUDMABuf *dmabuf)
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 50c4dcd408bb..7f3301a9ac57 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -383,7 +383,12 @@ static void virtio_gpu_resource_create_blob(VirtIOGPU *g,
             return;
         }
 
-        virtio_gpu_init_udmabuf(res);
+        if (!virtio_gpu_init_udmabuf(res)) {
+            cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
+            virtio_gpu_cleanup_mapping(g, res);
+            g_free(res);
+            return;
+        }
     }
 
     QTAILQ_INSERT_HEAD(&g->reslist, res, next);
@@ -1045,8 +1050,9 @@ virtio_gpu_resource_attach_backing(VirtIOGPU *g,
         return;
     }
 
-    if (!res->image) {
-        virtio_gpu_init_udmabuf(res);
+    if (!res->image && !virtio_gpu_init_udmabuf(res)) {
+        cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
+        virtio_gpu_cleanup_mapping(g, res);
     }
 }
 
@@ -1558,7 +1564,11 @@ static int virtio_gpu_blob_load(QEMUFile *f, void *opaque, size_t size,
                 return -EINVAL;
             }
 
-            virtio_gpu_init_udmabuf(res);
+            if (!virtio_gpu_init_udmabuf(res)) {
+                virtio_gpu_cleanup_mapping(g, res);
+                g_free(res);
+                return -EINVAL;
+            }
         }
 
         QTAILQ_INSERT_HEAD(&g->reslist, res, next);
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 220231ec9d43..69b5ee2e382f 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -388,7 +388,7 @@ bool virtio_gpu_scanout_blob_to_fb(struct virtio_gpu_framebuffer *fb,
 
 /* virtio-gpu-udmabuf.c */
 bool virtio_gpu_have_udmabuf(void);
-void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res);
+bool virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res);
 void virtio_gpu_fini_udmabuf(VirtIOGPU *g,
                              struct virtio_gpu_simple_resource *res);
 int virtio_gpu_update_dmabuf(VirtIOGPU *g,

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [GIT PULL 16/19] hw/display/virtio-gpu: Check cursor data presence
  2026-08-25 11:20 [GIT PULL 00/19] Various fixes Marc-André Lureau
                   ` (14 preceding siblings ...)
  2026-08-25 11:21 ` [GIT PULL 15/19] hw/display/virtio-gpu: Propagate udmabuf errors Marc-André Lureau
@ 2026-08-25 11:21 ` Marc-André Lureau
  2026-08-25 11:21 ` [GIT PULL 17/19] hw/display/virtio-gpu: Validate resource per command Marc-André Lureau
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2026-08-25 11:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: richard.henderson, Alex Bennée, Akihiko Odaki,
	Dmitry Osipenko, Michael S. Tsirkin

From: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>

Reject a blob that lacks the backing storage for
VIRTIO_GPU_CMD_UPDATE_CURSOR.

Fixes: bdd53f739273 ("virtio-gpu: Update cursor data using blob")
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260825-dmabuf-v2-4-b3d64d3b9a0e@rsg.ci.i.u-tokyo.ac.jp>
---
 hw/display/virtio-gpu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 7f3301a9ac57..01549d29d8a2 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -63,8 +63,8 @@ void virtio_gpu_update_cursor_data(VirtIOGPU *g,
         }
         data = pixman_image_get_data(res->image);
     } else {
-        if (res->blob_size < (s->current_cursor->width *
-                              s->current_cursor->height * 4)) {
+        if (!res->iov || res->blob_size < (s->current_cursor->width *
+                                           s->current_cursor->height * 4)) {
             return;
         }
         data = res->blob;

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [GIT PULL 17/19] hw/display/virtio-gpu: Validate resource per command
  2026-08-25 11:20 [GIT PULL 00/19] Various fixes Marc-André Lureau
                   ` (15 preceding siblings ...)
  2026-08-25 11:21 ` [GIT PULL 16/19] hw/display/virtio-gpu: Check cursor data presence Marc-André Lureau
@ 2026-08-25 11:21 ` Marc-André Lureau
  2026-08-25 11:21 ` [GIT PULL 18/19] hw/input/ps2: answer unknown mouse commands with a resend Marc-André Lureau
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2026-08-25 11:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: richard.henderson, Alex Bennée, Akihiko Odaki,
	Dmitry Osipenko, Michael S. Tsirkin

From: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>

virtio_gpu_find_check_resource() checks if the resource has backing
storage if require_backing is true, but the condition conflates backing
storage attachment with host representation; it checks
!res->iov || (!res->image && !res->blob), but !res->iov is sufficient.

Furthermore, its callers passing true as require_backing have different
requirements:

- virtio_gpu_transfer_to_host_2d() requires a non-blob with
  backing storage.
- virtio_gpu_set_scanout() requires a non-blob but does not require
  backing storage.
- virtio_gpu_set_scanout_blob() requires a blob with backing storage.
- virtio_gpu_resource_detach_backing() accepts any resource.

Remove the require_backing parameter and open-code checks appropriate
for each function instead.

Fixes: 25c001a40346 ("virtio-gpu: Add virtio_gpu_find_check_resource")
Fixes: e0933d91b1cd ("virtio-gpu: Add virtio_gpu_resource_create_blob")
Fixes: 32db3c63ae11 ("virtio-gpu: Add virtio_gpu_set_scanout_blob")
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260825-dmabuf-v2-5-b3d64d3b9a0e@rsg.ci.i.u-tokyo.ac.jp>
---
 hw/display/virtio-gpu.c | 66 +++++++++++++++++++++++++++++++++----------------
 1 file changed, 45 insertions(+), 21 deletions(-)

diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 01549d29d8a2..55a1c7f80fb8 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -37,7 +37,6 @@
 
 static struct virtio_gpu_simple_resource *
 virtio_gpu_find_check_resource(VirtIOGPU *g, uint32_t resource_id,
-                               bool require_backing,
                                const char *caller, uint32_t *error);
 
 static void virtio_gpu_reset_bh(void *opaque);
@@ -50,8 +49,7 @@ void virtio_gpu_update_cursor_data(VirtIOGPU *g,
     uint32_t pixels;
     void *data;
 
-    res = virtio_gpu_find_check_resource(g, resource_id, false,
-                                         __func__, NULL);
+    res = virtio_gpu_find_check_resource(g, resource_id, __func__, NULL);
     if (!res) {
         return;
     }
@@ -128,7 +126,6 @@ virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id)
 
 static struct virtio_gpu_simple_resource *
 virtio_gpu_find_check_resource(VirtIOGPU *g, uint32_t resource_id,
-                               bool require_backing,
                                const char *caller, uint32_t *error)
 {
     struct virtio_gpu_simple_resource *res;
@@ -143,17 +140,6 @@ virtio_gpu_find_check_resource(VirtIOGPU *g, uint32_t resource_id,
         return NULL;
     }
 
-    if (require_backing) {
-        if (!res->iov || (!res->image && !res->blob)) {
-            qemu_log_mask(LOG_GUEST_ERROR, "%s: no backing storage %d\n",
-                          caller, resource_id);
-            if (error) {
-                *error = VIRTIO_GPU_RESP_ERR_UNSPEC;
-            }
-            return NULL;
-        }
-    }
-
     return res;
 }
 
@@ -474,9 +460,24 @@ static void virtio_gpu_transfer_to_host_2d(VirtIOGPU *g,
     virtio_gpu_t2d_bswap(&t2d);
     trace_virtio_gpu_cmd_res_xfer_toh_2d(t2d.resource_id);
 
-    res = virtio_gpu_find_check_resource(g, t2d.resource_id, true,
+    res = virtio_gpu_find_check_resource(g, t2d.resource_id,
                                          __func__, &cmd->error);
-    if (!res || res->blob) {
+    if (!res) {
+        return;
+    }
+
+    if (!res->image) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: resource %d is a blob\n",
+                      __func__, t2d.resource_id);
+        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+        return;
+    }
+
+    if (!res->iov) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: resource %d has no backing storage\n",
+                      __func__, t2d.resource_id);
+        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
         return;
     }
 
@@ -533,7 +534,7 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g,
     trace_virtio_gpu_cmd_res_flush(rf.resource_id,
                                    rf.r.width, rf.r.height, rf.r.x, rf.r.y);
 
-    res = virtio_gpu_find_check_resource(g, rf.resource_id, false,
+    res = virtio_gpu_find_check_resource(g, rf.resource_id,
                                          __func__, &cmd->error);
     if (!res) {
         return;
@@ -771,12 +772,19 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g,
         return;
     }
 
-    res = virtio_gpu_find_check_resource(g, ss.resource_id, true,
+    res = virtio_gpu_find_check_resource(g, ss.resource_id,
                                          __func__, &cmd->error);
     if (!res) {
         return;
     }
 
+    if (!res->image) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: resource %d is a blob\n",
+                      __func__, ss.resource_id);
+        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+        return;
+    }
+
     fb.format = pixman_image_get_format(res->image);
     bytes_pp = virtio_gpu_format_bytes_pp(fb.format);
     fb.width  = pixman_image_get_width(res->image);
@@ -866,12 +874,28 @@ static void virtio_gpu_set_scanout_blob(VirtIOGPU *g,
         return;
     }
 
-    res = virtio_gpu_find_check_resource(g, ss.resource_id, true,
+    res = virtio_gpu_find_check_resource(g, ss.resource_id,
                                          __func__, &cmd->error);
     if (!res) {
         return;
     }
 
+    if (res->image) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: resource %d is not a blob\n",
+                      __func__, ss.resource_id);
+        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+        return;
+    }
+
+    if (!res->iov) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: resource %d has no backing storage\n",
+                      __func__, ss.resource_id);
+        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+        return;
+    }
+
     if (!virtio_gpu_scanout_blob_to_fb(&fb, &ss, res->blob_size)) {
         cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
         return;
@@ -1067,7 +1091,7 @@ virtio_gpu_resource_detach_backing(VirtIOGPU *g,
     virtio_gpu_bswap_32(&detach, sizeof(detach));
     trace_virtio_gpu_cmd_res_back_detach(detach.resource_id);
 
-    res = virtio_gpu_find_check_resource(g, detach.resource_id, true,
+    res = virtio_gpu_find_check_resource(g, detach.resource_id,
                                          __func__, &cmd->error);
     if (!res) {
         return;

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [GIT PULL 18/19] hw/input/ps2: answer unknown mouse commands with a resend
  2026-08-25 11:20 [GIT PULL 00/19] Various fixes Marc-André Lureau
                   ` (16 preceding siblings ...)
  2026-08-25 11:21 ` [GIT PULL 17/19] hw/display/virtio-gpu: Validate resource per command Marc-André Lureau
@ 2026-08-25 11:21 ` Marc-André Lureau
  2026-08-25 11:21 ` [GIT PULL 19/19] hw/input/ps2: say why unknown keyboard commands draw " Marc-André Lureau
  2026-08-25 18:40 ` [GIT PULL 00/19] Various fixes Richard Henderson
  19 siblings, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2026-08-25 11:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: richard.henderson

From: Christian Quante <christian@quante.one>

ps2_write_mouse() ends its command switch with a bare "default: break;",
so an unknown command draws no reply at all. A real PS/2 device answers
every byte it is given -- ACK (0xFA) when it understood one, resend
(0xFE) when it did not -- and a guest that gets nothing back is left
waiting out its reply timeout. The keyboard path in the same file has
answered unknown commands with KBD_REPLY_RESEND since commit
06b3611fc2a3 ("ps2: reject unknown commands, instead of blindly
accepting them").

Two guests were measured on this.

OS/2 probes the mouse with the vendor command 0xBB, which QEMU does not
implement, and then polls the status port until its own timeout runs
out. On a Warp 3 guest that wait costs about 25 ms of every boot under
TCG, and 2.1 s under KVM, where each of those polls leaves the guest.
With this patch the wait ends on the first read: the guest takes the
same error path an unexpected reply would, and does not retry.

Linux runs into two of them while probing the mouse: the ALPS probe
sends 0xEC (reset wrap mode), which ps2_write_mouse() only answers
while the mouse is in wrap mode, and the TrackPoint probe sends 0xE1.
Each costs libps2 a 200 ms reply timeout. Timing the psmouse detection
from a mark written to /dev/kmsg to the kernel's "input:" line, three
boots each of a 6.18.35 kernel under TCG: 426.7/428.8/441.6 ms without
this patch, 21.4/21.6/21.2 ms with it. The mouse is detected
identically either way; only the error the probe ends in changes, from
-EIO (nothing came back at all) to -EPROTO (libps2 gives up after its
second attempt).

The specification's second stage -- 0xFC (Error) when the byte after a
rejected one is invalid as well -- is deliberately left out. It would
need state that has to survive migration, no guest is known to test for
it, and the keyboard path does without it as well.

Cc: qemu-stable@nongnu.org
Signed-off-by: Christian Quante <christian@quante.one>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Message-ID: <20260825075127.34876-2-christian@quante.one>
---
 hw/input/ps2.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/hw/input/ps2.c b/hw/input/ps2.c
index 5516eb262d70..e8300d2d8308 100644
--- a/hw/input/ps2.c
+++ b/hw/input/ps2.c
@@ -73,6 +73,7 @@
 #define AUX_SET_DEFAULT     0xF6
 #define AUX_RESET           0xFF    /* Reset aux device */
 #define AUX_ACK             0xFA    /* Command byte ACK. */
+#define AUX_RESEND          0xFE    /* Command NACK, send the cmd again */
 
 #define MOUSE_STATUS_REMOTE     0x40
 #define MOUSE_STATUS_ENABLED    0x20
@@ -955,6 +956,11 @@ void ps2_write_mouse(PS2MouseState *s, int val)
                 s->mouse_type);
             break;
         default:
+            /*
+             * A PS/2 device answers every command it is given; an unknown
+             * one draws a resend.
+             */
+            ps2_queue(ps2, AUX_RESEND);
             break;
         }
         break;

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [GIT PULL 19/19] hw/input/ps2: say why unknown keyboard commands draw a resend
  2026-08-25 11:20 [GIT PULL 00/19] Various fixes Marc-André Lureau
                   ` (17 preceding siblings ...)
  2026-08-25 11:21 ` [GIT PULL 18/19] hw/input/ps2: answer unknown mouse commands with a resend Marc-André Lureau
@ 2026-08-25 11:21 ` Marc-André Lureau
  2026-08-25 18:40 ` [GIT PULL 00/19] Various fixes Richard Henderson
  19 siblings, 0 replies; 25+ messages in thread
From: Marc-André Lureau @ 2026-08-25 11:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: richard.henderson

From: Christian Quante <christian@quante.one>

The keyboard path has answered unknown commands with KBD_REPLY_RESEND
since commit 06b3611fc2a3 ("ps2: reject unknown commands, instead of
blindly accepting them"), but never said why. Give it the comment the
mouse path just gained, so the reasoning is written down in both
places.

Suggested-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Christian Quante <christian@quante.one>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Message-ID: <20260825075127.34876-3-christian@quante.one>
---
 hw/input/ps2.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/hw/input/ps2.c b/hw/input/ps2.c
index e8300d2d8308..01af4350b3bc 100644
--- a/hw/input/ps2.c
+++ b/hw/input/ps2.c
@@ -647,6 +647,10 @@ void ps2_write_keyboard(PS2KbdState *s, int val)
             ps2_cqueue_1(ps2, KBD_REPLY_ACK);
             break;
         default:
+            /*
+             * A PS/2 device answers every command it is given; an unknown
+             * one draws a resend.
+             */
             ps2_cqueue_1(ps2, KBD_REPLY_RESEND);
             break;
         }

-- 
2.55.0.543.g5ebe2ebe4ea8



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [GIT PULL 06/19] crypto: fix build against nettle >= 4
  2026-08-25 11:20 ` [GIT PULL 06/19] crypto: fix build against nettle >= 4 Marc-André Lureau
@ 2026-08-25 11:54   ` Daniel P. Berrangé
  0 siblings, 0 replies; 25+ messages in thread
From: Daniel P. Berrangé @ 2026-08-25 11:54 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-stable; +Cc: qemu-devel, richard.henderson

CC qemu-stable - can pick this into historical branches so
they build with latest nettle.

On Tue, Aug 25, 2026 at 03:20:56PM +0400, Marc-André Lureau wrote:
> sha.h has been deprecated. It seems we can rely on sha1.h/sha2.h
> since we depend on >= 3.7.3.
> 
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4184
> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  crypto/hash-nettle.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/crypto/hash-nettle.c b/crypto/hash-nettle.c
> index 53f68301efb5..2589bbf4c10e 100644
> --- a/crypto/hash-nettle.c
> +++ b/crypto/hash-nettle.c
> @@ -24,7 +24,8 @@
>  #include "crypto/hash.h"
>  #include "hashpriv.h"
>  #include <nettle/md5.h>
> -#include <nettle/sha.h>
> +#include <nettle/sha1.h>
> +#include <nettle/sha2.h>
>  #include <nettle/ripemd160.h>
>  #ifdef CONFIG_CRYPTO_SM3
>  #include <nettle/sm3.h>
> 
> -- 
> 2.55.0.543.g5ebe2ebe4ea8
> 

With regards,
Daniel
-- 
|: https://berrange.com       ~~        https://hachyderm.io/@berrange :|
|: https://libvirt.org          ~~          https://entangle-photo.org :|
|: https://pixelfed.art/berrange   ~~    https://fstop138.berrange.com :|



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [GIT PULL 00/19] Various fixes
  2026-08-25 11:20 [GIT PULL 00/19] Various fixes Marc-André Lureau
                   ` (18 preceding siblings ...)
  2026-08-25 11:21 ` [GIT PULL 19/19] hw/input/ps2: say why unknown keyboard commands draw " Marc-André Lureau
@ 2026-08-25 18:40 ` Richard Henderson
  19 siblings, 0 replies; 25+ messages in thread
From: Richard Henderson @ 2026-08-25 18:40 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-devel

On 8/25/26 04:20, Marc-André Lureau wrote:

> The following changes since commit 2be159078ea26feac4c9c9902acf8906f1a05c2a:
>
>    Merge tag 'pull-riscv-to-apply-20260824-1' ofhttps://github.com/alistair23/qemu into staging (2026-08-23 23:04:09 -0700)
>
> are available in the Git repository at:
>
>    https://gitlab.com/marcandre.lureau/qemu.git tags/fixes-pr-v1
>
> for you to fetch changes up to a88191a0caecdfba440682e3c120b439681ccaca:
>
>    hw/input/ps2: say why unknown keyboard commands draw a resend (2026-08-25 15:20:44 +0400)
>
> ----------------------------------------------------------------
> Various fixes
>
> Collect various graphics & chardev fixes, and some others.
>
> Signed-off-by: Marc-André Lureau<marcandre.lureau@redhat.com>

Applied, thanks.

r~



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [GIT PULL 05/19] virtio-gpu: use g_try_malloc to avoid guest-triggered abort
  2026-08-25 11:20 ` [GIT PULL 05/19] virtio-gpu: use g_try_malloc to avoid guest-triggered abort Marc-André Lureau
@ 2026-09-03 19:36   ` Peter Maydell
  2026-09-03 20:53     ` Marc-André Lureau
  0 siblings, 1 reply; 25+ messages in thread
From: Peter Maydell @ 2026-09-03 19:36 UTC (permalink / raw)
  To: Marc-André Lureau
  Cc: qemu-devel, richard.henderson, Michael S. Tsirkin,
	Stefano Garzarella, Alex Bennée, Akihiko Odaki,
	Dmitry Osipenko

On Tue, 25 Aug 2026 at 12:29, Marc-André Lureau
<marcandre.lureau@redhat.com> wrote:
>
> Use g_try_malloc/g_try_new0 for guest-controlled allocation, so failure
> returns an error to the guest rather than crashing the host (glib
> behaviour).
>
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3898
> Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> Message-ID: <20260805130141.211398-1-marcandre.lureau@redhat.com>

Hi; Coverity has some notes about this commit (CID 1685636,
1685637, 1685638):

> @@ -498,17 +498,22 @@ vg_create_mapping_iov(VuGpu *g,
>      }
>
>      esize = sizeof(*ents) * ab->nr_entries;
> -    ents = g_malloc(esize);
> +    ents = g_try_malloc(esize);
> +    if (!ents && esize) {
> +        return -1;
> +    }

This means that if esize == 0 we will continue even though
ents is NULL.

>      s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
>                     sizeof(*ab), ents, esize);

Coverity complains because it thinks iov_to_buf() might
try to dereference a NULL ent. I think that's wrong (a
zero size makes iov_to_buf() never touch the buffer), but
it does raise the question -- do we really want to be
continuing ahead here with a zero size and NULL buffer pointer,
rather than handling zero sizes with some kind of early return?

I think it's preferable to have the "allocation failure"
check be a plain "if (!ptr) { leave early }", because then
static analysis tools don't go down blind alleys assuming
that execution can run through all kinds of paths in the rest
of the function with a NULL pointer.

This specific check is what is triggering CID 1685638.

> diff --git a/contrib/vhost-user-gpu/virgl.c b/contrib/vhost-user-gpu/virgl.c
> index 550fd03bf5c4..20bae57d0fe4 100644
> --- a/contrib/vhost-user-gpu/virgl.c
> +++ b/contrib/vhost-user-gpu/virgl.c
> @@ -209,7 +209,11 @@ virgl_cmd_submit_3d(VuGpu *g,
>          return;
>      }
>
> -    buf = g_malloc(cs.size);
> +    buf = g_try_malloc(cs.size);
> +    if (!buf && cs.size) {
> +        cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
> +        return;
> +    }
>      s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
>                     sizeof(cs), buf, cs.size);

This one is CID 1685636.

>      if (s != cs.size) {

> diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
> index fbb6fec7a0ad..9eb010082d0d 100644
> --- a/hw/display/virtio-gpu.c
> +++ b/hw/display/virtio-gpu.c
> @@ -892,7 +892,10 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
>      }
>
>      esize = sizeof(*ents) * nr_entries;
> -    ents = g_malloc(esize);
> +    ents = g_try_malloc(esize);
> +    if (!ents && esize) {
> +        return -1;
> +    }
>      s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
>                     offset, ents, esize);

And this one is CID 1685637.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [GIT PULL 05/19] virtio-gpu: use g_try_malloc to avoid guest-triggered abort
  2026-09-03 19:36   ` Peter Maydell
@ 2026-09-03 20:53     ` Marc-André Lureau
  2026-09-10 11:19       ` Peter Maydell
  0 siblings, 1 reply; 25+ messages in thread
From: Marc-André Lureau @ 2026-09-03 20:53 UTC (permalink / raw)
  To: Peter Maydell
  Cc: qemu-devel, richard.henderson, Michael S. Tsirkin,
	Stefano Garzarella, Alex Bennée, Akihiko Odaki,
	Dmitry Osipenko

Hi

On Thu, Sep 3, 2026 at 11:39 PM Peter Maydell <peter.maydell@linaro.org> wrote:
>
> On Tue, 25 Aug 2026 at 12:29, Marc-André Lureau
> <marcandre.lureau@redhat.com> wrote:
> >
> > Use g_try_malloc/g_try_new0 for guest-controlled allocation, so failure
> > returns an error to the guest rather than crashing the host (glib
> > behaviour).
> >
> > Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3898
> > Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > Message-ID: <20260805130141.211398-1-marcandre.lureau@redhat.com>
>
> Hi; Coverity has some notes about this commit (CID 1685636,
> 1685637, 1685638):
>
> > @@ -498,17 +498,22 @@ vg_create_mapping_iov(VuGpu *g,
> >      }
> >
> >      esize = sizeof(*ents) * ab->nr_entries;
> > -    ents = g_malloc(esize);
> > +    ents = g_try_malloc(esize);
> > +    if (!ents && esize) {
> > +        return -1;
> > +    }
>
> This means that if esize == 0 we will continue even though
> ents is NULL.
>
> >      s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
> >                     sizeof(*ab), ents, esize);
>
> Coverity complains because it thinks iov_to_buf() might
> try to dereference a NULL ent. I think that's wrong (a
> zero size makes iov_to_buf() never touch the buffer), but
> it does raise the question -- do we really want to be
> continuing ahead here with a zero size and NULL buffer pointer,
> rather than handling zero sizes with some kind of early return?
>
> I think it's preferable to have the "allocation failure"
> check be a plain "if (!ptr) { leave early }", because then
> static analysis tools don't go down blind alleys assuming
> that execution can run through all kinds of paths in the rest
> of the function with a NULL pointer.
>
> This specific check is what is triggering CID 1685638.

The previous code was accepting 0/NULL.. I agree it is questionable.

There is nothing in vg_resource_attach_backing() that prevents 0/NULL.
So unless we have a clear indication that this is invalid, I would
rather not change it.

I think we can silence those warnings for now, unless we have more
evidence or clear argument. I am happy to fix it otherwise.

>
> > diff --git a/contrib/vhost-user-gpu/virgl.c b/contrib/vhost-user-gpu/virgl.c
> > index 550fd03bf5c4..20bae57d0fe4 100644
> > --- a/contrib/vhost-user-gpu/virgl.c
> > +++ b/contrib/vhost-user-gpu/virgl.c
> > @@ -209,7 +209,11 @@ virgl_cmd_submit_3d(VuGpu *g,
> >          return;
> >      }
> >
> > -    buf = g_malloc(cs.size);
> > +    buf = g_try_malloc(cs.size);
> > +    if (!buf && cs.size) {
> > +        cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
> > +        return;
> > +    }
> >      s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
> >                     sizeof(cs), buf, cs.size);
>
> This one is CID 1685636.
>
> >      if (s != cs.size) {
>
> > diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
> > index fbb6fec7a0ad..9eb010082d0d 100644
> > --- a/hw/display/virtio-gpu.c
> > +++ b/hw/display/virtio-gpu.c
> > @@ -892,7 +892,10 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
> >      }
> >
> >      esize = sizeof(*ents) * nr_entries;
> > -    ents = g_malloc(esize);
> > +    ents = g_try_malloc(esize);
> > +    if (!ents && esize) {
> > +        return -1;
> > +    }
> >      s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
> >                     offset, ents, esize);
>
> And this one is CID 1685637.
>
> thanks
> -- PMM
>


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [GIT PULL 05/19] virtio-gpu: use g_try_malloc to avoid guest-triggered abort
  2026-09-03 20:53     ` Marc-André Lureau
@ 2026-09-10 11:19       ` Peter Maydell
  0 siblings, 0 replies; 25+ messages in thread
From: Peter Maydell @ 2026-09-10 11:19 UTC (permalink / raw)
  To: Marc-André Lureau
  Cc: qemu-devel, richard.henderson, Michael S. Tsirkin,
	Stefano Garzarella, Alex Bennée, Akihiko Odaki,
	Dmitry Osipenko

On Thu, 3 Sept 2026 at 21:53, Marc-André Lureau
<marcandre.lureau@redhat.com> wrote:
>
> Hi
>
> On Thu, Sep 3, 2026 at 11:39 PM Peter Maydell <peter.maydell@linaro.org> wrote:
> >
> > On Tue, 25 Aug 2026 at 12:29, Marc-André Lureau
> > <marcandre.lureau@redhat.com> wrote:
> > >
> > > Use g_try_malloc/g_try_new0 for guest-controlled allocation, so failure
> > > returns an error to the guest rather than crashing the host (glib
> > > behaviour).
> > >
> > > Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3898
> > > Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
> > > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > > Message-ID: <20260805130141.211398-1-marcandre.lureau@redhat.com>
> >
> > Hi; Coverity has some notes about this commit (CID 1685636,
> > 1685637, 1685638):
> >
> > > @@ -498,17 +498,22 @@ vg_create_mapping_iov(VuGpu *g,
> > >      }
> > >
> > >      esize = sizeof(*ents) * ab->nr_entries;
> > > -    ents = g_malloc(esize);
> > > +    ents = g_try_malloc(esize);
> > > +    if (!ents && esize) {
> > > +        return -1;
> > > +    }
> >
> > This means that if esize == 0 we will continue even though
> > ents is NULL.
> >
> > >      s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
> > >                     sizeof(*ab), ents, esize);
> >
> > Coverity complains because it thinks iov_to_buf() might
> > try to dereference a NULL ent. I think that's wrong (a
> > zero size makes iov_to_buf() never touch the buffer), but
> > it does raise the question -- do we really want to be
> > continuing ahead here with a zero size and NULL buffer pointer,
> > rather than handling zero sizes with some kind of early return?
> >
> > I think it's preferable to have the "allocation failure"
> > check be a plain "if (!ptr) { leave early }", because then
> > static analysis tools don't go down blind alleys assuming
> > that execution can run through all kinds of paths in the rest
> > of the function with a NULL pointer.
> >
> > This specific check is what is triggering CID 1685638.
>
> The previous code was accepting 0/NULL.. I agree it is questionable.
>
> There is nothing in vg_resource_attach_backing() that prevents 0/NULL.
> So unless we have a clear indication that this is invalid, I would
> rather not change it.
>
> I think we can silence those warnings for now, unless we have more
> evidence or clear argument. I am happy to fix it otherwise.

Nobody has come in to say anything eles here, so I've marked
the Coverity issues as false positives. I do think it would
be nicer to avoid the 0/NULL problem, but I don't feel strongly
enough about it to actually write patches myself :-)

-- PMM


^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2026-09-10 11:19 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-25 11:20 [GIT PULL 00/19] Various fixes Marc-André Lureau
2026-08-25 11:20 ` [GIT PULL 01/19] hw/misc: fix trace-events Marc-André Lureau
2026-08-25 11:20 ` [GIT PULL 02/19] migration/multifd: fix Error leak in multifd_recv_terminate_threads() Marc-André Lureau
2026-08-25 11:20 ` [GIT PULL 03/19] hw/core/machine: fix fdt memory leak Marc-André Lureau
2026-08-25 11:20 ` [GIT PULL 04/19] hw/display/qxl: validate primary surface stride against width Marc-André Lureau
2026-08-25 11:20 ` [GIT PULL 05/19] virtio-gpu: use g_try_malloc to avoid guest-triggered abort Marc-André Lureau
2026-09-03 19:36   ` Peter Maydell
2026-09-03 20:53     ` Marc-André Lureau
2026-09-10 11:19       ` Peter Maydell
2026-08-25 11:20 ` [GIT PULL 06/19] crypto: fix build against nettle >= 4 Marc-André Lureau
2026-08-25 11:54   ` Daniel P. Berrangé
2026-08-25 11:20 ` [GIT PULL 07/19] tests: tag slow tests with 'slow' suite for easy filtering Marc-André Lureau
2026-08-25 11:20 ` [GIT PULL 08/19] ui/egl: fix render node cleanup order Marc-André Lureau
2026-08-25 11:20 ` [GIT PULL 09/19] ui/egl: fix qemu_egl_display type Marc-André Lureau
2026-08-25 11:21 ` [GIT PULL 10/19] tests/functional: fix pylint false positives for cv2 module Marc-André Lureau
2026-08-25 11:21 ` [GIT PULL 11/19] chardev: Don't unregister yank upon async path connection failure Marc-André Lureau
2026-08-25 11:21 ` [GIT PULL 12/19] hw/display/vga: fix text-mode OOB write after a graphics surface switch Marc-André Lureau
2026-08-25 11:21 ` [GIT PULL 13/19] hw/display/virtio-gpu: Avoid creating empty udmabuf Marc-André Lureau
2026-08-25 11:21 ` [GIT PULL 14/19] hw/display/virtio-gpu: Avoid mmap() for empty blob Marc-André Lureau
2026-08-25 11:21 ` [GIT PULL 15/19] hw/display/virtio-gpu: Propagate udmabuf errors Marc-André Lureau
2026-08-25 11:21 ` [GIT PULL 16/19] hw/display/virtio-gpu: Check cursor data presence Marc-André Lureau
2026-08-25 11:21 ` [GIT PULL 17/19] hw/display/virtio-gpu: Validate resource per command Marc-André Lureau
2026-08-25 11:21 ` [GIT PULL 18/19] hw/input/ps2: answer unknown mouse commands with a resend Marc-André Lureau
2026-08-25 11:21 ` [GIT PULL 19/19] hw/input/ps2: say why unknown keyboard commands draw " Marc-André Lureau
2026-08-25 18:40 ` [GIT PULL 00/19] Various fixes Richard Henderson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.