* [GIT PULL 0/9] Fixes for 11.1-rc
@ 2026-08-04 7:18 Marc-André Lureau
2026-08-04 7:18 ` [GIT PULL 1/9] hw/display/virtio-gpu: validate blob iov size Marc-André Lureau
` (10 more replies)
0 siblings, 11 replies; 22+ messages in thread
From: Marc-André Lureau @ 2026-08-04 7:18 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanha
The following changes since commit b428fe036233cbd15d37e3c027ab6ca4d3661a80:
Merge tag 'pull-target-arm-20260731' of https://gitlab.com/pm215/qemu into staging (2026-07-31 16:19:04 -0400)
are available in the Git repository at:
https://gitlab.com/marcandre.lureau/qemu.git tags/fix-pr-v1
for you to fetch changes up to 8876b366d7cac1f65978b8f8472725b980a1abfb:
qapi/dump: add allowed-by-guest feature to win-dmp (2026-08-04 11:18:43 +0400)
----------------------------------------------------------------
Fixes for 11.1-rc
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
----------------------------------------------------------------
Akihiko Odaki (1):
hw/display/virtio-gpu: Always reject invalid scanout bounds
Ankur Saini (1):
virtio-gpu: reject requests with short/truncated control headers
Bin Guo (1):
hw/display/virtio-gpu: Unmap DMA regions on reset
Denis V. Lunev (1):
qapi/dump: add allowed-by-guest feature to win-dmp
Marc-André Lureau (5):
hw/display/virtio-gpu: validate blob iov size
hw/display/vga: fix panning_buf OOB after text/graphics switch
vhost-user-gpu: fix integer overflow in buffer allocation
hw/display/virtio-gpu: fix offset wraparound in scanout_blob_to_fb
hw/display/virtio-gpu: drop redundant node->value NULL checks
qapi/dump.json | 9 +++-
contrib/vhost-user-gpu/vugpu.h | 1 +
include/hw/virtio/virtio-gpu.h | 8 ++++
contrib/vhost-user-gpu/vhost-user-gpu.c | 29 +++++++-----
contrib/vhost-user-gpu/vugbm.c | 11 ++++-
hw/display/vga.c | 7 +--
hw/display/virtio-gpu-base.c | 4 +-
hw/display/virtio-gpu-rutabaga.c | 6 +++
hw/display/virtio-gpu-virgl.c | 20 ++++-----
hw/display/virtio-gpu.c | 80 ++++++++++++++++++++++++---------
10 files changed, 126 insertions(+), 49 deletions(-)
^ permalink raw reply [flat|nested] 22+ messages in thread
* [GIT PULL 1/9] hw/display/virtio-gpu: validate blob iov size
2026-08-04 7:18 [GIT PULL 0/9] Fixes for 11.1-rc Marc-André Lureau
@ 2026-08-04 7:18 ` Marc-André Lureau
2026-08-04 7:18 ` [GIT PULL 2/9] hw/display/vga: fix panning_buf OOB after text/graphics switch Marc-André Lureau
` (9 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Marc-André Lureau @ 2026-08-04 7:18 UTC (permalink / raw)
To: qemu-devel
Cc: stefanha, Alex Bennée, Akihiko Odaki, Dmitry Osipenko,
Michael S. Tsirkin
virtio_gpu_resource_create_blob() stores the guest-controlled blob_size
without checking it against the total size of the iov backing entries.
Since both values are independently guest-controlled, a malicious guest
can set blob_size much larger than the actual iov backing. Subsequent
SET_SCANOUT_BLOB checks bounds against the inflated blob_size, allowing
a pixman surface to be created over the undersized buffer. Any display
refresh then reads past the actual allocation, potentially crashing
QEMU or leaking host memory contents depending on the backing type.
Validate that the iov backing is at least as large as the declared
blob_size in create_blob (when nr_entries > 0, since the spec permits
deferred backing), attach_backing (when attaching to a blob resource),
and the blob migration load path.
Fixes: CVE-2026-66021
Fixes: e0933d91b1cd ("virtio-gpu: Add virtio_gpu_resource_create_blob")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3945
Reported-by: "sundayjiang(蒋浩天)" <sundayjiang@tencent.com>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260729161431.1180691-1-marcandre.lureau@redhat.com>
---
hw/display/virtio-gpu.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 4d46a4eb10fa..0206910cc377 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -372,6 +372,17 @@ static void virtio_gpu_resource_create_blob(VirtIOGPU *g,
return;
}
+ 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);
}
@@ -993,6 +1004,15 @@ virtio_gpu_resource_attach_backing(VirtIOGPU *g,
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);
+ return;
+ }
+
if (!res->image) {
virtio_gpu_init_udmabuf(res);
}
@@ -1493,6 +1513,14 @@ static int virtio_gpu_blob_load(QEMUFile *f, void *opaque, size_t size,
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;
--
2.55.0
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [GIT PULL 2/9] hw/display/vga: fix panning_buf OOB after text/graphics switch
2026-08-04 7:18 [GIT PULL 0/9] Fixes for 11.1-rc Marc-André Lureau
2026-08-04 7:18 ` [GIT PULL 1/9] hw/display/virtio-gpu: validate blob iov size Marc-André Lureau
@ 2026-08-04 7:18 ` Marc-André Lureau
2026-08-04 7:18 ` [GIT PULL 3/9] vhost-user-gpu: fix integer overflow in buffer allocation Marc-André Lureau
` (8 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Marc-André Lureau @ 2026-08-04 7:18 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanha, Gerd Hoffmann
The fields last_width and last_height serve two purposes: the text
renderer counts in characters, the graphics renderer in pixels.
panning_buf reallocation is guarded by geometry-change check, so the
unit mismatch can trick it into thinking nothing changed when the
resolution actually grew.
A guest can trigger this by switching graphics -> text -> graphics:
1. Enter graphics mode with a small width (CR01=0x00, 8 pixels).
The predicate fires and panning_buf is allocated for that width.
2. Switch to text mode with a large width (CR01=0xFF, 256 chars).
The text renderer stores 256 into last_width. The text path
never touches panning_buf.
3. Switch back to graphics with a width that happens to equal 256
in pixels (CR01=0x1F, 32*8 = 256). The predicate sees
256 == 256 and skips the realloc. With horizontal pel panning
enabled, vga_draw_line4() then writes a full 256-pixel scanline
into the buffer still sized for 8 pixels -- a 960-byte heap
overflow on every scanline, every refresh.
Fix it by reallocating unconditionally panning_buf on
vga_draw_graphic().
Fixes: CVE-2026-17516
Fixes: 973a724eb006 ("vga: implement horizontal pel panning in graphics modes")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4085
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Warisjeet Singh <sinxx198@gmail.com>
[ Marc- André - drop realloc() resize condition & commit message ]
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260728151456.3704099-1-marcandre.lureau@redhat.com>
---
hw/display/vga.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/hw/display/vga.c b/hw/display/vga.c
index abe3f8e07758..da0c331486eb 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -1647,11 +1647,12 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
s->last_line_offset = s->params.line_offset;
s->last_depth = depth;
s->last_byteswap = byteswap;
- /* 16 extra pixels are needed for double-width planar modes. */
- s->panning_buf = g_realloc(s->panning_buf,
- (disp_width + 16) * sizeof(uint32_t));
full_update = 1;
}
+
+ /* 16 extra pixels are needed for double-width planar modes. */
+ s->panning_buf = g_realloc(s->panning_buf,
+ (disp_width + 16) * sizeof(uint32_t));
if (surface_data(surface) != s->vram_ptr + (s->params.start_addr * 4)
&& !surface_is_allocated(surface)) {
/* base address changed (page flip) -> shared display surfaces
--
2.55.0
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [GIT PULL 3/9] vhost-user-gpu: fix integer overflow in buffer allocation
2026-08-04 7:18 [GIT PULL 0/9] Fixes for 11.1-rc Marc-André Lureau
2026-08-04 7:18 ` [GIT PULL 1/9] hw/display/virtio-gpu: validate blob iov size Marc-André Lureau
2026-08-04 7:18 ` [GIT PULL 2/9] hw/display/vga: fix panning_buf OOB after text/graphics switch Marc-André Lureau
@ 2026-08-04 7:18 ` Marc-André Lureau
2026-08-04 7:18 ` [GIT PULL 4/9] hw/display/virtio-gpu: fix offset wraparound in scanout_blob_to_fb Marc-André Lureau
` (7 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Marc-André Lureau @ 2026-08-04 7:18 UTC (permalink / raw)
To: qemu-devel
Cc: stefanha, Marc-André Lureau, Michael S. Tsirkin,
Stefano Garzarella
A malicious guest can trigger a heap buffer overflow in the
vhost-user-gpu backend by sending a VIRTIO_GPU_CMD_RESOURCE_CREATE_2D
with large width and height values (e.g. 65537x65537). The allocation
size width * height * 4 silently wraps in uint32_t arithmetic,
resulting in a much smaller allocation than expected. Subsequent
VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D writes past the heap buffer.
The in-tree virtio-gpu device (hw/display/virtio-gpu.c) already handles
this via calc_image_hostmem() with uint64_t arithmetic and an overflow
check. Apply the same approach to the vhost-user-gpu contrib backend:
- Add an overflow check in vugbm_buffer_create() rejecting dimensions
where width * height * 4 exceeds UINT32_MAX
- Promote the size arithmetic to uint64_t in mem_alloc_bo() and
udmabuf_get_size()
- Check the return value of vugbm_buffer_create() in
vg_resource_create_2d(), which was previously ignored
Fixes: CVE-2026-15264
Reported-by: "Vulnerability Report" <vr@darknavy.com>
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3940
Signed-off-by: Marc-Andre Lureau <marcandre.lureau@redhat.com>
Acked-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Message-ID: <20260710134720.2317856-1-marcandre.lureau@redhat.com>
---
contrib/vhost-user-gpu/vhost-user-gpu.c | 8 +++++++-
contrib/vhost-user-gpu/vugbm.c | 11 +++++++++--
2 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/contrib/vhost-user-gpu/vhost-user-gpu.c b/contrib/vhost-user-gpu/vhost-user-gpu.c
index bb41758e3454..ee9858c397ce 100644
--- a/contrib/vhost-user-gpu/vhost-user-gpu.c
+++ b/contrib/vhost-user-gpu/vhost-user-gpu.c
@@ -388,7 +388,13 @@ vg_resource_create_2d(VuGpu *g,
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
return;
}
- vugbm_buffer_create(&res->buffer, &g->gdev, c2d.width, c2d.height);
+ if (!vugbm_buffer_create(&res->buffer, &g->gdev, c2d.width, c2d.height)) {
+ g_critical("%s: buffer creation failed %d %d %d",
+ __func__, c2d.resource_id, c2d.width, c2d.height);
+ g_free(res);
+ cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
+ return;
+ }
res->image = pixman_image_create_bits(pformat,
c2d.width,
c2d.height,
diff --git a/contrib/vhost-user-gpu/vugbm.c b/contrib/vhost-user-gpu/vugbm.c
index 503d0a4566f8..710d54529779 100644
--- a/contrib/vhost-user-gpu/vugbm.c
+++ b/contrib/vhost-user-gpu/vugbm.c
@@ -13,7 +13,7 @@
static bool
mem_alloc_bo(struct vugbm_buffer *buf)
{
- buf->mmap = g_malloc(buf->width * buf->height * 4);
+ buf->mmap = g_malloc((uint64_t)buf->width * buf->height * 4);
buf->stride = buf->width * 4;
return true;
}
@@ -53,7 +53,8 @@ struct udmabuf_create {
static size_t
udmabuf_get_size(struct vugbm_buffer *buf)
{
- return ROUND_UP(buf->width * buf->height * 4, qemu_real_host_page_size());
+ return ROUND_UP((uint64_t)buf->width * buf->height * 4,
+ qemu_real_host_page_size());
}
static bool
@@ -293,6 +294,12 @@ bool
vugbm_buffer_create(struct vugbm_buffer *buffer, struct vugbm_device *dev,
uint32_t width, uint32_t height)
{
+ uint64_t size = (uint64_t)width * height * 4;
+ if (size > UINT32_MAX) {
+ g_warning("buffer dimensions too large: %ux%u", width, height);
+ return false;
+ }
+
buffer->dev = dev;
buffer->width = width;
buffer->height = height;
--
2.55.0
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [GIT PULL 4/9] hw/display/virtio-gpu: fix offset wraparound in scanout_blob_to_fb
2026-08-04 7:18 [GIT PULL 0/9] Fixes for 11.1-rc Marc-André Lureau
` (2 preceding siblings ...)
2026-08-04 7:18 ` [GIT PULL 3/9] vhost-user-gpu: fix integer overflow in buffer allocation Marc-André Lureau
@ 2026-08-04 7:18 ` Marc-André Lureau
2026-08-04 7:18 ` [GIT PULL 5/9] hw/display/virtio-gpu: drop redundant node->value NULL checks Marc-André Lureau
` (6 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Marc-André Lureau @ 2026-08-04 7:18 UTC (permalink / raw)
To: qemu-devel
Cc: stefanha, Michael S. Tsirkin, Alex Bennée, Akihiko Odaki,
Dmitry Osipenko
virtio_gpu_scanout_blob_to_fb() computes the framebuffer offset from
guest-controlled offsets[0], r.x, r.y and stride using uint32_t
arithmetic. When the sum exceeds UINT32_MAX, silent wraparound lets
the guest steer the scanout to an arbitrary in-bounds region of the
blob instead of the intended rectangle.
Compute the offset in uint64_t, reject values exceeding UINT32_MAX
(the width of fb->offset), and only store into fb->offset once both
range checks pass.
("[PATCH] hw/display/virtio-gpu: Remove the bytes_pp field")
Fixes: 32db3c63ae11 ("virtio-gpu: Add virtio_gpu_set_scanout_blob")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3871
Based-on: <20260719-bpp-v1-1-9b91946d6cf3@rsg.ci.i.u-tokyo.ac.jp>
Reported-by: Cyber_black <Cyberblackk@proton.me>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260725122734.1775774-1-marcandre.lureau@redhat.com>
---
hw/display/virtio-gpu.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 0206910cc377..51592b49c21e 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -777,7 +777,7 @@ bool virtio_gpu_scanout_blob_to_fb(struct virtio_gpu_framebuffer *fb,
struct virtio_gpu_set_scanout_blob *ss,
uint64_t blob_size)
{
- uint64_t fbend;
+ uint64_t fbend, offset;
uint32_t bytes_pp;
fb->format = virtio_gpu_get_pixman_format(ss->format);
@@ -807,18 +807,20 @@ bool virtio_gpu_scanout_blob_to_fb(struct virtio_gpu_framebuffer *fb,
return false;
}
- fb->offset = ss->offsets[0] + ss->r.x * bytes_pp + ss->r.y * fb->stride;
+ offset = (uint64_t)ss->offsets[0] + (uint64_t)ss->r.x * bytes_pp +
+ (uint64_t)ss->r.y * fb->stride;
- fbend = fb->offset;
- fbend += (uint64_t) fb->stride * ss->r.height;
+ fbend = offset + (uint64_t)fb->stride * ss->r.height;
- if (fbend > blob_size) {
+ if (offset > UINT32_MAX || fbend > blob_size) {
qemu_log_mask(LOG_GUEST_ERROR,
- "%s: fb end out of range\n",
+ "%s: invalid fb bounds\n",
__func__);
return false;
}
+ fb->offset = offset;
+
return true;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [GIT PULL 5/9] hw/display/virtio-gpu: drop redundant node->value NULL checks
2026-08-04 7:18 [GIT PULL 0/9] Fixes for 11.1-rc Marc-André Lureau
` (3 preceding siblings ...)
2026-08-04 7:18 ` [GIT PULL 4/9] hw/display/virtio-gpu: fix offset wraparound in scanout_blob_to_fb Marc-André Lureau
@ 2026-08-04 7:18 ` Marc-André Lureau
2026-08-04 7:18 ` [GIT PULL 6/9] virtio-gpu: reject requests with short/truncated control headers Marc-André Lureau
` (5 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Marc-André Lureau @ 2026-08-04 7:18 UTC (permalink / raw)
To: qemu-devel
Cc: stefanha, Alex Bennée, Akihiko Odaki, Dmitry Osipenko,
Michael S. Tsirkin
QAPI-generated list visitors guarantee that node->value is never NULL:
the input visitor allocates it via g_malloc0() in visit_start_struct(),
and on failure the entire list parse is aborted and freed.
Remove the unnecessary NULL checks from both callsites iterating
g->conf.outputs.
Resolves: Coverity CID 1664272
Fixes: 8dc8449a678f ("hw/display/virtio-gpu: Avoid leaking migration blocker")
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260730114751.3515083-1-marcandre.lureau@redhat.com>
---
hw/display/virtio-gpu-base.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c
index 946e56b42f61..270fbaae1029 100644
--- a/hw/display/virtio-gpu-base.c
+++ b/hw/display/virtio-gpu-base.c
@@ -69,7 +69,7 @@ virtio_gpu_base_generate_edid(VirtIOGPUBase *g, int scanout,
for (output_idx = 0, node = g->conf.outputs;
output_idx <= scanout && node; output_idx++, node = node->next) {
- if (output_idx == scanout && node->value && node->value->name) {
+ if (output_idx == scanout && node->value->name) {
info.name = node->value->name;
break;
}
@@ -206,7 +206,7 @@ virtio_gpu_base_device_realize(DeviceState *qdev,
error_setg(errp, "invalid outputs > %d", g->conf.max_outputs);
return false;
}
- if (node->value && node->value->name &&
+ if (node->value->name &&
strlen(node->value->name) > EDID_NAME_MAX_LENGTH) {
error_setg(errp, "invalid output name '%s' > %d",
node->value->name, EDID_NAME_MAX_LENGTH);
--
2.55.0
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [GIT PULL 6/9] virtio-gpu: reject requests with short/truncated control headers
2026-08-04 7:18 [GIT PULL 0/9] Fixes for 11.1-rc Marc-André Lureau
` (4 preceding siblings ...)
2026-08-04 7:18 ` [GIT PULL 5/9] hw/display/virtio-gpu: drop redundant node->value NULL checks Marc-André Lureau
@ 2026-08-04 7:18 ` Marc-André Lureau
2026-08-04 7:18 ` [GIT PULL 7/9] hw/display/virtio-gpu: Always reject invalid scanout bounds Marc-André Lureau
` (4 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Marc-André Lureau @ 2026-08-04 7:18 UTC (permalink / raw)
To: qemu-devel
Cc: stefanha, Michael S. Tsirkin, Stefano Garzarella,
Marc-André Lureau, Alex Bennée, Akihiko Odaki,
Dmitry Osipenko
From: Ankur Saini <ankur98saini@gmail.com>
A short control request can leave command data partially initialized.
For the common header, guest-controlled flags can then cause stale fence
metadata to be returned to the guest.
The command fill helpers detect a short copy but only log and return.
For the common header this leaves the request without any completion;
for type-specific commands the caller still completes the request but
reports VIRTIO_GPU_RESP_OK_NODATA, masking the error. Make
VIRTIO_GPU_FILL_CMD() clear the partially copied object and complete the
request with ERR_INVALID_PARAMETER. Make VUGPU_FILL_CMD() report the same
error through the existing vhost-user-gpu dispatcher. This also rejects
truncated type-specific commands.
The vhost-user-gpu common header is copied outside VUGPU_FILL_CMD(), so
clear it and complete the request directly when that copy is short.
Fixes: CVE-2026-66021
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4094
Reported-by: Ankur Saini <ankur98saini@gmail.com>
Suggested-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Ankur Saini <ankur98saini@gmail.com>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260803-virtio-gpu-short-header-v3-1-936c1daa8e61@gmail.com>
---
contrib/vhost-user-gpu/vugpu.h | 1 +
include/hw/virtio/virtio-gpu.h | 3 +++
contrib/vhost-user-gpu/vhost-user-gpu.c | 21 ++++++++++++---------
3 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/contrib/vhost-user-gpu/vugpu.h b/contrib/vhost-user-gpu/vugpu.h
index 2374eb90cb9b..aaf2870cb24d 100644
--- a/contrib/vhost-user-gpu/vugpu.h
+++ b/contrib/vhost-user-gpu/vugpu.h
@@ -179,6 +179,7 @@ struct virtio_gpu_ctrl_command {
if (vugpufillcmd_s_ != sizeof(out)) { \
g_critical("%s: command size incorrect %zu vs %zu", \
__func__, vugpufillcmd_s_, sizeof(out)); \
+ cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; \
return; \
} \
} while (0)
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 2f60c72078b3..f965defa6b25 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -315,6 +315,9 @@ struct VirtIOGPURutabaga {
qemu_log_mask(LOG_GUEST_ERROR, \
"%s: command size incorrect %zu vs %zu\n", \
__func__, virtiogpufillcmd_s_, sizeof(out)); \
+ memset(&out, 0, sizeof(out)); \
+ virtio_gpu_ctrl_response_nodata( \
+ g, cmd, VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER); \
return; \
} \
} while (0)
diff --git a/contrib/vhost-user-gpu/vhost-user-gpu.c b/contrib/vhost-user-gpu/vhost-user-gpu.c
index ee9858c397ce..786488150932 100644
--- a/contrib/vhost-user-gpu/vhost-user-gpu.c
+++ b/contrib/vhost-user-gpu/vhost-user-gpu.c
@@ -930,16 +930,19 @@ vg_handle_ctrl(VuDev *dev, int qidx)
if (len != sizeof(cmd->cmd_hdr)) {
g_warning("%s: command size incorrect %zu vs %zu\n",
__func__, len, sizeof(cmd->cmd_hdr));
- }
-
- virtio_gpu_ctrl_hdr_bswap(&cmd->cmd_hdr);
- g_debug("%d %s\n", cmd->cmd_hdr.type,
- vg_cmd_to_string(cmd->cmd_hdr.type));
-
- if (vg->virgl) {
- vg_virgl_process_cmd(vg, cmd);
+ memset(&cmd->cmd_hdr, 0, sizeof(cmd->cmd_hdr));
+ vg_ctrl_response_nodata(
+ vg, cmd, VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER);
} else {
- vg_process_cmd(vg, cmd);
+ virtio_gpu_ctrl_hdr_bswap(&cmd->cmd_hdr);
+ g_debug("%d %s\n", cmd->cmd_hdr.type,
+ vg_cmd_to_string(cmd->cmd_hdr.type));
+
+ if (vg->virgl) {
+ vg_virgl_process_cmd(vg, cmd);
+ } else {
+ vg_process_cmd(vg, cmd);
+ }
}
if (cmd->state != VG_CMD_STATE_FINISHED) {
--
2.55.0
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [GIT PULL 7/9] hw/display/virtio-gpu: Always reject invalid scanout bounds
2026-08-04 7:18 [GIT PULL 0/9] Fixes for 11.1-rc Marc-André Lureau
` (5 preceding siblings ...)
2026-08-04 7:18 ` [GIT PULL 6/9] virtio-gpu: reject requests with short/truncated control headers Marc-André Lureau
@ 2026-08-04 7:18 ` Marc-André Lureau
2026-08-04 7:18 ` [GIT PULL 8/9] hw/display/virtio-gpu: Unmap DMA regions on reset Marc-André Lureau
` (3 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Marc-André Lureau @ 2026-08-04 7:18 UTC (permalink / raw)
To: qemu-devel
Cc: stefanha, Alex Bennée, Akihiko Odaki, Dmitry Osipenko,
Michael S. Tsirkin
From: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
virtio-gpu does not consistently check scanout bounds with wraparound
handling. In the unchecked virgl SET_SCANOUT path, guest dimensions
reach qemu_console_resize(), qemu_create_displaysurface(), and
ultimately qemu_pixman_image_new_shareable(..., &error_abort), so an
invalid rectangle can terminate QEMU. Implement a check with proper
wraparound handling and apply it consistently.
Fixes: 9d9e152136bd ("virtio-gpu: add 3d mode and virgl rendering support.")
Fixes: 32db3c63ae11 ("virtio-gpu: Add virtio_gpu_set_scanout_blob")
Fixes: 7c092f17ccee ("virtio-gpu: Handle resource blob commands")
Fixes: 1dcc6adbc168 ("gfxstream + rutabaga: add initial support for gfxstream")
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260803-scanout-v1-1-c9831dafdab2@rsg.ci.i.u-tokyo.ac.jp>
---
include/hw/virtio/virtio-gpu.h | 5 +++++
hw/display/virtio-gpu-rutabaga.c | 6 ++++++
hw/display/virtio-gpu-virgl.c | 20 +++++++++-----------
hw/display/virtio-gpu.c | 36 ++++++++++++++++++++++--------------
4 files changed, 42 insertions(+), 25 deletions(-)
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index f965defa6b25..220231ec9d43 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -366,6 +366,11 @@ 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,
+ const struct virtio_gpu_rect *r,
+ uint32_t *error);
+
/**
* virtio_gpu_scanout_blob_to_fb() - fill out fb based on scanout data
* fb: the frame-buffer descriptor to fill out
diff --git a/hw/display/virtio-gpu-rutabaga.c b/hw/display/virtio-gpu-rutabaga.c
index e28aad94eead..a054f8117f14 100644
--- a/hw/display/virtio-gpu-rutabaga.c
+++ b/hw/display/virtio-gpu-rutabaga.c
@@ -315,6 +315,12 @@ rutabaga_cmd_set_scanout(VirtIOGPU *g, struct virtio_gpu_ctrl_command *cmd)
res = virtio_gpu_find_resource(g, ss.resource_id);
CHECK(res, cmd);
+ if (!virtio_gpu_check_scanout_bounds(ss.scanout_id, ss.resource_id,
+ res->width, res->height, &ss.r,
+ &cmd->error)) {
+ return;
+ }
+
if (!res->image) {
pixman_format_code_t pformat;
pformat = virtio_gpu_get_pixman_format(res->format);
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index d9e5b0110497..6e298f997d66 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -560,7 +560,7 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g,
}
g->parent_obj.enable = 1;
- if (ss.resource_id && ss.r.width && ss.r.height) {
+ if (ss.resource_id) {
struct virgl_renderer_resource_info info;
void *d3d_tex2d = NULL;
@@ -581,6 +581,11 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g,
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
return;
}
+ if (!virtio_gpu_check_scanout_bounds(ss.scanout_id, ss.resource_id,
+ info.width, info.height, &ss.r,
+ &cmd->error)) {
+ return;
+ }
qemu_console_resize(g->parent_obj.scanout[ss.scanout_id].con,
ss.r.width, ss.r.height);
virgl_renderer_force_ctx_0();
@@ -987,16 +992,9 @@ static void virgl_cmd_set_scanout_blob(VirtIOGPU *g,
return;
}
- if (ss.width < 16 ||
- ss.height < 16 ||
- ss.r.x + ss.r.width > ss.width ||
- ss.r.y + ss.r.height > ss.height) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout %d bounds for"
- " resource %d, rect (%d,%d)+%d,%d, fb %d %d\n",
- __func__, ss.scanout_id, ss.resource_id,
- ss.r.x, ss.r.y, ss.r.width, ss.r.height,
- ss.width, ss.height);
- cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+ if (!virtio_gpu_check_scanout_bounds(ss.scanout_id, ss.resource_id,
+ ss.width, ss.height, &ss.r,
+ &cmd->error)) {
return;
}
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 51592b49c21e..c15d4b527d0e 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -633,6 +633,26 @@ static uint32_t virtio_gpu_format_bytes_pp(pixman_format_code_t format)
return DIV_ROUND_UP(PIXMAN_FORMAT_BPP(format), 8);
}
+bool virtio_gpu_check_scanout_bounds(uint32_t scanout_id, uint32_t resource_id,
+ uint32_t width, uint32_t height,
+ const struct virtio_gpu_rect *r,
+ uint32_t *error)
+{
+ if (r->width < 16 ||
+ r->height < 16 ||
+ (uint64_t)r->x + r->width > width ||
+ (uint64_t)r->y + r->height > height) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout %d bounds for"
+ " resource %d, fb %d %d, rect (%d,%d)+%d,%d\n",
+ __func__, scanout_id, resource_id, width, height,
+ r->x, r->y, r->width, r->height);
+ *error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+ return false;
+ }
+
+ return true;
+}
+
static bool virtio_gpu_do_set_scanout(VirtIOGPU *g,
uint32_t scanout_id,
struct virtio_gpu_framebuffer *fb,
@@ -646,20 +666,8 @@ static bool virtio_gpu_do_set_scanout(VirtIOGPU *g,
scanout = &g->parent_obj.scanout[scanout_id];
- if (r->x > fb->width ||
- r->y > fb->height ||
- r->width < 16 ||
- r->height < 16 ||
- r->width > fb->width ||
- r->height > fb->height ||
- r->x + r->width > fb->width ||
- r->y + r->height > fb->height) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout %d bounds for"
- " resource %d, rect (%d,%d)+%d,%d, fb %d %d\n",
- __func__, scanout_id, res->resource_id,
- r->x, r->y, r->width, r->height,
- fb->width, fb->height);
- *error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+ if (!virtio_gpu_check_scanout_bounds(scanout_id, res->resource_id,
+ fb->width, fb->height, r, error)) {
return false;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [GIT PULL 8/9] hw/display/virtio-gpu: Unmap DMA regions on reset
2026-08-04 7:18 [GIT PULL 0/9] Fixes for 11.1-rc Marc-André Lureau
` (6 preceding siblings ...)
2026-08-04 7:18 ` [GIT PULL 7/9] hw/display/virtio-gpu: Always reject invalid scanout bounds Marc-André Lureau
@ 2026-08-04 7:18 ` Marc-André Lureau
2026-08-04 7:18 ` [GIT PULL 9/9] qapi/dump: add allowed-by-guest feature to win-dmp Marc-André Lureau
` (2 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Marc-André Lureau @ 2026-08-04 7:18 UTC (permalink / raw)
To: qemu-devel
Cc: stefanha, Michael S. Tsirkin, Alex Bennée, Akihiko Odaki,
Dmitry Osipenko
From: Bin Guo <guobin@linux.alibaba.com>
virtio_gpu_reset() freed in-flight commands without unmapping the
DMA regions acquired by virtqueue_pop(). Call virtqueue_detach_element()
before g_free() in both drain loops.
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3467
Cc: qemu-stable@nongnu.org
Signed-off-by: Bin Guo <guobin@linux.alibaba.com>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260803082158.62998-1-guobin@linux.alibaba.com>
---
hw/display/virtio-gpu.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index c15d4b527d0e..fbb6fec7a0ad 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1725,12 +1725,14 @@ void virtio_gpu_reset(VirtIODevice *vdev)
while (!QTAILQ_EMPTY(&g->cmdq)) {
cmd = QTAILQ_FIRST(&g->cmdq);
QTAILQ_REMOVE(&g->cmdq, cmd, next);
+ virtqueue_detach_element(cmd->vq, &cmd->elem, 0);
g_free(cmd);
}
while (!QTAILQ_EMPTY(&g->fenceq)) {
cmd = QTAILQ_FIRST(&g->fenceq);
QTAILQ_REMOVE(&g->fenceq, cmd, next);
+ virtqueue_detach_element(cmd->vq, &cmd->elem, 0);
g->inflight--;
g_free(cmd);
}
--
2.55.0
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [GIT PULL 9/9] qapi/dump: add allowed-by-guest feature to win-dmp
2026-08-04 7:18 [GIT PULL 0/9] Fixes for 11.1-rc Marc-André Lureau
` (7 preceding siblings ...)
2026-08-04 7:18 ` [GIT PULL 8/9] hw/display/virtio-gpu: Unmap DMA regions on reset Marc-André Lureau
@ 2026-08-04 7:18 ` Marc-André Lureau
2026-08-04 19:07 ` [GIT PULL 0/9] Fixes for 11.1-rc Marc-André Lureau
2026-08-04 19:21 ` [GIT PULL v2 " Marc-André Lureau
10 siblings, 0 replies; 22+ messages in thread
From: Marc-André Lureau @ 2026-08-04 7:18 UTC (permalink / raw)
To: qemu-devel
Cc: stefanha, Marc-André Lureau, Ani Sinha, Eric Blake,
Markus Armbruster
From: "Denis V. Lunev" <den@openvz.org>
Commit 1c0e259c5a35 ("dump: make win_dump_available() check vmcoreinfo
for a Windows dump header") changed two things in a way that is visible
to QMP clients but not to introspection:
query-dump-guest-memory-capability now lists win-dmp only for a guest
that has published a Windows dump header through the vmcoreinfo device,
and dump-guest-memory, which shares win_dump_available(), rejects the
format otherwise. Before that, both accepted win-dmp on any x86
machine.
A client that wants to select win-dmp automatically therefore cannot
trust the capability query on its own: on an older QEMU it reports
win-dmp for every x86 guest, Linux ones included, where the resulting
dump is useless. libvirt ran into exactly this while picking a format
for on_crash and watchdog triggered dumps, and has no way to tell the
two behaviours apart.
Add an 'allowed-by-guest' feature to the win-dmp member of
DumpGuestMemoryFormat so the fixed behaviour becomes discoverable.
DumpGuestMemoryFormat is reachable from both
query-dump-guest-memory-capability's return type and
dump-guest-memory's arguments, so a single flag covers both halves of
the change. Where the feature is absent, a reported win-dmp says
nothing about the guest, and a client that needs the dump to be
loadable afterwards should fall back to elf.
CC: Eric Blake <eblake@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: "Marc-André Lureau" <marcandre.lureau@redhat.com>
Suggested-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260731155001.1204103-1-den@openvz.org>
---
qapi/dump.json | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/qapi/dump.json b/qapi/dump.json
index 726b5208703c..690f3963fe15 100644
--- a/qapi/dump.json
+++ b/qapi/dump.json
@@ -38,6 +38,13 @@
# @win-dmp: Windows full crashdump format, can be used instead of ELF
# converting (since 2.13)
#
+# Features:
+#
+# @allowed-by-guest: If present, @win-dmp is listed by
+# `query-dump-guest-memory-capability`, and accepted by
+# `dump-guest-memory`, only when the guest has published a Windows
+# dump header through the vmcoreinfo device (since 11.1)
+#
# Since: 2.0
##
{ 'enum': 'DumpGuestMemoryFormat',
@@ -45,7 +52,7 @@
'elf',
'kdump-zlib', 'kdump-lzo', 'kdump-snappy',
'kdump-raw-zlib', 'kdump-raw-lzo', 'kdump-raw-snappy',
- 'win-dmp' ] }
+ { 'name': 'win-dmp', 'features': ['allowed-by-guest'] } ] }
##
# @dump-guest-memory:
--
2.55.0
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [GIT PULL 0/9] Fixes for 11.1-rc
2026-08-04 7:18 [GIT PULL 0/9] Fixes for 11.1-rc Marc-André Lureau
` (8 preceding siblings ...)
2026-08-04 7:18 ` [GIT PULL 9/9] qapi/dump: add allowed-by-guest feature to win-dmp Marc-André Lureau
@ 2026-08-04 19:07 ` Marc-André Lureau
2026-08-04 19:21 ` [GIT PULL v2 " Marc-André Lureau
10 siblings, 0 replies; 22+ messages in thread
From: Marc-André Lureau @ 2026-08-04 19:07 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanha
Hi Stefan
On Tue, Aug 4, 2026 at 11:20 AM Marc-André Lureau
<marcandre.lureau@redhat.com> wrote:
>
> The following changes since commit b428fe036233cbd15d37e3c027ab6ca4d3661a80:
>
> Merge tag 'pull-target-arm-20260731' of https://gitlab.com/pm215/qemu into staging (2026-07-31 16:19:04 -0400)
>
> are available in the Git repository at:
>
> https://gitlab.com/marcandre.lureau/qemu.git tags/fix-pr-v1
>
> for you to fetch changes up to 8876b366d7cac1f65978b8f8472725b980a1abfb:
>
> qapi/dump: add allowed-by-guest feature to win-dmp (2026-08-04 11:18:43 +0400)
I see it's already in staging, can you drop it? I need to double check
the CVE#...
>
> ----------------------------------------------------------------
> Fixes for 11.1-rc
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> ----------------------------------------------------------------
> Akihiko Odaki (1):
> hw/display/virtio-gpu: Always reject invalid scanout bounds
>
> Ankur Saini (1):
> virtio-gpu: reject requests with short/truncated control headers
>
> Bin Guo (1):
> hw/display/virtio-gpu: Unmap DMA regions on reset
>
> Denis V. Lunev (1):
> qapi/dump: add allowed-by-guest feature to win-dmp
>
> Marc-André Lureau (5):
> hw/display/virtio-gpu: validate blob iov size
> hw/display/vga: fix panning_buf OOB after text/graphics switch
> vhost-user-gpu: fix integer overflow in buffer allocation
> hw/display/virtio-gpu: fix offset wraparound in scanout_blob_to_fb
> hw/display/virtio-gpu: drop redundant node->value NULL checks
>
> qapi/dump.json | 9 +++-
> contrib/vhost-user-gpu/vugpu.h | 1 +
> include/hw/virtio/virtio-gpu.h | 8 ++++
> contrib/vhost-user-gpu/vhost-user-gpu.c | 29 +++++++-----
> contrib/vhost-user-gpu/vugbm.c | 11 ++++-
> hw/display/vga.c | 7 +--
> hw/display/virtio-gpu-base.c | 4 +-
> hw/display/virtio-gpu-rutabaga.c | 6 +++
> hw/display/virtio-gpu-virgl.c | 20 ++++-----
> hw/display/virtio-gpu.c | 80 ++++++++++++++++++++++++---------
> 10 files changed, 126 insertions(+), 49 deletions(-)
>
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* [GIT PULL v2 0/9] Fixes for 11.1-rc
2026-08-04 7:18 [GIT PULL 0/9] Fixes for 11.1-rc Marc-André Lureau
` (9 preceding siblings ...)
2026-08-04 19:07 ` [GIT PULL 0/9] Fixes for 11.1-rc Marc-André Lureau
@ 2026-08-04 19:21 ` Marc-André Lureau
2026-08-04 19:21 ` [GIT PULL v2 1/9] hw/display/virtio-gpu: validate blob iov size Marc-André Lureau
` (9 more replies)
10 siblings, 10 replies; 22+ messages in thread
From: Marc-André Lureau @ 2026-08-04 19:21 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanha
The following changes since commit b428fe036233cbd15d37e3c027ab6ca4d3661a80:
Merge tag 'pull-target-arm-20260731' of https://gitlab.com/pm215/qemu into staging (2026-07-31 16:19:04 -0400)
are available in the Git repository at:
https://gitlab.com/marcandre.lureau/qemu.git tags/fix-pr-v2
for you to fetch changes up to dd272c8c87f165d41c945946242c5c8619e7122f:
qapi/dump: add allowed-by-guest feature to win-dmp (2026-08-04 23:21:40 +0400)
----------------------------------------------------------------
Fixes for 11.1-rc
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
v2:
- fix CVE# in "virtio-gpu: reject requests with short/truncated control
headers"
----------------------------------------------------------------
Akihiko Odaki (1):
hw/display/virtio-gpu: Always reject invalid scanout bounds
Ankur Saini (1):
virtio-gpu: reject requests with short/truncated control headers
Bin Guo (1):
hw/display/virtio-gpu: Unmap DMA regions on reset
Denis V. Lunev (1):
qapi/dump: add allowed-by-guest feature to win-dmp
Marc-André Lureau (5):
hw/display/virtio-gpu: validate blob iov size
hw/display/vga: fix panning_buf OOB after text/graphics switch
vhost-user-gpu: fix integer overflow in buffer allocation
hw/display/virtio-gpu: fix offset wraparound in scanout_blob_to_fb
hw/display/virtio-gpu: drop redundant node->value NULL checks
qapi/dump.json | 9 +++-
contrib/vhost-user-gpu/vugpu.h | 1 +
include/hw/virtio/virtio-gpu.h | 8 ++++
contrib/vhost-user-gpu/vhost-user-gpu.c | 29 +++++++-----
contrib/vhost-user-gpu/vugbm.c | 11 ++++-
hw/display/vga.c | 7 +--
hw/display/virtio-gpu-base.c | 4 +-
hw/display/virtio-gpu-rutabaga.c | 6 +++
hw/display/virtio-gpu-virgl.c | 20 ++++-----
hw/display/virtio-gpu.c | 80 ++++++++++++++++++++++++---------
10 files changed, 126 insertions(+), 49 deletions(-)
^ permalink raw reply [flat|nested] 22+ messages in thread
* [GIT PULL v2 1/9] hw/display/virtio-gpu: validate blob iov size
2026-08-04 19:21 ` [GIT PULL v2 " Marc-André Lureau
@ 2026-08-04 19:21 ` Marc-André Lureau
2026-08-04 19:21 ` [GIT PULL v2 2/9] hw/display/vga: fix panning_buf OOB after text/graphics switch Marc-André Lureau
` (8 subsequent siblings)
9 siblings, 0 replies; 22+ messages in thread
From: Marc-André Lureau @ 2026-08-04 19:21 UTC (permalink / raw)
To: qemu-devel
Cc: stefanha, Alex Bennée, Akihiko Odaki, Dmitry Osipenko,
Michael S. Tsirkin
virtio_gpu_resource_create_blob() stores the guest-controlled blob_size
without checking it against the total size of the iov backing entries.
Since both values are independently guest-controlled, a malicious guest
can set blob_size much larger than the actual iov backing. Subsequent
SET_SCANOUT_BLOB checks bounds against the inflated blob_size, allowing
a pixman surface to be created over the undersized buffer. Any display
refresh then reads past the actual allocation, potentially crashing
QEMU or leaking host memory contents depending on the backing type.
Validate that the iov backing is at least as large as the declared
blob_size in create_blob (when nr_entries > 0, since the spec permits
deferred backing), attach_backing (when attaching to a blob resource),
and the blob migration load path.
Fixes: CVE-2026-66021
Fixes: e0933d91b1cd ("virtio-gpu: Add virtio_gpu_resource_create_blob")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3945
Reported-by: "sundayjiang(蒋浩天)" <sundayjiang@tencent.com>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260729161431.1180691-1-marcandre.lureau@redhat.com>
---
hw/display/virtio-gpu.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 4d46a4eb10fa..0206910cc377 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -372,6 +372,17 @@ static void virtio_gpu_resource_create_blob(VirtIOGPU *g,
return;
}
+ 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);
}
@@ -993,6 +1004,15 @@ virtio_gpu_resource_attach_backing(VirtIOGPU *g,
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);
+ return;
+ }
+
if (!res->image) {
virtio_gpu_init_udmabuf(res);
}
@@ -1493,6 +1513,14 @@ static int virtio_gpu_blob_load(QEMUFile *f, void *opaque, size_t size,
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;
--
2.55.0
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [GIT PULL v2 2/9] hw/display/vga: fix panning_buf OOB after text/graphics switch
2026-08-04 19:21 ` [GIT PULL v2 " Marc-André Lureau
2026-08-04 19:21 ` [GIT PULL v2 1/9] hw/display/virtio-gpu: validate blob iov size Marc-André Lureau
@ 2026-08-04 19:21 ` Marc-André Lureau
2026-08-04 19:21 ` [GIT PULL v2 3/9] vhost-user-gpu: fix integer overflow in buffer allocation Marc-André Lureau
` (7 subsequent siblings)
9 siblings, 0 replies; 22+ messages in thread
From: Marc-André Lureau @ 2026-08-04 19:21 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanha, Gerd Hoffmann
The fields last_width and last_height serve two purposes: the text
renderer counts in characters, the graphics renderer in pixels.
panning_buf reallocation is guarded by geometry-change check, so the
unit mismatch can trick it into thinking nothing changed when the
resolution actually grew.
A guest can trigger this by switching graphics -> text -> graphics:
1. Enter graphics mode with a small width (CR01=0x00, 8 pixels).
The predicate fires and panning_buf is allocated for that width.
2. Switch to text mode with a large width (CR01=0xFF, 256 chars).
The text renderer stores 256 into last_width. The text path
never touches panning_buf.
3. Switch back to graphics with a width that happens to equal 256
in pixels (CR01=0x1F, 32*8 = 256). The predicate sees
256 == 256 and skips the realloc. With horizontal pel panning
enabled, vga_draw_line4() then writes a full 256-pixel scanline
into the buffer still sized for 8 pixels -- a 960-byte heap
overflow on every scanline, every refresh.
Fix it by reallocating unconditionally panning_buf on
vga_draw_graphic().
Fixes: CVE-2026-17516
Fixes: 973a724eb006 ("vga: implement horizontal pel panning in graphics modes")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4085
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Warisjeet Singh <sinxx198@gmail.com>
[ Marc- André - drop realloc() resize condition & commit message ]
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260728151456.3704099-1-marcandre.lureau@redhat.com>
---
hw/display/vga.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/hw/display/vga.c b/hw/display/vga.c
index abe3f8e07758..da0c331486eb 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -1647,11 +1647,12 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
s->last_line_offset = s->params.line_offset;
s->last_depth = depth;
s->last_byteswap = byteswap;
- /* 16 extra pixels are needed for double-width planar modes. */
- s->panning_buf = g_realloc(s->panning_buf,
- (disp_width + 16) * sizeof(uint32_t));
full_update = 1;
}
+
+ /* 16 extra pixels are needed for double-width planar modes. */
+ s->panning_buf = g_realloc(s->panning_buf,
+ (disp_width + 16) * sizeof(uint32_t));
if (surface_data(surface) != s->vram_ptr + (s->params.start_addr * 4)
&& !surface_is_allocated(surface)) {
/* base address changed (page flip) -> shared display surfaces
--
2.55.0
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [GIT PULL v2 3/9] vhost-user-gpu: fix integer overflow in buffer allocation
2026-08-04 19:21 ` [GIT PULL v2 " Marc-André Lureau
2026-08-04 19:21 ` [GIT PULL v2 1/9] hw/display/virtio-gpu: validate blob iov size Marc-André Lureau
2026-08-04 19:21 ` [GIT PULL v2 2/9] hw/display/vga: fix panning_buf OOB after text/graphics switch Marc-André Lureau
@ 2026-08-04 19:21 ` Marc-André Lureau
2026-08-04 19:21 ` [GIT PULL v2 4/9] hw/display/virtio-gpu: fix offset wraparound in scanout_blob_to_fb Marc-André Lureau
` (6 subsequent siblings)
9 siblings, 0 replies; 22+ messages in thread
From: Marc-André Lureau @ 2026-08-04 19:21 UTC (permalink / raw)
To: qemu-devel
Cc: stefanha, Michael S. Tsirkin, Stefano Garzarella,
Marc-André Lureau
A malicious guest can trigger a heap buffer overflow in the
vhost-user-gpu backend by sending a VIRTIO_GPU_CMD_RESOURCE_CREATE_2D
with large width and height values (e.g. 65537x65537). The allocation
size width * height * 4 silently wraps in uint32_t arithmetic,
resulting in a much smaller allocation than expected. Subsequent
VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D writes past the heap buffer.
The in-tree virtio-gpu device (hw/display/virtio-gpu.c) already handles
this via calc_image_hostmem() with uint64_t arithmetic and an overflow
check. Apply the same approach to the vhost-user-gpu contrib backend:
- Add an overflow check in vugbm_buffer_create() rejecting dimensions
where width * height * 4 exceeds UINT32_MAX
- Promote the size arithmetic to uint64_t in mem_alloc_bo() and
udmabuf_get_size()
- Check the return value of vugbm_buffer_create() in
vg_resource_create_2d(), which was previously ignored
Fixes: CVE-2026-15264
Reported-by: "Vulnerability Report" <vr@darknavy.com>
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3940
Signed-off-by: Marc-Andre Lureau <marcandre.lureau@redhat.com>
Acked-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Message-ID: <20260710134720.2317856-1-marcandre.lureau@redhat.com>
---
contrib/vhost-user-gpu/vhost-user-gpu.c | 8 +++++++-
contrib/vhost-user-gpu/vugbm.c | 11 +++++++++--
2 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/contrib/vhost-user-gpu/vhost-user-gpu.c b/contrib/vhost-user-gpu/vhost-user-gpu.c
index bb41758e3454..ee9858c397ce 100644
--- a/contrib/vhost-user-gpu/vhost-user-gpu.c
+++ b/contrib/vhost-user-gpu/vhost-user-gpu.c
@@ -388,7 +388,13 @@ vg_resource_create_2d(VuGpu *g,
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
return;
}
- vugbm_buffer_create(&res->buffer, &g->gdev, c2d.width, c2d.height);
+ if (!vugbm_buffer_create(&res->buffer, &g->gdev, c2d.width, c2d.height)) {
+ g_critical("%s: buffer creation failed %d %d %d",
+ __func__, c2d.resource_id, c2d.width, c2d.height);
+ g_free(res);
+ cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
+ return;
+ }
res->image = pixman_image_create_bits(pformat,
c2d.width,
c2d.height,
diff --git a/contrib/vhost-user-gpu/vugbm.c b/contrib/vhost-user-gpu/vugbm.c
index 503d0a4566f8..710d54529779 100644
--- a/contrib/vhost-user-gpu/vugbm.c
+++ b/contrib/vhost-user-gpu/vugbm.c
@@ -13,7 +13,7 @@
static bool
mem_alloc_bo(struct vugbm_buffer *buf)
{
- buf->mmap = g_malloc(buf->width * buf->height * 4);
+ buf->mmap = g_malloc((uint64_t)buf->width * buf->height * 4);
buf->stride = buf->width * 4;
return true;
}
@@ -53,7 +53,8 @@ struct udmabuf_create {
static size_t
udmabuf_get_size(struct vugbm_buffer *buf)
{
- return ROUND_UP(buf->width * buf->height * 4, qemu_real_host_page_size());
+ return ROUND_UP((uint64_t)buf->width * buf->height * 4,
+ qemu_real_host_page_size());
}
static bool
@@ -293,6 +294,12 @@ bool
vugbm_buffer_create(struct vugbm_buffer *buffer, struct vugbm_device *dev,
uint32_t width, uint32_t height)
{
+ uint64_t size = (uint64_t)width * height * 4;
+ if (size > UINT32_MAX) {
+ g_warning("buffer dimensions too large: %ux%u", width, height);
+ return false;
+ }
+
buffer->dev = dev;
buffer->width = width;
buffer->height = height;
--
2.55.0
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [GIT PULL v2 4/9] hw/display/virtio-gpu: fix offset wraparound in scanout_blob_to_fb
2026-08-04 19:21 ` [GIT PULL v2 " Marc-André Lureau
` (2 preceding siblings ...)
2026-08-04 19:21 ` [GIT PULL v2 3/9] vhost-user-gpu: fix integer overflow in buffer allocation Marc-André Lureau
@ 2026-08-04 19:21 ` Marc-André Lureau
2026-08-04 19:21 ` [GIT PULL v2 5/9] hw/display/virtio-gpu: drop redundant node->value NULL checks Marc-André Lureau
` (5 subsequent siblings)
9 siblings, 0 replies; 22+ messages in thread
From: Marc-André Lureau @ 2026-08-04 19:21 UTC (permalink / raw)
To: qemu-devel
Cc: stefanha, Michael S. Tsirkin, Alex Bennée, Akihiko Odaki,
Dmitry Osipenko
virtio_gpu_scanout_blob_to_fb() computes the framebuffer offset from
guest-controlled offsets[0], r.x, r.y and stride using uint32_t
arithmetic. When the sum exceeds UINT32_MAX, silent wraparound lets
the guest steer the scanout to an arbitrary in-bounds region of the
blob instead of the intended rectangle.
Compute the offset in uint64_t, reject values exceeding UINT32_MAX
(the width of fb->offset), and only store into fb->offset once both
range checks pass.
("[PATCH] hw/display/virtio-gpu: Remove the bytes_pp field")
Fixes: 32db3c63ae11 ("virtio-gpu: Add virtio_gpu_set_scanout_blob")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3871
Based-on: <20260719-bpp-v1-1-9b91946d6cf3@rsg.ci.i.u-tokyo.ac.jp>
Reported-by: Cyber_black <Cyberblackk@proton.me>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260725122734.1775774-1-marcandre.lureau@redhat.com>
---
hw/display/virtio-gpu.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 0206910cc377..51592b49c21e 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -777,7 +777,7 @@ bool virtio_gpu_scanout_blob_to_fb(struct virtio_gpu_framebuffer *fb,
struct virtio_gpu_set_scanout_blob *ss,
uint64_t blob_size)
{
- uint64_t fbend;
+ uint64_t fbend, offset;
uint32_t bytes_pp;
fb->format = virtio_gpu_get_pixman_format(ss->format);
@@ -807,18 +807,20 @@ bool virtio_gpu_scanout_blob_to_fb(struct virtio_gpu_framebuffer *fb,
return false;
}
- fb->offset = ss->offsets[0] + ss->r.x * bytes_pp + ss->r.y * fb->stride;
+ offset = (uint64_t)ss->offsets[0] + (uint64_t)ss->r.x * bytes_pp +
+ (uint64_t)ss->r.y * fb->stride;
- fbend = fb->offset;
- fbend += (uint64_t) fb->stride * ss->r.height;
+ fbend = offset + (uint64_t)fb->stride * ss->r.height;
- if (fbend > blob_size) {
+ if (offset > UINT32_MAX || fbend > blob_size) {
qemu_log_mask(LOG_GUEST_ERROR,
- "%s: fb end out of range\n",
+ "%s: invalid fb bounds\n",
__func__);
return false;
}
+ fb->offset = offset;
+
return true;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [GIT PULL v2 5/9] hw/display/virtio-gpu: drop redundant node->value NULL checks
2026-08-04 19:21 ` [GIT PULL v2 " Marc-André Lureau
` (3 preceding siblings ...)
2026-08-04 19:21 ` [GIT PULL v2 4/9] hw/display/virtio-gpu: fix offset wraparound in scanout_blob_to_fb Marc-André Lureau
@ 2026-08-04 19:21 ` Marc-André Lureau
2026-08-04 19:21 ` [GIT PULL v2 6/9] virtio-gpu: reject requests with short/truncated control headers Marc-André Lureau
` (4 subsequent siblings)
9 siblings, 0 replies; 22+ messages in thread
From: Marc-André Lureau @ 2026-08-04 19:21 UTC (permalink / raw)
To: qemu-devel
Cc: stefanha, Alex Bennée, Akihiko Odaki, Dmitry Osipenko,
Michael S. Tsirkin
QAPI-generated list visitors guarantee that node->value is never NULL:
the input visitor allocates it via g_malloc0() in visit_start_struct(),
and on failure the entire list parse is aborted and freed.
Remove the unnecessary NULL checks from both callsites iterating
g->conf.outputs.
Resolves: Coverity CID 1664272
Fixes: 8dc8449a678f ("hw/display/virtio-gpu: Avoid leaking migration blocker")
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260730114751.3515083-1-marcandre.lureau@redhat.com>
---
hw/display/virtio-gpu-base.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c
index 946e56b42f61..270fbaae1029 100644
--- a/hw/display/virtio-gpu-base.c
+++ b/hw/display/virtio-gpu-base.c
@@ -69,7 +69,7 @@ virtio_gpu_base_generate_edid(VirtIOGPUBase *g, int scanout,
for (output_idx = 0, node = g->conf.outputs;
output_idx <= scanout && node; output_idx++, node = node->next) {
- if (output_idx == scanout && node->value && node->value->name) {
+ if (output_idx == scanout && node->value->name) {
info.name = node->value->name;
break;
}
@@ -206,7 +206,7 @@ virtio_gpu_base_device_realize(DeviceState *qdev,
error_setg(errp, "invalid outputs > %d", g->conf.max_outputs);
return false;
}
- if (node->value && node->value->name &&
+ if (node->value->name &&
strlen(node->value->name) > EDID_NAME_MAX_LENGTH) {
error_setg(errp, "invalid output name '%s' > %d",
node->value->name, EDID_NAME_MAX_LENGTH);
--
2.55.0
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [GIT PULL v2 6/9] virtio-gpu: reject requests with short/truncated control headers
2026-08-04 19:21 ` [GIT PULL v2 " Marc-André Lureau
` (4 preceding siblings ...)
2026-08-04 19:21 ` [GIT PULL v2 5/9] hw/display/virtio-gpu: drop redundant node->value NULL checks Marc-André Lureau
@ 2026-08-04 19:21 ` Marc-André Lureau
2026-08-04 19:21 ` [GIT PULL v2 7/9] hw/display/virtio-gpu: Always reject invalid scanout bounds Marc-André Lureau
` (3 subsequent siblings)
9 siblings, 0 replies; 22+ messages in thread
From: Marc-André Lureau @ 2026-08-04 19:21 UTC (permalink / raw)
To: qemu-devel
Cc: stefanha, Michael S. Tsirkin, Stefano Garzarella,
Marc-André Lureau, Alex Bennée, Akihiko Odaki,
Dmitry Osipenko
From: Ankur Saini <ankur98saini@gmail.com>
A short control request can leave command data partially initialized.
For the common header, guest-controlled flags can then cause stale fence
metadata to be returned to the guest.
The command fill helpers detect a short copy but only log and return.
For the common header this leaves the request without any completion;
for type-specific commands the caller still completes the request but
reports VIRTIO_GPU_RESP_OK_NODATA, masking the error. Make
VIRTIO_GPU_FILL_CMD() clear the partially copied object and complete the
request with ERR_INVALID_PARAMETER. Make VUGPU_FILL_CMD() report the same
error through the existing vhost-user-gpu dispatcher. This also rejects
truncated type-specific commands.
The vhost-user-gpu common header is copied outside VUGPU_FILL_CMD(), so
clear it and complete the request directly when that copy is short.
Fixes: CVE-2026-18054
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4094
Reported-by: Ankur Saini <ankur98saini@gmail.com>
Suggested-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Ankur Saini <ankur98saini@gmail.com>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260803-virtio-gpu-short-header-v3-1-936c1daa8e61@gmail.com>
---
contrib/vhost-user-gpu/vugpu.h | 1 +
include/hw/virtio/virtio-gpu.h | 3 +++
contrib/vhost-user-gpu/vhost-user-gpu.c | 21 ++++++++++++---------
3 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/contrib/vhost-user-gpu/vugpu.h b/contrib/vhost-user-gpu/vugpu.h
index 2374eb90cb9b..aaf2870cb24d 100644
--- a/contrib/vhost-user-gpu/vugpu.h
+++ b/contrib/vhost-user-gpu/vugpu.h
@@ -179,6 +179,7 @@ struct virtio_gpu_ctrl_command {
if (vugpufillcmd_s_ != sizeof(out)) { \
g_critical("%s: command size incorrect %zu vs %zu", \
__func__, vugpufillcmd_s_, sizeof(out)); \
+ cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; \
return; \
} \
} while (0)
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 2f60c72078b3..f965defa6b25 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -315,6 +315,9 @@ struct VirtIOGPURutabaga {
qemu_log_mask(LOG_GUEST_ERROR, \
"%s: command size incorrect %zu vs %zu\n", \
__func__, virtiogpufillcmd_s_, sizeof(out)); \
+ memset(&out, 0, sizeof(out)); \
+ virtio_gpu_ctrl_response_nodata( \
+ g, cmd, VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER); \
return; \
} \
} while (0)
diff --git a/contrib/vhost-user-gpu/vhost-user-gpu.c b/contrib/vhost-user-gpu/vhost-user-gpu.c
index ee9858c397ce..786488150932 100644
--- a/contrib/vhost-user-gpu/vhost-user-gpu.c
+++ b/contrib/vhost-user-gpu/vhost-user-gpu.c
@@ -930,16 +930,19 @@ vg_handle_ctrl(VuDev *dev, int qidx)
if (len != sizeof(cmd->cmd_hdr)) {
g_warning("%s: command size incorrect %zu vs %zu\n",
__func__, len, sizeof(cmd->cmd_hdr));
- }
-
- virtio_gpu_ctrl_hdr_bswap(&cmd->cmd_hdr);
- g_debug("%d %s\n", cmd->cmd_hdr.type,
- vg_cmd_to_string(cmd->cmd_hdr.type));
-
- if (vg->virgl) {
- vg_virgl_process_cmd(vg, cmd);
+ memset(&cmd->cmd_hdr, 0, sizeof(cmd->cmd_hdr));
+ vg_ctrl_response_nodata(
+ vg, cmd, VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER);
} else {
- vg_process_cmd(vg, cmd);
+ virtio_gpu_ctrl_hdr_bswap(&cmd->cmd_hdr);
+ g_debug("%d %s\n", cmd->cmd_hdr.type,
+ vg_cmd_to_string(cmd->cmd_hdr.type));
+
+ if (vg->virgl) {
+ vg_virgl_process_cmd(vg, cmd);
+ } else {
+ vg_process_cmd(vg, cmd);
+ }
}
if (cmd->state != VG_CMD_STATE_FINISHED) {
--
2.55.0
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [GIT PULL v2 7/9] hw/display/virtio-gpu: Always reject invalid scanout bounds
2026-08-04 19:21 ` [GIT PULL v2 " Marc-André Lureau
` (5 preceding siblings ...)
2026-08-04 19:21 ` [GIT PULL v2 6/9] virtio-gpu: reject requests with short/truncated control headers Marc-André Lureau
@ 2026-08-04 19:21 ` Marc-André Lureau
2026-08-04 19:21 ` [GIT PULL v2 8/9] hw/display/virtio-gpu: Unmap DMA regions on reset Marc-André Lureau
` (2 subsequent siblings)
9 siblings, 0 replies; 22+ messages in thread
From: Marc-André Lureau @ 2026-08-04 19:21 UTC (permalink / raw)
To: qemu-devel
Cc: stefanha, Alex Bennée, Akihiko Odaki, Dmitry Osipenko,
Michael S. Tsirkin
From: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
virtio-gpu does not consistently check scanout bounds with wraparound
handling. In the unchecked virgl SET_SCANOUT path, guest dimensions
reach qemu_console_resize(), qemu_create_displaysurface(), and
ultimately qemu_pixman_image_new_shareable(..., &error_abort), so an
invalid rectangle can terminate QEMU. Implement a check with proper
wraparound handling and apply it consistently.
Fixes: 9d9e152136bd ("virtio-gpu: add 3d mode and virgl rendering support.")
Fixes: 32db3c63ae11 ("virtio-gpu: Add virtio_gpu_set_scanout_blob")
Fixes: 7c092f17ccee ("virtio-gpu: Handle resource blob commands")
Fixes: 1dcc6adbc168 ("gfxstream + rutabaga: add initial support for gfxstream")
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260803-scanout-v1-1-c9831dafdab2@rsg.ci.i.u-tokyo.ac.jp>
---
include/hw/virtio/virtio-gpu.h | 5 +++++
hw/display/virtio-gpu-rutabaga.c | 6 ++++++
hw/display/virtio-gpu-virgl.c | 20 +++++++++-----------
hw/display/virtio-gpu.c | 36 ++++++++++++++++++++++--------------
4 files changed, 42 insertions(+), 25 deletions(-)
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index f965defa6b25..220231ec9d43 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -366,6 +366,11 @@ 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,
+ const struct virtio_gpu_rect *r,
+ uint32_t *error);
+
/**
* virtio_gpu_scanout_blob_to_fb() - fill out fb based on scanout data
* fb: the frame-buffer descriptor to fill out
diff --git a/hw/display/virtio-gpu-rutabaga.c b/hw/display/virtio-gpu-rutabaga.c
index e28aad94eead..a054f8117f14 100644
--- a/hw/display/virtio-gpu-rutabaga.c
+++ b/hw/display/virtio-gpu-rutabaga.c
@@ -315,6 +315,12 @@ rutabaga_cmd_set_scanout(VirtIOGPU *g, struct virtio_gpu_ctrl_command *cmd)
res = virtio_gpu_find_resource(g, ss.resource_id);
CHECK(res, cmd);
+ if (!virtio_gpu_check_scanout_bounds(ss.scanout_id, ss.resource_id,
+ res->width, res->height, &ss.r,
+ &cmd->error)) {
+ return;
+ }
+
if (!res->image) {
pixman_format_code_t pformat;
pformat = virtio_gpu_get_pixman_format(res->format);
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index d9e5b0110497..6e298f997d66 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -560,7 +560,7 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g,
}
g->parent_obj.enable = 1;
- if (ss.resource_id && ss.r.width && ss.r.height) {
+ if (ss.resource_id) {
struct virgl_renderer_resource_info info;
void *d3d_tex2d = NULL;
@@ -581,6 +581,11 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g,
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
return;
}
+ if (!virtio_gpu_check_scanout_bounds(ss.scanout_id, ss.resource_id,
+ info.width, info.height, &ss.r,
+ &cmd->error)) {
+ return;
+ }
qemu_console_resize(g->parent_obj.scanout[ss.scanout_id].con,
ss.r.width, ss.r.height);
virgl_renderer_force_ctx_0();
@@ -987,16 +992,9 @@ static void virgl_cmd_set_scanout_blob(VirtIOGPU *g,
return;
}
- if (ss.width < 16 ||
- ss.height < 16 ||
- ss.r.x + ss.r.width > ss.width ||
- ss.r.y + ss.r.height > ss.height) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout %d bounds for"
- " resource %d, rect (%d,%d)+%d,%d, fb %d %d\n",
- __func__, ss.scanout_id, ss.resource_id,
- ss.r.x, ss.r.y, ss.r.width, ss.r.height,
- ss.width, ss.height);
- cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+ if (!virtio_gpu_check_scanout_bounds(ss.scanout_id, ss.resource_id,
+ ss.width, ss.height, &ss.r,
+ &cmd->error)) {
return;
}
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 51592b49c21e..c15d4b527d0e 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -633,6 +633,26 @@ static uint32_t virtio_gpu_format_bytes_pp(pixman_format_code_t format)
return DIV_ROUND_UP(PIXMAN_FORMAT_BPP(format), 8);
}
+bool virtio_gpu_check_scanout_bounds(uint32_t scanout_id, uint32_t resource_id,
+ uint32_t width, uint32_t height,
+ const struct virtio_gpu_rect *r,
+ uint32_t *error)
+{
+ if (r->width < 16 ||
+ r->height < 16 ||
+ (uint64_t)r->x + r->width > width ||
+ (uint64_t)r->y + r->height > height) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout %d bounds for"
+ " resource %d, fb %d %d, rect (%d,%d)+%d,%d\n",
+ __func__, scanout_id, resource_id, width, height,
+ r->x, r->y, r->width, r->height);
+ *error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+ return false;
+ }
+
+ return true;
+}
+
static bool virtio_gpu_do_set_scanout(VirtIOGPU *g,
uint32_t scanout_id,
struct virtio_gpu_framebuffer *fb,
@@ -646,20 +666,8 @@ static bool virtio_gpu_do_set_scanout(VirtIOGPU *g,
scanout = &g->parent_obj.scanout[scanout_id];
- if (r->x > fb->width ||
- r->y > fb->height ||
- r->width < 16 ||
- r->height < 16 ||
- r->width > fb->width ||
- r->height > fb->height ||
- r->x + r->width > fb->width ||
- r->y + r->height > fb->height) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout %d bounds for"
- " resource %d, rect (%d,%d)+%d,%d, fb %d %d\n",
- __func__, scanout_id, res->resource_id,
- r->x, r->y, r->width, r->height,
- fb->width, fb->height);
- *error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+ if (!virtio_gpu_check_scanout_bounds(scanout_id, res->resource_id,
+ fb->width, fb->height, r, error)) {
return false;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [GIT PULL v2 8/9] hw/display/virtio-gpu: Unmap DMA regions on reset
2026-08-04 19:21 ` [GIT PULL v2 " Marc-André Lureau
` (6 preceding siblings ...)
2026-08-04 19:21 ` [GIT PULL v2 7/9] hw/display/virtio-gpu: Always reject invalid scanout bounds Marc-André Lureau
@ 2026-08-04 19:21 ` Marc-André Lureau
2026-08-04 19:21 ` [GIT PULL v2 9/9] qapi/dump: add allowed-by-guest feature to win-dmp Marc-André Lureau
2026-08-05 0:55 ` [GIT PULL v2 0/9] Fixes for 11.1-rc Stefan Hajnoczi
9 siblings, 0 replies; 22+ messages in thread
From: Marc-André Lureau @ 2026-08-04 19:21 UTC (permalink / raw)
To: qemu-devel
Cc: stefanha, Alex Bennée, Akihiko Odaki, Dmitry Osipenko,
Michael S. Tsirkin
From: Bin Guo <guobin@linux.alibaba.com>
virtio_gpu_reset() freed in-flight commands without unmapping the
DMA regions acquired by virtqueue_pop(). Call virtqueue_detach_element()
before g_free() in both drain loops.
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3467
Cc: qemu-stable@nongnu.org
Signed-off-by: Bin Guo <guobin@linux.alibaba.com>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260803082158.62998-1-guobin@linux.alibaba.com>
---
hw/display/virtio-gpu.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index c15d4b527d0e..fbb6fec7a0ad 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1725,12 +1725,14 @@ void virtio_gpu_reset(VirtIODevice *vdev)
while (!QTAILQ_EMPTY(&g->cmdq)) {
cmd = QTAILQ_FIRST(&g->cmdq);
QTAILQ_REMOVE(&g->cmdq, cmd, next);
+ virtqueue_detach_element(cmd->vq, &cmd->elem, 0);
g_free(cmd);
}
while (!QTAILQ_EMPTY(&g->fenceq)) {
cmd = QTAILQ_FIRST(&g->fenceq);
QTAILQ_REMOVE(&g->fenceq, cmd, next);
+ virtqueue_detach_element(cmd->vq, &cmd->elem, 0);
g->inflight--;
g_free(cmd);
}
--
2.55.0
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [GIT PULL v2 9/9] qapi/dump: add allowed-by-guest feature to win-dmp
2026-08-04 19:21 ` [GIT PULL v2 " Marc-André Lureau
` (7 preceding siblings ...)
2026-08-04 19:21 ` [GIT PULL v2 8/9] hw/display/virtio-gpu: Unmap DMA regions on reset Marc-André Lureau
@ 2026-08-04 19:21 ` Marc-André Lureau
2026-08-05 0:55 ` [GIT PULL v2 0/9] Fixes for 11.1-rc Stefan Hajnoczi
9 siblings, 0 replies; 22+ messages in thread
From: Marc-André Lureau @ 2026-08-04 19:21 UTC (permalink / raw)
To: qemu-devel
Cc: stefanha, Marc-André Lureau, Ani Sinha, Eric Blake,
Markus Armbruster
From: "Denis V. Lunev" <den@openvz.org>
Commit 1c0e259c5a35 ("dump: make win_dump_available() check vmcoreinfo
for a Windows dump header") changed two things in a way that is visible
to QMP clients but not to introspection:
query-dump-guest-memory-capability now lists win-dmp only for a guest
that has published a Windows dump header through the vmcoreinfo device,
and dump-guest-memory, which shares win_dump_available(), rejects the
format otherwise. Before that, both accepted win-dmp on any x86
machine.
A client that wants to select win-dmp automatically therefore cannot
trust the capability query on its own: on an older QEMU it reports
win-dmp for every x86 guest, Linux ones included, where the resulting
dump is useless. libvirt ran into exactly this while picking a format
for on_crash and watchdog triggered dumps, and has no way to tell the
two behaviours apart.
Add an 'allowed-by-guest' feature to the win-dmp member of
DumpGuestMemoryFormat so the fixed behaviour becomes discoverable.
DumpGuestMemoryFormat is reachable from both
query-dump-guest-memory-capability's return type and
dump-guest-memory's arguments, so a single flag covers both halves of
the change. Where the feature is absent, a reported win-dmp says
nothing about the guest, and a client that needs the dump to be
loadable afterwards should fall back to elf.
CC: Eric Blake <eblake@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: "Marc-André Lureau" <marcandre.lureau@redhat.com>
Suggested-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260731155001.1204103-1-den@openvz.org>
---
qapi/dump.json | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/qapi/dump.json b/qapi/dump.json
index 726b5208703c..690f3963fe15 100644
--- a/qapi/dump.json
+++ b/qapi/dump.json
@@ -38,6 +38,13 @@
# @win-dmp: Windows full crashdump format, can be used instead of ELF
# converting (since 2.13)
#
+# Features:
+#
+# @allowed-by-guest: If present, @win-dmp is listed by
+# `query-dump-guest-memory-capability`, and accepted by
+# `dump-guest-memory`, only when the guest has published a Windows
+# dump header through the vmcoreinfo device (since 11.1)
+#
# Since: 2.0
##
{ 'enum': 'DumpGuestMemoryFormat',
@@ -45,7 +52,7 @@
'elf',
'kdump-zlib', 'kdump-lzo', 'kdump-snappy',
'kdump-raw-zlib', 'kdump-raw-lzo', 'kdump-raw-snappy',
- 'win-dmp' ] }
+ { 'name': 'win-dmp', 'features': ['allowed-by-guest'] } ] }
##
# @dump-guest-memory:
--
2.55.0
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [GIT PULL v2 0/9] Fixes for 11.1-rc
2026-08-04 19:21 ` [GIT PULL v2 " Marc-André Lureau
` (8 preceding siblings ...)
2026-08-04 19:21 ` [GIT PULL v2 9/9] qapi/dump: add allowed-by-guest feature to win-dmp Marc-André Lureau
@ 2026-08-05 0:55 ` Stefan Hajnoczi
9 siblings, 0 replies; 22+ messages in thread
From: Stefan Hajnoczi @ 2026-08-05 0:55 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel, stefanha
[-- Attachment #1: Type: text/plain, Size: 116 bytes --]
Applied, thanks.
Please update the changelog at https://wiki.qemu.org/ChangeLog/11.1 for any user-visible changes.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2026-08-05 0:56 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-04 7:18 [GIT PULL 0/9] Fixes for 11.1-rc Marc-André Lureau
2026-08-04 7:18 ` [GIT PULL 1/9] hw/display/virtio-gpu: validate blob iov size Marc-André Lureau
2026-08-04 7:18 ` [GIT PULL 2/9] hw/display/vga: fix panning_buf OOB after text/graphics switch Marc-André Lureau
2026-08-04 7:18 ` [GIT PULL 3/9] vhost-user-gpu: fix integer overflow in buffer allocation Marc-André Lureau
2026-08-04 7:18 ` [GIT PULL 4/9] hw/display/virtio-gpu: fix offset wraparound in scanout_blob_to_fb Marc-André Lureau
2026-08-04 7:18 ` [GIT PULL 5/9] hw/display/virtio-gpu: drop redundant node->value NULL checks Marc-André Lureau
2026-08-04 7:18 ` [GIT PULL 6/9] virtio-gpu: reject requests with short/truncated control headers Marc-André Lureau
2026-08-04 7:18 ` [GIT PULL 7/9] hw/display/virtio-gpu: Always reject invalid scanout bounds Marc-André Lureau
2026-08-04 7:18 ` [GIT PULL 8/9] hw/display/virtio-gpu: Unmap DMA regions on reset Marc-André Lureau
2026-08-04 7:18 ` [GIT PULL 9/9] qapi/dump: add allowed-by-guest feature to win-dmp Marc-André Lureau
2026-08-04 19:07 ` [GIT PULL 0/9] Fixes for 11.1-rc Marc-André Lureau
2026-08-04 19:21 ` [GIT PULL v2 " Marc-André Lureau
2026-08-04 19:21 ` [GIT PULL v2 1/9] hw/display/virtio-gpu: validate blob iov size Marc-André Lureau
2026-08-04 19:21 ` [GIT PULL v2 2/9] hw/display/vga: fix panning_buf OOB after text/graphics switch Marc-André Lureau
2026-08-04 19:21 ` [GIT PULL v2 3/9] vhost-user-gpu: fix integer overflow in buffer allocation Marc-André Lureau
2026-08-04 19:21 ` [GIT PULL v2 4/9] hw/display/virtio-gpu: fix offset wraparound in scanout_blob_to_fb Marc-André Lureau
2026-08-04 19:21 ` [GIT PULL v2 5/9] hw/display/virtio-gpu: drop redundant node->value NULL checks Marc-André Lureau
2026-08-04 19:21 ` [GIT PULL v2 6/9] virtio-gpu: reject requests with short/truncated control headers Marc-André Lureau
2026-08-04 19:21 ` [GIT PULL v2 7/9] hw/display/virtio-gpu: Always reject invalid scanout bounds Marc-André Lureau
2026-08-04 19:21 ` [GIT PULL v2 8/9] hw/display/virtio-gpu: Unmap DMA regions on reset Marc-André Lureau
2026-08-04 19:21 ` [GIT PULL v2 9/9] qapi/dump: add allowed-by-guest feature to win-dmp Marc-André Lureau
2026-08-05 0:55 ` [GIT PULL v2 0/9] Fixes for 11.1-rc Stefan Hajnoczi
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.