All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] virtio-gpu: reject non-32bpp cursor resources
@ 2026-11-10  8:31 Marc-André Lureau
  2026-11-10  8:31 ` [PATCH 1/4] virtio-gpu: make some 2d callbacks statics Marc-André Lureau
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Marc-André Lureau @ 2026-11-10  8:31 UTC (permalink / raw)
  To: qemu-devel
  Cc: Michael S. Tsirkin, Alex Bennée, Akihiko Odaki,
	Dmitry Osipenko, Stefano Garzarella, Gurchetan Singh,
	Marc-André Lureau

Cursor data is copied out of the resource as 32bpp BGRA by every
accelerated backend, but none of them checks the resource format first.
(the 2d backend rejects any resource format that is not 32bpp already)

Refuse cursor resources that are not 32bpp in the three backends,
reusing virtio_gpu_get_pixman_format() as the allowlist, and log the
dimension mismatch in the rutabaga backend as the others do. Supported
formats keep working unchanged.

The vhost-user-gpu cursor path also leaked the virgl buffer when the
size check failed, so a guest could grow the backend memory with
repeated UPDATE_CURSOR commands. Release it with g_autofree, and skip
the update instead of sending zero-filled cursor pixels when no data
was produced.

First patch is a trivial cleanup.

The virglrenderer side is fixed with
https://gitlab.freedesktop.org/virgl/virglrenderer/-/merge_requests/1703

Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4756
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
Marc-André Lureau (4):
      virtio-gpu: make some 2d callbacks statics
      virtio-gpu/gl: reject non-32bpp cursor resources
      virtio-gpu/rutabaga: reject non-32bpp cursor resources
      contrib/vhost-user-gpu: reject non-32bpp cursor resources

 contrib/vhost-user-gpu/vhost-user-gpu.c | 31 ++++++++++++++++++++-----------
 contrib/vhost-user-gpu/virgl.c          | 25 ++++++++++++++++++-------
 contrib/vhost-user-gpu/virgl.h          |  2 +-
 hw/display/virtio-gpu-gl.c              | 18 ++++++++++++++++++
 hw/display/virtio-gpu-rutabaga.c        | 19 ++++++++++++++++---
 hw/display/virtio-gpu.c                 | 12 +++++++-----
 include/hw/virtio/virtio-gpu-pixman.h   | 13 +++++++++++++
 include/hw/virtio/virtio-gpu.h          |  4 ----
 8 files changed, 93 insertions(+), 31 deletions(-)
---
base-commit: 723622bedb0b423de7d1c61ebbe6e7a71934949c
change-id: 20261104-master-b659997e3be3

Best regards,
--  
Marc-André Lureau <marcandre.lureau@redhat.com>



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

* [PATCH 1/4] virtio-gpu: make some 2d callbacks statics
  2026-11-10  8:31 [PATCH 0/4] virtio-gpu: reject non-32bpp cursor resources Marc-André Lureau
@ 2026-11-10  8:31 ` Marc-André Lureau
  2026-11-10  8:49   ` Daniel P. Berrangé
  2026-11-11 13:13   ` Akihiko Odaki
  2026-11-10  8:31 ` [PATCH 2/4] virtio-gpu/gl: reject non-32bpp cursor resources Marc-André Lureau
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 13+ messages in thread
From: Marc-André Lureau @ 2026-11-10  8:31 UTC (permalink / raw)
  To: qemu-devel
  Cc: Michael S. Tsirkin, Alex Bennée, Akihiko Odaki,
	Dmitry Osipenko, Stefano Garzarella, Gurchetan Singh,
	Marc-André Lureau

Those functions are not shared with other units.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hw/display/virtio-gpu.c        | 12 +++++++-----
 include/hw/virtio/virtio-gpu.h |  4 ----
 2 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 5d43ffb99184..6450f4734861 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -81,9 +81,10 @@ virtio_gpu_simple_resource_new_blob(uint32_t resource_id, uint64_t blob_size)
     return res;
 }
 
-void virtio_gpu_update_cursor_data(VirtIOGPU *g,
-                                   struct virtio_gpu_scanout *s,
-                                   uint32_t resource_id)
+static void
+virtio_gpu_update_cursor_data(VirtIOGPU *g,
+                              struct virtio_gpu_scanout *s,
+                              uint32_t resource_id)
 {
     struct virtio_gpu_simple_resource *res;
     uint32_t pixels;
@@ -1178,8 +1179,9 @@ virtio_gpu_resource_detach_backing(VirtIOGPU *g,
     virtio_gpu_cleanup_mapping(g, res);
 }
 
-void virtio_gpu_simple_process_cmd(VirtIOGPU *g,
-                                   struct virtio_gpu_ctrl_command *cmd)
+static void
+virtio_gpu_simple_process_cmd(VirtIOGPU *g,
+                              struct virtio_gpu_ctrl_command *cmd)
 {
     VIRTIO_GPU_FILL_CMD(cmd->cmd_hdr);
     virtio_gpu_ctrl_hdr_bswap(&cmd->cmd_hdr);
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 631dfc63a4d4..65e96b8fc4de 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -361,10 +361,6 @@ void virtio_gpu_cleanup_mapping(VirtIOGPU *g,
 void virtio_gpu_process_cmdq(VirtIOGPU *g);
 void virtio_gpu_device_realize(DeviceState *qdev, Error **errp);
 void virtio_gpu_reset(VirtIODevice *vdev);
-void virtio_gpu_simple_process_cmd(VirtIOGPU *g, struct virtio_gpu_ctrl_command *cmd);
-void virtio_gpu_update_cursor_data(VirtIOGPU *g,
-                                   struct virtio_gpu_scanout *s,
-                                   uint32_t resource_id);
 
 bool virtio_gpu_check_scanout_bounds(uint32_t scanout_id, uint32_t resource_id,
                                      uint32_t width, uint32_t height,

-- 
2.56.0.116.g6de20f6092dc



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

* [PATCH 2/4] virtio-gpu/gl: reject non-32bpp cursor resources
  2026-11-10  8:31 [PATCH 0/4] virtio-gpu: reject non-32bpp cursor resources Marc-André Lureau
  2026-11-10  8:31 ` [PATCH 1/4] virtio-gpu: make some 2d callbacks statics Marc-André Lureau
@ 2026-11-10  8:31 ` Marc-André Lureau
  2026-11-10  8:53   ` Daniel P. Berrangé
  2026-11-10  8:31 ` [PATCH 3/4] virtio-gpu/rutabaga: " Marc-André Lureau
  2026-11-10  8:31 ` [PATCH 4/4] contrib/vhost-user-gpu: " Marc-André Lureau
  3 siblings, 1 reply; 13+ messages in thread
From: Marc-André Lureau @ 2026-11-10  8:31 UTC (permalink / raw)
  To: qemu-devel
  Cc: Michael S. Tsirkin, Alex Bennée, Akihiko Odaki,
	Dmitry Osipenko, Stefano Garzarella, Gurchetan Singh,
	Marc-André Lureau

Cursor pixel data is copied as 32bpp, but the resource format is never
checked. virgl_renderer_get_cursor_data() sizes its buffer for the
resource's own format, while virtio_gpu_gl_update_cursor_data() copies
width * height * 4 bytes from it: a 64x64 R8_UNORM resource gives a
4096 byte buffer and a 16384 byte read, so 12 KiB of host heap past the
end of the allocation is sent to a connected VNC client as cursor data.

Look up the resource format and refuse anything that is not 32bpp,
matching what the non-virgl paths accept. Querying the renderer covers
blob resources: a blob carries no format in the virtio command and QEMU
stores 0 for it. The virgl and virtio format enums have the same values
for the accepted formats.

Fixes: CVE-2026-122027
Fixes: 9d9e152136bd ("virtio-gpu: add 3d mode and virgl rendering support.")
Reported-by: Fernando Bortotti <https://gitlab.com/fernando.bortotti>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hw/display/virtio-gpu-gl.c            | 18 ++++++++++++++++++
 include/hw/virtio/virtio-gpu-pixman.h | 13 +++++++++++++
 2 files changed, 31 insertions(+)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 2b7a41c46643..c314631b05f3 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -31,6 +31,7 @@ static void virtio_gpu_gl_update_cursor_data(VirtIOGPU *g,
                                              uint32_t resource_id)
 {
     VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
+    struct virgl_renderer_resource_info info = { 0 };
     uint32_t width, height;
     uint32_t pixels, *data;
 
@@ -38,6 +39,20 @@ static void virtio_gpu_gl_update_cursor_data(VirtIOGPU *g,
         return;
     }
 
+    virgl_renderer_force_ctx_0();
+    if (virgl_renderer_resource_get_info(resource_id, &info) != 0) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: unknown cursor resource %u\n",
+                      __func__, resource_id);
+        return;
+    }
+
+    if (!virtio_gpu_format_is_cursor_capable(info.virgl_format)) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: cursor resource %u has unsupported format %u\n",
+                      __func__, resource_id, info.virgl_format);
+        return;
+    }
+
     data = virgl_renderer_get_cursor_data(resource_id, &width, &height);
     if (!data) {
         return;
@@ -45,6 +60,9 @@ static void virtio_gpu_gl_update_cursor_data(VirtIOGPU *g,
 
     if (width != s->current_cursor->width ||
         height != s->current_cursor->height) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: cursor resource %u has unsupported dimension %ux%u\n",
+                      __func__, resource_id, width, height);
         free(data);
         return;
     }
diff --git a/include/hw/virtio/virtio-gpu-pixman.h b/include/hw/virtio/virtio-gpu-pixman.h
index 4dba782758dc..d6043d2ca1df 100644
--- a/include/hw/virtio/virtio-gpu-pixman.h
+++ b/include/hw/virtio/virtio-gpu-pixman.h
@@ -42,4 +42,17 @@ virtio_gpu_get_pixman_format(uint32_t virtio_gpu_format)
     }
 }
 
+/*
+ * Cursor data is copied as 32bpp; formats without a pixman mapping are
+ * rejected.
+ */
+static inline bool
+virtio_gpu_format_is_cursor_capable(uint32_t format)
+{
+    pixman_format_code_t pformat;
+
+    pformat = virtio_gpu_get_pixman_format(format);
+    return pformat && PIXMAN_FORMAT_BPP(pformat) == 32;
+}
+
 #endif

-- 
2.56.0.116.g6de20f6092dc



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

* [PATCH 3/4] virtio-gpu/rutabaga: reject non-32bpp cursor resources
  2026-11-10  8:31 [PATCH 0/4] virtio-gpu: reject non-32bpp cursor resources Marc-André Lureau
  2026-11-10  8:31 ` [PATCH 1/4] virtio-gpu: make some 2d callbacks statics Marc-André Lureau
  2026-11-10  8:31 ` [PATCH 2/4] virtio-gpu/gl: reject non-32bpp cursor resources Marc-André Lureau
@ 2026-11-10  8:31 ` Marc-André Lureau
  2026-11-10  8:54   ` Daniel P. Berrangé
  2026-11-11 13:21   ` Akihiko Odaki
  2026-11-10  8:31 ` [PATCH 4/4] contrib/vhost-user-gpu: " Marc-André Lureau
  3 siblings, 2 replies; 13+ messages in thread
From: Marc-André Lureau @ 2026-11-10  8:31 UTC (permalink / raw)
  To: qemu-devel
  Cc: Michael S. Tsirkin, Alex Bennée, Akihiko Odaki,
	Dmitry Osipenko, Stefano Garzarella, Gurchetan Singh,
	Marc-André Lureau

The cursor buffer is always 64x64x4, but rutabaga does not check the
resource format before the transfer read. Gfxstream copies only as many
bytes as the resource format needs, so an R8_UNORM cursor updates the
first 4096 bytes of the 16384 byte buffer and leaves the rest untouched,
while formats with a larger pixel size do not fit the request and fail.

Refuse cursor resources that are not 32bpp, reusing
virtio_gpu_get_pixman_format() as the allowlist so the 32bpp formats the
other backends accept keep working. res->format is the value passed to
rutabaga_resource_create_3d(), so it matches what gfxstream stores. Blob
resources carry no format; they were already rejected by the dimension
check and stay rejected. Log the dimension mismatch and the transfer
failure as well.

Fixes: CVE-2026-122027
Fixes: 1dcc6adbc168 ("gfxstream + rutabaga: add initial support for gfxstream")
Reported-by: Fernando Bortotti <https://gitlab.com/fernando.bortotti>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hw/display/virtio-gpu-rutabaga.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/hw/display/virtio-gpu-rutabaga.c b/hw/display/virtio-gpu-rutabaga.c
index 1312a67d7011..6246aca894b0 100644
--- a/hw/display/virtio-gpu-rutabaga.c
+++ b/hw/display/virtio-gpu-rutabaga.c
@@ -44,8 +44,18 @@ virtio_gpu_rutabaga_update_cursor(VirtIOGPU *g, struct virtio_gpu_scanout *s,
         return;
     }
 
+    if (!virtio_gpu_format_is_cursor_capable(res->format)) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: cursor resource %u has unsupported format %u\n",
+                      __func__, resource_id, res->format);
+        return;
+    }
+
     if (res->width != s->current_cursor->width ||
         res->height != s->current_cursor->height) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: cursor resource %u has unsupported dimension %ux%u\n",
+                      __func__, resource_id, res->width, res->height);
         return;
     }
 
@@ -59,9 +69,12 @@ virtio_gpu_rutabaga_update_cursor(VirtIOGPU *g, struct virtio_gpu_scanout *s,
     transfer_iovec.iov_base = s->current_cursor->data;
     transfer_iovec.iov_len = res->width * res->height * 4;
 
-    rutabaga_resource_transfer_read(vr->rutabaga, 0,
-                                    resource_id, &transfer,
-                                    &transfer_iovec);
+    if (rutabaga_resource_transfer_read(vr->rutabaga, 0, resource_id,
+                                        &transfer, &transfer_iovec) != 0) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: failed to read cursor resource %u\n",
+                      __func__, resource_id);
+    }
 }
 
 static void

-- 
2.56.0.116.g6de20f6092dc



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

* [PATCH 4/4] contrib/vhost-user-gpu: reject non-32bpp cursor resources
  2026-11-10  8:31 [PATCH 0/4] virtio-gpu: reject non-32bpp cursor resources Marc-André Lureau
                   ` (2 preceding siblings ...)
  2026-11-10  8:31 ` [PATCH 3/4] virtio-gpu/rutabaga: " Marc-André Lureau
@ 2026-11-10  8:31 ` Marc-André Lureau
  2026-11-10  8:56   ` Daniel P. Berrangé
  2026-11-11 13:29   ` Akihiko Odaki
  3 siblings, 2 replies; 13+ messages in thread
From: Marc-André Lureau @ 2026-11-10  8:31 UTC (permalink / raw)
  To: qemu-devel
  Cc: Michael S. Tsirkin, Alex Bennée, Akihiko Odaki,
	Dmitry Osipenko, Stefano Garzarella, Gurchetan Singh,
	Marc-André Lureau

Cursor pixel data is copied as 32bpp, but the resource format is never
checked. virgl_renderer_get_cursor_data() sizes its buffer for the
resource's own format, while vg_virgl_update_cursor_data() copies
64 * 64 * 4 bytes from it: a 64x64 R8_UNORM resource gives a 4096 byte
buffer, so 12 KiB past its end is read and handed to the display
backend as cursor pixels.

Look up the resource format and refuse anything that is not 32bpp,
matching the virtio-gpu backends.

While at it, let g_autofree release the buffer: the 64x64 check returned
before it was freed, letting a guest grow the backend's memory with
repeated UPDATE_CURSOR.

Fixes: CVE-2026-122027
Fixes: d52c454aadcd ("contrib: add vhost-user-gpu")
Reported-by: Fernando Bortotti <https://gitlab.com/fernando.bortotti>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 contrib/vhost-user-gpu/vhost-user-gpu.c | 31 ++++++++++++++++++++-----------
 contrib/vhost-user-gpu/virgl.c          | 25 ++++++++++++++++++-------
 contrib/vhost-user-gpu/virgl.h          |  2 +-
 3 files changed, 39 insertions(+), 19 deletions(-)

diff --git a/contrib/vhost-user-gpu/vhost-user-gpu.c b/contrib/vhost-user-gpu/vhost-user-gpu.c
index f70b34c179f3..b34a1e013b8b 100644
--- a/contrib/vhost-user-gpu/vhost-user-gpu.c
+++ b/contrib/vhost-user-gpu/vhost-user-gpu.c
@@ -949,19 +949,22 @@ vg_handle_ctrl(VuDev *dev, int qidx)
     }
 }
 
-static void
+static bool
 update_cursor_data_simple(VuGpu *g, uint32_t resource_id, gpointer data)
 {
     struct virtio_gpu_simple_resource *res;
 
     res = virtio_gpu_find_resource(g, resource_id);
-    g_return_if_fail(res != NULL);
-    g_return_if_fail(pixman_image_get_width(res->image) == 64);
-    g_return_if_fail(pixman_image_get_height(res->image) == 64);
-    g_return_if_fail(
-        PIXMAN_FORMAT_BPP(pixman_image_get_format(res->image)) == 32);
+    if (!res || !res->image ||
+        pixman_image_get_width(res->image) != 64 ||
+        pixman_image_get_height(res->image) != 64 ||
+        PIXMAN_FORMAT_BPP(pixman_image_get_format(res->image)) != 32) {
+        g_debug("%s: invalid cursor resource %u", G_STRFUNC, resource_id);
+        return false;
+    }
 
     memcpy(data, pixman_image_get_data(res->image), 64 * 64 * sizeof(uint32_t));
+    return true;
 }
 
 static void
@@ -984,6 +987,7 @@ vg_process_cursor_cmd(VuGpu *g, struct virtio_gpu_update_cursor *cursor)
         break;
     }
     case VIRTIO_GPU_CMD_UPDATE_CURSOR: {
+        bool ok = true;
         VhostUserGpuMsg msg = {
             .request = VHOST_USER_GPU_CURSOR_UPDATE,
             .size = sizeof(VhostUserGpuCursorUpdate),
@@ -998,12 +1002,17 @@ vg_process_cursor_cmd(VuGpu *g, struct virtio_gpu_update_cursor *cursor)
             }
         };
         g_debug("%s: update", G_STRFUNC);
-        if (g->virgl) {
-            vg_virgl_update_cursor_data(g, cursor->resource_id,
-                                        msg.payload.cursor_update.data);
+        if (!cursor->resource_id) {
+            /* no resource: send a transparent cursor */
+        } else if (g->virgl) {
+            ok = vg_virgl_update_cursor_data(g, cursor->resource_id,
+                                             msg.payload.cursor_update.data);
         } else {
-            update_cursor_data_simple(g, cursor->resource_id,
-                                      msg.payload.cursor_update.data);
+            ok = update_cursor_data_simple(g, cursor->resource_id,
+                                           msg.payload.cursor_update.data);
+        }
+        if (!ok) {
+            break;
         }
         vg_send_msg(g, &msg, -1);
         break;
diff --git a/contrib/vhost-user-gpu/virgl.c b/contrib/vhost-user-gpu/virgl.c
index 0ef4b9d8c903..8af5a456ee5b 100644
--- a/contrib/vhost-user-gpu/virgl.c
+++ b/contrib/vhost-user-gpu/virgl.c
@@ -14,24 +14,35 @@
 
 #include "qemu/osdep.h"
 #include <virglrenderer.h>
+#include "hw/virtio/virtio-gpu-pixman.h"
 #include "virgl.h"
 
 #include <epoxy/gl.h>
 
-void
+bool
 vg_virgl_update_cursor_data(VuGpu *g, uint32_t resource_id,
                             gpointer data)
 {
-    uint32_t width, height;
-    uint32_t *cursor;
+    struct virgl_renderer_resource_info info = { 0 };
+    g_autofree uint32_t *cursor = NULL;
+    uint32_t width = 0, height = 0;
+
+    virgl_renderer_force_ctx_0();
+    if (virgl_renderer_resource_get_info(resource_id, &info) != 0 ||
+        !virtio_gpu_format_is_cursor_capable(info.virgl_format)) {
+        g_debug("%s: invalid cursor resource %u", G_STRFUNC, resource_id);
+        return false;
+    }
 
     cursor = virgl_renderer_get_cursor_data(resource_id, &width, &height);
-    g_return_if_fail(cursor != NULL);
-    g_return_if_fail(width == 64);
-    g_return_if_fail(height == 64);
+    if (!cursor || width != 64 || height != 64) {
+        g_debug("%s: failed to read cursor resource %u (%ux%u)",
+                G_STRFUNC, resource_id, width, height);
+        return false;
+    }
 
     memcpy(data, cursor, 64 * 64 * sizeof(uint32_t));
-    free(cursor);
+    return true;
 }
 
 static void
diff --git a/contrib/vhost-user-gpu/virgl.h b/contrib/vhost-user-gpu/virgl.h
index 17078783a50f..40caa766d3fe 100644
--- a/contrib/vhost-user-gpu/virgl.h
+++ b/contrib/vhost-user-gpu/virgl.h
@@ -20,7 +20,7 @@
 bool vg_virgl_init(VuGpu *g);
 uint32_t vg_virgl_get_num_capsets(void);
 void vg_virgl_process_cmd(VuGpu *vg, struct virtio_gpu_ctrl_command *cmd);
-void vg_virgl_update_cursor_data(VuGpu *g, uint32_t resource_id,
+bool vg_virgl_update_cursor_data(VuGpu *g, uint32_t resource_id,
                                  gpointer data);
 
 #endif

-- 
2.56.0.116.g6de20f6092dc



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

* Re: [PATCH 1/4] virtio-gpu: make some 2d callbacks statics
  2026-11-10  8:31 ` [PATCH 1/4] virtio-gpu: make some 2d callbacks statics Marc-André Lureau
@ 2026-11-10  8:49   ` Daniel P. Berrangé
  2026-11-11 13:13   ` Akihiko Odaki
  1 sibling, 0 replies; 13+ messages in thread
From: Daniel P. Berrangé @ 2026-11-10  8:49 UTC (permalink / raw)
  To: Marc-André Lureau
  Cc: qemu-devel, Michael S. Tsirkin, Alex Bennée, Akihiko Odaki,
	Dmitry Osipenko, Stefano Garzarella, Gurchetan Singh

On Tue, Nov 10, 2026 at 12:31:11PM +0400, Marc-André Lureau wrote:
> Those functions are not shared with other units.
> 
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  hw/display/virtio-gpu.c        | 12 +++++++-----
>  include/hw/virtio/virtio-gpu.h |  4 ----
>  2 files changed, 7 insertions(+), 9 deletions(-)

Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>


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] 13+ messages in thread

* Re: [PATCH 2/4] virtio-gpu/gl: reject non-32bpp cursor resources
  2026-11-10  8:31 ` [PATCH 2/4] virtio-gpu/gl: reject non-32bpp cursor resources Marc-André Lureau
@ 2026-11-10  8:53   ` Daniel P. Berrangé
  2026-11-11 13:19     ` Akihiko Odaki
  0 siblings, 1 reply; 13+ messages in thread
From: Daniel P. Berrangé @ 2026-11-10  8:53 UTC (permalink / raw)
  To: Marc-André Lureau
  Cc: qemu-devel, Michael S. Tsirkin, Alex Bennée, Akihiko Odaki,
	Dmitry Osipenko, Stefano Garzarella, Gurchetan Singh

On Tue, Nov 10, 2026 at 12:31:12PM +0400, Marc-André Lureau wrote:
> Cursor pixel data is copied as 32bpp, but the resource format is never
> checked. virgl_renderer_get_cursor_data() sizes its buffer for the
> resource's own format, while virtio_gpu_gl_update_cursor_data() copies
> width * height * 4 bytes from it: a 64x64 R8_UNORM resource gives a
> 4096 byte buffer and a 16384 byte read, so 12 KiB of host heap past the
> end of the allocation is sent to a connected VNC client as cursor data.
> 
> Look up the resource format and refuse anything that is not 32bpp,
> matching what the non-virgl paths accept. Querying the renderer covers
> blob resources: a blob carries no format in the virtio command and QEMU
> stores 0 for it. The virgl and virtio format enums have the same values
> for the accepted formats.
> 
> Fixes: CVE-2026-122027
> Fixes: 9d9e152136bd ("virtio-gpu: add 3d mode and virgl rendering support.")
> Reported-by: Fernando Bortotti <https://gitlab.com/fernando.bortotti>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  hw/display/virtio-gpu-gl.c            | 18 ++++++++++++++++++
>  include/hw/virtio/virtio-gpu-pixman.h | 13 +++++++++++++
>  2 files changed, 31 insertions(+)
> 
> diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
> index 2b7a41c46643..c314631b05f3 100644
> --- a/hw/display/virtio-gpu-gl.c
> +++ b/hw/display/virtio-gpu-gl.c
> @@ -31,6 +31,7 @@ static void virtio_gpu_gl_update_cursor_data(VirtIOGPU *g,
>                                               uint32_t resource_id)
>  {
>      VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
> +    struct virgl_renderer_resource_info info = { 0 };
>      uint32_t width, height;
>      uint32_t pixels, *data;
>  
> @@ -38,6 +39,20 @@ static void virtio_gpu_gl_update_cursor_data(VirtIOGPU *g,
>          return;
>      }
>  
> +    virgl_renderer_force_ctx_0();
> +    if (virgl_renderer_resource_get_info(resource_id, &info) != 0) {
> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: unknown cursor resource %u\n",
> +                      __func__, resource_id);
> +        return;
> +    }
> +
> +    if (!virtio_gpu_format_is_cursor_capable(info.virgl_format)) {
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +                      "%s: cursor resource %u has unsupported format %u\n",
> +                      __func__, resource_id, info.virgl_format);
> +        return;
> +    }
> +
>      data = virgl_renderer_get_cursor_data(resource_id, &width, &height);
>      if (!data) {
>          return;
> @@ -45,6 +60,9 @@ static void virtio_gpu_gl_update_cursor_data(VirtIOGPU *g,
>  
>      if (width != s->current_cursor->width ||
>          height != s->current_cursor->height) {
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +                      "%s: cursor resource %u has unsupported dimension %ux%u\n",
> +                      __func__, resource_id, width, height);
>          free(data);
>          return;
>      }
> diff --git a/include/hw/virtio/virtio-gpu-pixman.h b/include/hw/virtio/virtio-gpu-pixman.h
> index 4dba782758dc..d6043d2ca1df 100644
> --- a/include/hw/virtio/virtio-gpu-pixman.h
> +++ b/include/hw/virtio/virtio-gpu-pixman.h
> @@ -42,4 +42,17 @@ virtio_gpu_get_pixman_format(uint32_t virtio_gpu_format)
>      }
>  }
>  
> +/*
> + * Cursor data is copied as 32bpp; formats without a pixman mapping are
> + * rejected.
> + */
> +static inline bool
> +virtio_gpu_format_is_cursor_capable(uint32_t format)
> +{
> +    pixman_format_code_t pformat;
> +
> +    pformat = virtio_gpu_get_pixman_format(format);
> +    return pformat && PIXMAN_FORMAT_BPP(pformat) == 32;

Seems like 'pformat &&' is redundant since pixman_format_code_t is an
int (enum) and thus it is impossible for it to be 0, at the same time
as PIXMAN_FORMAT_BPP() reports 32.

Functionally it works though, so with/without it, 

  Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>



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] 13+ messages in thread

* Re: [PATCH 3/4] virtio-gpu/rutabaga: reject non-32bpp cursor resources
  2026-11-10  8:31 ` [PATCH 3/4] virtio-gpu/rutabaga: " Marc-André Lureau
@ 2026-11-10  8:54   ` Daniel P. Berrangé
  2026-11-11 13:21   ` Akihiko Odaki
  1 sibling, 0 replies; 13+ messages in thread
From: Daniel P. Berrangé @ 2026-11-10  8:54 UTC (permalink / raw)
  To: Marc-André Lureau
  Cc: qemu-devel, Michael S. Tsirkin, Alex Bennée, Akihiko Odaki,
	Dmitry Osipenko, Stefano Garzarella, Gurchetan Singh

On Tue, Nov 10, 2026 at 12:31:13PM +0400, Marc-André Lureau wrote:
> The cursor buffer is always 64x64x4, but rutabaga does not check the
> resource format before the transfer read. Gfxstream copies only as many
> bytes as the resource format needs, so an R8_UNORM cursor updates the
> first 4096 bytes of the 16384 byte buffer and leaves the rest untouched,
> while formats with a larger pixel size do not fit the request and fail.
> 
> Refuse cursor resources that are not 32bpp, reusing
> virtio_gpu_get_pixman_format() as the allowlist so the 32bpp formats the
> other backends accept keep working. res->format is the value passed to
> rutabaga_resource_create_3d(), so it matches what gfxstream stores. Blob
> resources carry no format; they were already rejected by the dimension
> check and stay rejected. Log the dimension mismatch and the transfer
> failure as well.
> 
> Fixes: CVE-2026-122027
> Fixes: 1dcc6adbc168 ("gfxstream + rutabaga: add initial support for gfxstream")
> Reported-by: Fernando Bortotti <https://gitlab.com/fernando.bortotti>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  hw/display/virtio-gpu-rutabaga.c | 19 ++++++++++++++++---
>  1 file changed, 16 insertions(+), 3 deletions(-)

Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>


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] 13+ messages in thread

* Re: [PATCH 4/4] contrib/vhost-user-gpu: reject non-32bpp cursor resources
  2026-11-10  8:31 ` [PATCH 4/4] contrib/vhost-user-gpu: " Marc-André Lureau
@ 2026-11-10  8:56   ` Daniel P. Berrangé
  2026-11-11 13:29   ` Akihiko Odaki
  1 sibling, 0 replies; 13+ messages in thread
From: Daniel P. Berrangé @ 2026-11-10  8:56 UTC (permalink / raw)
  To: Marc-André Lureau
  Cc: qemu-devel, Michael S. Tsirkin, Alex Bennée, Akihiko Odaki,
	Dmitry Osipenko, Stefano Garzarella, Gurchetan Singh

On Tue, Nov 10, 2026 at 12:31:14PM +0400, Marc-André Lureau wrote:
> Cursor pixel data is copied as 32bpp, but the resource format is never
> checked. virgl_renderer_get_cursor_data() sizes its buffer for the
> resource's own format, while vg_virgl_update_cursor_data() copies
> 64 * 64 * 4 bytes from it: a 64x64 R8_UNORM resource gives a 4096 byte
> buffer, so 12 KiB past its end is read and handed to the display
> backend as cursor pixels.
> 
> Look up the resource format and refuse anything that is not 32bpp,
> matching the virtio-gpu backends.
> 
> While at it, let g_autofree release the buffer: the 64x64 check returned
> before it was freed, letting a guest grow the backend's memory with
> repeated UPDATE_CURSOR.
> 
> Fixes: CVE-2026-122027
> Fixes: d52c454aadcd ("contrib: add vhost-user-gpu")
> Reported-by: Fernando Bortotti <https://gitlab.com/fernando.bortotti>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  contrib/vhost-user-gpu/vhost-user-gpu.c | 31 ++++++++++++++++++++-----------
>  contrib/vhost-user-gpu/virgl.c          | 25 ++++++++++++++++++-------
>  contrib/vhost-user-gpu/virgl.h          |  2 +-
>  3 files changed, 39 insertions(+), 19 deletions(-)

Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>


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] 13+ messages in thread

* Re: [PATCH 1/4] virtio-gpu: make some 2d callbacks statics
  2026-11-10  8:31 ` [PATCH 1/4] virtio-gpu: make some 2d callbacks statics Marc-André Lureau
  2026-11-10  8:49   ` Daniel P. Berrangé
@ 2026-11-11 13:13   ` Akihiko Odaki
  1 sibling, 0 replies; 13+ messages in thread
From: Akihiko Odaki @ 2026-11-11 13:13 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-devel
  Cc: Michael S. Tsirkin, Alex Bennée, Dmitry Osipenko,
	Stefano Garzarella, Gurchetan Singh

On 2026/11/10 17:31, Marc-André Lureau wrote:
> Those functions are not shared with other units.
> 
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

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

Regards,
Akihiko Odaki


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

* Re: [PATCH 2/4] virtio-gpu/gl: reject non-32bpp cursor resources
  2026-11-10  8:53   ` Daniel P. Berrangé
@ 2026-11-11 13:19     ` Akihiko Odaki
  0 siblings, 0 replies; 13+ messages in thread
From: Akihiko Odaki @ 2026-11-11 13:19 UTC (permalink / raw)
  To: Daniel P. Berrangé, Marc-André Lureau
  Cc: qemu-devel, Michael S. Tsirkin, Alex Bennée, Dmitry Osipenko,
	Stefano Garzarella, Gurchetan Singh

On 2026/11/10 17:53, Daniel P. Berrangé wrote:
> On Tue, Nov 10, 2026 at 12:31:12PM +0400, Marc-André Lureau wrote:
>> Cursor pixel data is copied as 32bpp, but the resource format is never
>> checked. virgl_renderer_get_cursor_data() sizes its buffer for the
>> resource's own format, while virtio_gpu_gl_update_cursor_data() copies
>> width * height * 4 bytes from it: a 64x64 R8_UNORM resource gives a
>> 4096 byte buffer and a 16384 byte read, so 12 KiB of host heap past the
>> end of the allocation is sent to a connected VNC client as cursor data.
>>
>> Look up the resource format and refuse anything that is not 32bpp,
>> matching what the non-virgl paths accept. Querying the renderer covers
>> blob resources: a blob carries no format in the virtio command and QEMU
>> stores 0 for it. The virgl and virtio format enums have the same values
>> for the accepted formats.
>>
>> Fixes: CVE-2026-122027
>> Fixes: 9d9e152136bd ("virtio-gpu: add 3d mode and virgl rendering support.")
>> Reported-by: Fernando Bortotti <https://gitlab.com/fernando.bortotti>
>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> ---
>>   hw/display/virtio-gpu-gl.c            | 18 ++++++++++++++++++
>>   include/hw/virtio/virtio-gpu-pixman.h | 13 +++++++++++++
>>   2 files changed, 31 insertions(+)
>>
>> diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
>> index 2b7a41c46643..c314631b05f3 100644
>> --- a/hw/display/virtio-gpu-gl.c
>> +++ b/hw/display/virtio-gpu-gl.c
>> @@ -31,6 +31,7 @@ static void virtio_gpu_gl_update_cursor_data(VirtIOGPU *g,
>>                                                uint32_t resource_id)
>>   {
>>       VirtIOGPUGL *gl = VIRTIO_GPU_GL(g);
>> +    struct virgl_renderer_resource_info info = { 0 };
>>       uint32_t width, height;
>>       uint32_t pixels, *data;
>>   
>> @@ -38,6 +39,20 @@ static void virtio_gpu_gl_update_cursor_data(VirtIOGPU *g,
>>           return;
>>       }
>>   
>> +    virgl_renderer_force_ctx_0();
>> +    if (virgl_renderer_resource_get_info(resource_id, &info) != 0) {
>> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: unknown cursor resource %u\n",
>> +                      __func__, resource_id);
>> +        return;
>> +    }
>> +
>> +    if (!virtio_gpu_format_is_cursor_capable(info.virgl_format)) {
>> +        qemu_log_mask(LOG_GUEST_ERROR,
>> +                      "%s: cursor resource %u has unsupported format %u\n",
>> +                      __func__, resource_id, info.virgl_format);
>> +        return;
>> +    }
>> +
>>       data = virgl_renderer_get_cursor_data(resource_id, &width, &height);
>>       if (!data) {
>>           return;
>> @@ -45,6 +60,9 @@ static void virtio_gpu_gl_update_cursor_data(VirtIOGPU *g,
>>   
>>       if (width != s->current_cursor->width ||
>>           height != s->current_cursor->height) {
>> +        qemu_log_mask(LOG_GUEST_ERROR,
>> +                      "%s: cursor resource %u has unsupported dimension %ux%u\n",
>> +                      __func__, resource_id, width, height);
>>           free(data);
>>           return;
>>       }
>> diff --git a/include/hw/virtio/virtio-gpu-pixman.h b/include/hw/virtio/virtio-gpu-pixman.h
>> index 4dba782758dc..d6043d2ca1df 100644
>> --- a/include/hw/virtio/virtio-gpu-pixman.h
>> +++ b/include/hw/virtio/virtio-gpu-pixman.h
>> @@ -42,4 +42,17 @@ virtio_gpu_get_pixman_format(uint32_t virtio_gpu_format)
>>       }
>>   }
>>   
>> +/*
>> + * Cursor data is copied as 32bpp; formats without a pixman mapping are
>> + * rejected.
>> + */
>> +static inline bool
>> +virtio_gpu_format_is_cursor_capable(uint32_t format)
>> +{
>> +    pixman_format_code_t pformat;
>> +
>> +    pformat = virtio_gpu_get_pixman_format(format);
>> +    return pformat && PIXMAN_FORMAT_BPP(pformat) == 32;
> 
> Seems like 'pformat &&' is redundant since pixman_format_code_t is an
> int (enum) and thus it is impossible for it to be 0, at the same time
> as PIXMAN_FORMAT_BPP() reports 32.
> 
> Functionally it works though, so with/without it,
> 
>    Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>

virtio_gpu_get_pixman_format() returns 0 for formats without a pixman 
mapping though 0 is not part of pixman_format_code_t. It is confusing, 
but the function is pre-existing, so:

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

Regards,
Akihiko Odaki


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

* Re: [PATCH 3/4] virtio-gpu/rutabaga: reject non-32bpp cursor resources
  2026-11-10  8:31 ` [PATCH 3/4] virtio-gpu/rutabaga: " Marc-André Lureau
  2026-11-10  8:54   ` Daniel P. Berrangé
@ 2026-11-11 13:21   ` Akihiko Odaki
  1 sibling, 0 replies; 13+ messages in thread
From: Akihiko Odaki @ 2026-11-11 13:21 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-devel
  Cc: Michael S. Tsirkin, Alex Bennée, Dmitry Osipenko,
	Stefano Garzarella, Gurchetan Singh

On 2026/11/10 17:31, Marc-André Lureau wrote:
> The cursor buffer is always 64x64x4, but rutabaga does not check the
> resource format before the transfer read. Gfxstream copies only as many
> bytes as the resource format needs, so an R8_UNORM cursor updates the
> first 4096 bytes of the 16384 byte buffer and leaves the rest untouched,
> while formats with a larger pixel size do not fit the request and fail.
> 
> Refuse cursor resources that are not 32bpp, reusing
> virtio_gpu_get_pixman_format() as the allowlist so the 32bpp formats the
> other backends accept keep working. res->format is the value passed to
> rutabaga_resource_create_3d(), so it matches what gfxstream stores. Blob
> resources carry no format; they were already rejected by the dimension
> check and stay rejected. Log the dimension mismatch and the transfer
> failure as well.
> 
> Fixes: CVE-2026-122027
> Fixes: 1dcc6adbc168 ("gfxstream + rutabaga: add initial support for gfxstream")
> Reported-by: Fernando Bortotti <https://gitlab.com/fernando.bortotti>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

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

Regards,
Akihiko Odaki


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

* Re: [PATCH 4/4] contrib/vhost-user-gpu: reject non-32bpp cursor resources
  2026-11-10  8:31 ` [PATCH 4/4] contrib/vhost-user-gpu: " Marc-André Lureau
  2026-11-10  8:56   ` Daniel P. Berrangé
@ 2026-11-11 13:29   ` Akihiko Odaki
  1 sibling, 0 replies; 13+ messages in thread
From: Akihiko Odaki @ 2026-11-11 13:29 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-devel
  Cc: Michael S. Tsirkin, Alex Bennée, Dmitry Osipenko,
	Stefano Garzarella, Gurchetan Singh

On 2026/11/10 17:31, Marc-André Lureau wrote:
> Cursor pixel data is copied as 32bpp, but the resource format is never
> checked. virgl_renderer_get_cursor_data() sizes its buffer for the
> resource's own format, while vg_virgl_update_cursor_data() copies
> 64 * 64 * 4 bytes from it: a 64x64 R8_UNORM resource gives a 4096 byte
> buffer, so 12 KiB past its end is read and handed to the display
> backend as cursor pixels.
> 
> Look up the resource format and refuse anything that is not 32bpp,
> matching the virtio-gpu backends.
> 
> While at it, let g_autofree release the buffer: the 64x64 check returned
> before it was freed, letting a guest grow the backend's memory with
> repeated UPDATE_CURSOR.
> 
> Fixes: CVE-2026-122027
> Fixes: d52c454aadcd ("contrib: add vhost-user-gpu")
> Reported-by: Fernando Bortotti <https://gitlab.com/fernando.bortotti>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

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

Regards,
Akihiko Odaki


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

end of thread, other threads:[~2026-11-11 13:30 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-10  8:31 [PATCH 0/4] virtio-gpu: reject non-32bpp cursor resources Marc-André Lureau
2026-11-10  8:31 ` [PATCH 1/4] virtio-gpu: make some 2d callbacks statics Marc-André Lureau
2026-11-10  8:49   ` Daniel P. Berrangé
2026-11-11 13:13   ` Akihiko Odaki
2026-11-10  8:31 ` [PATCH 2/4] virtio-gpu/gl: reject non-32bpp cursor resources Marc-André Lureau
2026-11-10  8:53   ` Daniel P. Berrangé
2026-11-11 13:19     ` Akihiko Odaki
2026-11-10  8:31 ` [PATCH 3/4] virtio-gpu/rutabaga: " Marc-André Lureau
2026-11-10  8:54   ` Daniel P. Berrangé
2026-11-11 13:21   ` Akihiko Odaki
2026-11-10  8:31 ` [PATCH 4/4] contrib/vhost-user-gpu: " Marc-André Lureau
2026-11-10  8:56   ` Daniel P. Berrangé
2026-11-11 13:29   ` Akihiko Odaki

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.