* [GIT PULL 01/15] i386/tdx: fix uninitialized variable warning in tdx_check_features
2026-07-17 11:52 [GIT PULL 00/15] Various UI/security-related fixes for 11.1 Marc-André Lureau
@ 2026-07-17 11:52 ` Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 02/15] ui/vnc: fix OOB write in vnc_refresh_lossy_rect Marc-André Lureau
` (17 subsequent siblings)
18 siblings, 0 replies; 26+ messages in thread
From: Marc-André Lureau @ 2026-07-17 11:52 UTC (permalink / raw)
To: qemu-devel
tdx_fetch_cpuid() only sets the output ret parameter on the error
path. GCC cannot prove that r is always initialized before use in
the caller, triggering -Werror=maybe-uninitialized.
Initialize r to -1 to silence the warning.
Fixes: 228e40f33048 ("i386/tdx: Fetch and validate CPUID of TD guest")
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-Andre Lureau <marcandre.lureau@redhat.com>
---
target/i386/kvm/tdx.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/target/i386/kvm/tdx.c b/target/i386/kvm/tdx.c
index c9c3b05d5fe..8294dbde3aa 100644
--- a/target/i386/kvm/tdx.c
+++ b/target/i386/kvm/tdx.c
@@ -887,7 +887,7 @@ static int tdx_check_features(X86ConfidentialGuest *cg, CPUState *cs)
FeatureWordInfo *wi;
FeatureWord w;
bool mismatch = false;
- int r;
+ int r = -1;
fetch_cpuid = tdx_fetch_cpuid(cs, &r);
if (!fetch_cpuid) {
--
2.55.0
^ permalink raw reply related [flat|nested] 26+ messages in thread* [GIT PULL 02/15] ui/vnc: fix OOB write in vnc_refresh_lossy_rect
2026-07-17 11:52 [GIT PULL 00/15] Various UI/security-related fixes for 11.1 Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 01/15] i386/tdx: fix uninitialized variable warning in tdx_check_features Marc-André Lureau
@ 2026-07-17 11:52 ` Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 03/15] ui/vnc: validate color shifts in SetPixelFormat Marc-André Lureau
` (16 subsequent siblings)
18 siblings, 0 replies; 26+ messages in thread
From: Marc-André Lureau @ 2026-07-17 11:52 UTC (permalink / raw)
To: qemu-devel
vnc_refresh_lossy_rect() always marks a full VNC_STAT_RECT (64) rows
as dirty when refreshing a lossy tile. When the display height is not
a multiple of VNC_STAT_RECT (e.g. VNC_MAX_HEIGHT = 2160), the bottom
tile is partial -- the last tile at y=2112 has only 48 valid rows.
The unclamped loop writes to vs->dirty[2160..2175], past the end of
the VNC_MAX_HEIGHT-sized array.
Clamp the row count to the actual surface height so partial bottom
tiles only mark valid dirty bitmap entries.
Fixes: CVE-2026-48002
Fixes: 7d964c9d2fc6 ("vnc: refresh lossy rect after a given timeout")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3950
Reported-by: huntr bubble
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-Andre Lureau <marcandre.lureau@redhat.com>
---
ui/vnc.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/ui/vnc.c b/ui/vnc.c
index b2b69923b75..559d3954b87 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -3004,10 +3004,18 @@ static int vnc_refresh_lossy_rect(VncDisplay *vd, int x, int y)
int sty = y / VNC_STAT_RECT;
int stx = x / VNC_STAT_RECT;
int has_dirty = 0;
+ int height = MIN(pixman_image_get_height(vd->guest.fb),
+ pixman_image_get_height(vd->server));
+ int rows;
y = QEMU_ALIGN_DOWN(y, VNC_STAT_RECT);
x = QEMU_ALIGN_DOWN(x, VNC_STAT_RECT);
+ rows = MIN(VNC_STAT_RECT, height - y);
+ if (rows <= 0) {
+ return 0;
+ }
+
QTAILQ_FOREACH(vs, &vd->clients, next) {
VncConnection *vc = container_of(vs, VncConnection, vs);
int j;
@@ -3022,7 +3030,7 @@ static int vnc_refresh_lossy_rect(VncDisplay *vd, int x, int y)
}
vc->worker.lossy_rect[sty][stx] = 0;
- for (j = 0; j < VNC_STAT_RECT; ++j) {
+ for (j = 0; j < rows; ++j) {
bitmap_set(vs->dirty[y + j],
x / VNC_DIRTY_PIXELS_PER_BIT,
VNC_STAT_RECT / VNC_DIRTY_PIXELS_PER_BIT);
--
2.55.0
^ permalink raw reply related [flat|nested] 26+ messages in thread* [GIT PULL 03/15] ui/vnc: validate color shifts in SetPixelFormat
2026-07-17 11:52 [GIT PULL 00/15] Various UI/security-related fixes for 11.1 Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 01/15] i386/tdx: fix uninitialized variable warning in tdx_check_features Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 02/15] ui/vnc: fix OOB write in vnc_refresh_lossy_rect Marc-André Lureau
@ 2026-07-17 11:52 ` Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 04/15] ui/vnc: use RFB wire types for client message handlers Marc-André Lureau
` (15 subsequent siblings)
18 siblings, 0 replies; 26+ messages in thread
From: Marc-André Lureau @ 2026-07-17 11:52 UTC (permalink / raw)
To: qemu-devel
A malicious VNC client can send a SetPixelFormat message with shift
values >= 32, causing UB mask computation
(e.g. red_max << red_shift where red_shift is 255). Apparently, this is
not covered by -fwrapv.
Reject color shifts >= bits_per_pixel || 32 before computing masks.
Fixes: 9f64916da20 ("pixman/vnc: use pixman images in vnc.")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3948
Reported-by: huntr bubble
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-Andre Lureau <marcandre.lureau@redhat.com>
---
ui/vnc.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/ui/vnc.c b/ui/vnc.c
index 559d3954b87..9219f593d95 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2276,6 +2276,13 @@ static void set_pixel_format(VncState *vs, int bits_per_pixel,
return;
}
+ if (red_shift >= bits_per_pixel || red_shift >= 32 ||
+ green_shift >= bits_per_pixel || green_shift >= 32 ||
+ blue_shift >= bits_per_pixel || blue_shift >= 32) {
+ vnc_client_error(vs);
+ return;
+ }
+
vs->client_pf.rmax = red_max ? red_max : 0xFF;
vs->client_pf.rbits = ctpopl(red_max);
vs->client_pf.rshift = red_shift;
--
2.55.0
^ permalink raw reply related [flat|nested] 26+ messages in thread* [GIT PULL 04/15] ui/vnc: use RFB wire types for client message handlers
2026-07-17 11:52 [GIT PULL 00/15] Various UI/security-related fixes for 11.1 Marc-André Lureau
` (2 preceding siblings ...)
2026-07-17 11:52 ` [GIT PULL 03/15] ui/vnc: validate color shifts in SetPixelFormat Marc-André Lureau
@ 2026-07-17 11:52 ` Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 05/15] ui/input-barrier: fix off-by-one in keycode bounds check Marc-André Lureau
` (14 subsequent siblings)
18 siblings, 0 replies; 26+ messages in thread
From: Marc-André Lureau @ 2026-07-17 11:52 UTC (permalink / raw)
To: qemu-devel
Use exact-width unsigned types for the static functions that process
RFB client messages, matching the types returned by read_u8(),
read_u16(), and read_u32():
- set_pixel_format: uint8_t/uint16_t for pixel format fields
- pointer_event: uint8_t button_mask, uint16_t x/y
- key_event/ext_key_event: bool down, uint32_t sym/keycode
- do_key_event: uint32_t sym
- framebuffer_update_request: uint8_t incremental, uint16_t x/y/w/h
Drop needless declarations.
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-Andre Lureau <marcandre.lureau@redhat.com>
---
ui/vnc.c | 39 +++++++++++++++++----------------------
1 file changed, 17 insertions(+), 22 deletions(-)
diff --git a/ui/vnc.c b/ui/vnc.c
index 9219f593d95..8d91cee4d9f 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -608,15 +608,7 @@ bool vnc_display_reload_certs(const char *id, Error **errp)
3) resolutions > 1024
*/
-static int vnc_update_client(VncState *vs, int has_dirty);
-static void vnc_disconnect_start(VncState *vs);
-
static void vnc_colordepth(VncState *vs);
-static void framebuffer_update_request(VncState *vs, int incremental,
- int x_position, int y_position,
- int w, int h);
-static void vnc_refresh(DisplayChangeListener *dcl);
-static int vnc_refresh_server_surface(VncDisplay *vd);
static int vnc_width(VncDisplay *vd)
{
@@ -1763,7 +1755,8 @@ static void check_pointer_type_change(Notifier *notifier, void *data)
vs->absolute = absolute;
}
-static void pointer_event(VncState *vs, int button_mask, int x, int y)
+static void pointer_event(VncState *vs, uint8_t button_mask,
+ uint16_t x, uint16_t y)
{
static uint32_t bmap[INPUT_BUTTON__MAX] = {
[INPUT_BUTTON_LEFT] = 0x01,
@@ -1841,7 +1834,7 @@ static void kbd_leds(Notifier *notifier, void *data)
}
}
-static void do_key_event(VncState *vs, int down, int keycode, int sym)
+static void do_key_event(VncState *vs, int down, int keycode, uint32_t sym)
{
unsigned int lnx = qemu_input_key_number_to_linux(keycode);
@@ -2019,7 +2012,7 @@ static const char *code2name(int keycode)
return QKeyCode_str(qemu_input_key_number_to_qcode(keycode));
}
-static void key_event(VncState *vs, int down, uint32_t sym)
+static void key_event(VncState *vs, bool down, uint32_t sym)
{
int keycode;
int lsym = sym;
@@ -2034,8 +2027,8 @@ static void key_event(VncState *vs, int down, uint32_t sym)
do_key_event(vs, down, keycode, sym);
}
-static void ext_key_event(VncState *vs, int down,
- uint32_t sym, uint16_t keycode)
+static void ext_key_event(VncState *vs, bool down,
+ uint32_t sym, uint32_t keycode)
{
/* if the user specifies a keyboard layout, always use it */
if (keyboard_layout) {
@@ -2046,8 +2039,9 @@ static void ext_key_event(VncState *vs, int down,
}
}
-static void framebuffer_update_request(VncState *vs, int incremental,
- int x, int y, int w, int h)
+static void framebuffer_update_request(VncState *vs, uint8_t incremental,
+ uint16_t x, uint16_t y,
+ uint16_t w, uint16_t h)
{
if (incremental) {
if (vs->update != VNC_STATE_UPDATE_FORCE) {
@@ -2250,10 +2244,11 @@ static void send_color_map(VncState *vs)
vnc_unlock_output(vs);
}
-static void set_pixel_format(VncState *vs, int bits_per_pixel,
- int big_endian_flag, int true_color_flag,
- int red_max, int green_max, int blue_max,
- int red_shift, int green_shift, int blue_shift)
+static void set_pixel_format(VncState *vs, uint8_t bits_per_pixel,
+ uint8_t big_endian_flag, uint8_t true_color_flag,
+ uint16_t red_max, uint16_t green_max,
+ uint16_t blue_max, uint8_t red_shift,
+ uint8_t green_shift, uint8_t blue_shift)
{
if (!true_color_flag) {
/* Expose a reasonable default 256 color map */
@@ -2286,15 +2281,15 @@ static void set_pixel_format(VncState *vs, int bits_per_pixel,
vs->client_pf.rmax = red_max ? red_max : 0xFF;
vs->client_pf.rbits = ctpopl(red_max);
vs->client_pf.rshift = red_shift;
- vs->client_pf.rmask = red_max << red_shift;
+ vs->client_pf.rmask = (uint32_t)red_max << red_shift;
vs->client_pf.gmax = green_max ? green_max : 0xFF;
vs->client_pf.gbits = ctpopl(green_max);
vs->client_pf.gshift = green_shift;
- vs->client_pf.gmask = green_max << green_shift;
+ vs->client_pf.gmask = (uint32_t)green_max << green_shift;
vs->client_pf.bmax = blue_max ? blue_max : 0xFF;
vs->client_pf.bbits = ctpopl(blue_max);
vs->client_pf.bshift = blue_shift;
- vs->client_pf.bmask = blue_max << blue_shift;
+ vs->client_pf.bmask = (uint32_t)blue_max << blue_shift;
vs->client_pf.bits_per_pixel = bits_per_pixel;
vs->client_pf.bytes_per_pixel = bits_per_pixel / 8;
vs->client_pf.depth = bits_per_pixel == 32 ? 24 : bits_per_pixel;
--
2.55.0
^ permalink raw reply related [flat|nested] 26+ messages in thread* [GIT PULL 05/15] ui/input-barrier: fix off-by-one in keycode bounds check
2026-07-17 11:52 [GIT PULL 00/15] Various UI/security-related fixes for 11.1 Marc-André Lureau
` (3 preceding siblings ...)
2026-07-17 11:52 ` [GIT PULL 04/15] ui/vnc: use RFB wire types for client message handlers Marc-André Lureau
@ 2026-07-17 11:52 ` Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 06/15] ui/gtk: Narrow DMA-BUF critical section Marc-André Lureau
` (13 subsequent siblings)
18 siblings, 0 replies; 26+ messages in thread
From: Marc-André Lureau @ 2026-07-17 11:52 UTC (permalink / raw)
To: qemu-devel
Use strict "<" to fix the off-by-one.
Fixes: 6105683da35b ("ui: add an embedded Barrier client")
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3951
Reported-by: huntr bubble
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Laurent Vivier <lvivier@redhat.com>
Signed-off-by: Marc-Andre Lureau <marcandre.lureau@redhat.com>
---
ui/input-barrier.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ui/input-barrier.c b/ui/input-barrier.c
index d07027114af..0a238d4010b 100644
--- a/ui/input-barrier.c
+++ b/ui/input-barrier.c
@@ -87,7 +87,7 @@ static kbd_layout_t *kbd_layout;
static unsigned int input_barrier_to_linux(uint16_t keyid, uint16_t keycode)
{
/* keycode is optional, if it is not provided use keyid */
- if (keycode && keycode <= qemu_input_map_xorgkbd_to_linux_len) {
+ if (keycode && keycode < qemu_input_map_xorgkbd_to_linux_len) {
return qemu_input_map_xorgkbd_to_linux[keycode];
}
--
2.55.0
^ permalink raw reply related [flat|nested] 26+ messages in thread* [GIT PULL 06/15] ui/gtk: Narrow DMA-BUF critical section
2026-07-17 11:52 [GIT PULL 00/15] Various UI/security-related fixes for 11.1 Marc-André Lureau
` (4 preceding siblings ...)
2026-07-17 11:52 ` [GIT PULL 05/15] ui/input-barrier: fix off-by-one in keycode bounds check Marc-André Lureau
@ 2026-07-17 11:52 ` Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 07/15] ui/vnc: fix out-of-bounds write in lossy refresh dirty marking Marc-André Lureau
` (12 subsequent siblings)
18 siblings, 0 replies; 26+ messages in thread
From: Marc-André Lureau @ 2026-07-17 11:52 UTC (permalink / raw)
To: qemu-devel
From: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Scanout operations need to be properly ordered to avoid tearing. The
virtio specification allows the guest to use pageflip. With pageflip,
the guest only modifies the invisible framebuffer while the host scans
out the visible framebuffer. The guest may choose not to use pageflip to
avoid its overhead, accepting the risk of tearing.
ui/gtk performs the following procedure to flush a scanout:
1) Queue a draw event.
2) The draw event gets triggered.
3) Blit the guest framebuffer to the host framebuffer.
When flushing a DMA-BUF scanout, ui/gtk blocks the device before 2) if
possible and unblocks it after 3) to enforce proper ordering. However,
blocking the device before 2) has two problems.
First, it can leave the device blocked indefinitely because GTK
sometimes decides to cancel 2) when the window is not visible for
example. ui/gtk regularly repeats 1) as a workaround, but it is not
applicable to GtkGLArea because it causes display corruption.
Second, the behavior is inconsistent with the other types of scanout
that leave the device unblocked between 1) and 2).
To fix these problems, let ui/gtk block the device only when the
queued draw event runs, immediately before 3). Blocking before that is
unnecessary since ui/gtk does not access the framebuffer yet. If the
guest does not use pageflip but instead updates the visible framebuffer
directly, ui/gtk should not add the overhead of a pre-draw block.
ui/gtk still blocks the device during 3) for DMA-BUF. Unlike the other
scanout types, 3) can happen asynchronously with the device for a
DMA-BUF, so ui/gtk needs to keep the visible guest framebuffer stable
for the blit.
With the problems fixed, the workaround to repeat 1) is no longer
necessary and is removed.
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Acked-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260628-gtk-v2-1-1e4839012f09@rsg.ci.i.u-tokyo.ac.jp>
---
ui/gtk-egl.c | 6 ++----
ui/gtk-gl-area.c | 23 +----------------------
2 files changed, 3 insertions(+), 26 deletions(-)
diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
index 7c5c9b2428c..adc81f34b1c 100644
--- a/ui/gtk-egl.c
+++ b/ui/gtk-egl.c
@@ -91,6 +91,7 @@ void gd_egl_draw(VirtualConsole *vc)
} else {
qemu_dmabuf_set_draw_submitted(dmabuf, false);
}
+ qemu_console_hw_gl_block(vc->gfx.dcl.con, true);
}
#endif
gd_egl_scanout_flush(&vc->gfx.dcl, 0, 0, vc->gfx.w, vc->gfx.h);
@@ -405,14 +406,11 @@ void gd_egl_flush(DisplayChangeListener *dcl,
if (vc->gfx.guest_fb.dmabuf &&
!qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) {
- qemu_console_hw_gl_block(vc->gfx.dcl.con, true);
qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true);
gtk_egl_set_scanout_mode(vc, true);
- gtk_widget_queue_draw_area(area, x, y, w, h);
- return;
}
- gd_egl_scanout_flush(&vc->gfx.dcl, x, y, w, h);
+ gtk_widget_queue_draw_area(area, x, y, w, h);
}
void gtk_egl_init(DisplayGLMode mode)
diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c
index 23806b9d01b..29497019ee4 100644
--- a/ui/gtk-gl-area.c
+++ b/ui/gtk-gl-area.c
@@ -86,6 +86,7 @@ void gd_gl_area_draw(VirtualConsole *vc)
} else {
qemu_dmabuf_set_draw_submitted(dmabuf, false);
}
+ qemu_console_hw_gl_block(vc->gfx.dcl.con, true);
}
#endif
@@ -163,27 +164,6 @@ void gd_gl_area_refresh(DisplayChangeListener *dcl)
gd_update_monitor_refresh_rate(vc, vc->window ? vc->window : vc->gfx.drawing_area);
- if (vc->gfx.guest_fb.dmabuf &&
- qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) {
- /*
- * gd_egl_refresh() calls gd_egl_draw() if a DMA-BUF draw has already
- * been submitted, but this function does not call gd_gl_area_draw() in
- * such a case due to display corruption.
- *
- * Calling gd_gl_area_draw() is necessary to prevent a situation where
- * there is a scheduled draw event but it won't happen bacause the window
- * is currently in inactive state (minimized or tabified). If draw is not
- * done for a long time, gl_block timeout and/or fence timeout (on the
- * guest) will happen eventually.
- *
- * However, it is found that calling gd_gl_area_draw() here causes guest
- * display corruption on a Wayland Compositor. The display corruption is
- * more serious than the possible fence timeout so gd_gl_area_draw() is
- * omitted for now.
- */
- return;
- }
-
if (!vc->gfx.gls) {
if (!gtk_widget_get_realized(vc->gfx.drawing_area)) {
return;
@@ -347,7 +327,6 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl,
if (vc->gfx.guest_fb.dmabuf &&
!qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) {
- qemu_console_hw_gl_block(vc->gfx.dcl.con, true);
qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true);
gtk_gl_area_set_scanout_mode(vc, true);
}
--
2.55.0
^ permalink raw reply related [flat|nested] 26+ messages in thread* [GIT PULL 07/15] ui/vnc: fix out-of-bounds write in lossy refresh dirty marking
2026-07-17 11:52 [GIT PULL 00/15] Various UI/security-related fixes for 11.1 Marc-André Lureau
` (5 preceding siblings ...)
2026-07-17 11:52 ` [GIT PULL 06/15] ui/gtk: Narrow DMA-BUF critical section Marc-André Lureau
@ 2026-07-17 11:52 ` Marc-André Lureau
2026-07-21 8:17 ` Peter Maydell
2026-07-17 11:52 ` [GIT PULL 08/15] ui/vnc: validate SetPixelFormat field ranges Marc-André Lureau
` (11 subsequent siblings)
18 siblings, 1 reply; 26+ messages in thread
From: Marc-André Lureau @ 2026-07-17 11:52 UTC (permalink / raw)
To: qemu-devel
vnc_refresh_lossy_rect() marks a full VNC_STAT_RECT (64) rows of the
dirty bitmap when refreshing a lossy tile. When the display height is
not a multiple of VNC_STAT_RECT, the last tile row is a partial tile and
the loop writes past the end of vs->dirty[VNC_MAX_HEIGHT].
For example, with a 2160-pixel-high display (VNC_MAX_HEIGHT), the last
stat tile starts at y=2112. The unconditional 64-row loop writes rows
2112..2175, overflowing 16 rows (640 bytes) past the dirty bitmap into
subsequent VncState fields.
Fix by passing the effective display height into
vnc_refresh_lossy_rect() and clamping the inner loop.
Fixes: CVE-2026-61475
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3935
Reported-by: "Vulnerability Report" <vr@darknavy.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Marc-Andre Lureau <marcandre.lureau@redhat.com>
---
ui/vnc.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/ui/vnc.c b/ui/vnc.c
index 8d91cee4d9f..c957731877f 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -3000,18 +3000,18 @@ void vnc_sent_lossy_rect(VncWorker *worker, int x, int y, int w, int h)
}
}
-static int vnc_refresh_lossy_rect(VncDisplay *vd, int x, int y)
+static int vnc_refresh_lossy_rect(VncDisplay *vd, int x, int y,
+ int height)
{
VncState *vs;
int sty = y / VNC_STAT_RECT;
int stx = x / VNC_STAT_RECT;
int has_dirty = 0;
- int height = MIN(pixman_image_get_height(vd->guest.fb),
- pixman_image_get_height(vd->server));
int rows;
y = QEMU_ALIGN_DOWN(y, VNC_STAT_RECT);
x = QEMU_ALIGN_DOWN(x, VNC_STAT_RECT);
+ rows = MIN(VNC_STAT_RECT, height - y);
rows = MIN(VNC_STAT_RECT, height - y);
if (rows <= 0) {
@@ -3083,7 +3083,7 @@ static int vnc_update_stats(VncDisplay *vd, struct timeval * tv)
if (timercmp(&res, &VNC_REFRESH_LOSSY, >)) {
rect->freq = 0;
- has_dirty += vnc_refresh_lossy_rect(vd, x, y);
+ has_dirty += vnc_refresh_lossy_rect(vd, x, y, height);
memset(rect->times, 0, sizeof (rect->times));
continue ;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 26+ messages in thread* Re: [GIT PULL 07/15] ui/vnc: fix out-of-bounds write in lossy refresh dirty marking
2026-07-17 11:52 ` [GIT PULL 07/15] ui/vnc: fix out-of-bounds write in lossy refresh dirty marking Marc-André Lureau
@ 2026-07-21 8:17 ` Peter Maydell
2026-07-21 8:23 ` Marc-André Lureau
0 siblings, 1 reply; 26+ messages in thread
From: Peter Maydell @ 2026-07-21 8:17 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel
On Fri, 17 Jul 2026 at 12:54, Marc-André Lureau
<marcandre.lureau@redhat.com> wrote:
>
> vnc_refresh_lossy_rect() marks a full VNC_STAT_RECT (64) rows of the
> dirty bitmap when refreshing a lossy tile. When the display height is
> not a multiple of VNC_STAT_RECT, the last tile row is a partial tile and
> the loop writes past the end of vs->dirty[VNC_MAX_HEIGHT].
>
> For example, with a 2160-pixel-high display (VNC_MAX_HEIGHT), the last
> stat tile starts at y=2112. The unconditional 64-row loop writes rows
> 2112..2175, overflowing 16 rows (640 bytes) past the dirty bitmap into
> subsequent VncState fields.
>
> Fix by passing the effective display height into
> vnc_refresh_lossy_rect() and clamping the inner loop.
>
> Fixes: CVE-2026-61475
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3935
> Reported-by: "Vulnerability Report" <vr@darknavy.com>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
> Signed-off-by: Marc-Andre Lureau <marcandre.lureau@redhat.com>
> ---
> ui/vnc.c | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/ui/vnc.c b/ui/vnc.c
> index 8d91cee4d9f..c957731877f 100644
> --- a/ui/vnc.c
> +++ b/ui/vnc.c
> @@ -3000,18 +3000,18 @@ void vnc_sent_lossy_rect(VncWorker *worker, int x, int y, int w, int h)
> }
> }
>
> -static int vnc_refresh_lossy_rect(VncDisplay *vd, int x, int y)
> +static int vnc_refresh_lossy_rect(VncDisplay *vd, int x, int y,
> + int height)
> {
> VncState *vs;
> int sty = y / VNC_STAT_RECT;
> int stx = x / VNC_STAT_RECT;
> int has_dirty = 0;
> - int height = MIN(pixman_image_get_height(vd->guest.fb),
> - pixman_image_get_height(vd->server));
> int rows;
>
> y = QEMU_ALIGN_DOWN(y, VNC_STAT_RECT);
> x = QEMU_ALIGN_DOWN(x, VNC_STAT_RECT);
> + rows = MIN(VNC_STAT_RECT, height - y);
Hi. Coverity points out (CID 1664010) that this added line...
> rows = MIN(VNC_STAT_RECT, height - y);
...is a duplicate of this pre-existing line, so it does nothing.
Were you intending to clamp a different variable here ?
thanks
-- PMM
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [GIT PULL 07/15] ui/vnc: fix out-of-bounds write in lossy refresh dirty marking
2026-07-21 8:17 ` Peter Maydell
@ 2026-07-21 8:23 ` Marc-André Lureau
2026-07-21 8:34 ` Peter Maydell
0 siblings, 1 reply; 26+ messages in thread
From: Marc-André Lureau @ 2026-07-21 8:23 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-devel
Hi
On Tue, Jul 21, 2026 at 12:18 PM Peter Maydell <peter.maydell@linaro.org> wrote:
>
> On Fri, 17 Jul 2026 at 12:54, Marc-André Lureau
> <marcandre.lureau@redhat.com> wrote:
> >
> > vnc_refresh_lossy_rect() marks a full VNC_STAT_RECT (64) rows of the
> > dirty bitmap when refreshing a lossy tile. When the display height is
> > not a multiple of VNC_STAT_RECT, the last tile row is a partial tile and
> > the loop writes past the end of vs->dirty[VNC_MAX_HEIGHT].
> >
> > For example, with a 2160-pixel-high display (VNC_MAX_HEIGHT), the last
> > stat tile starts at y=2112. The unconditional 64-row loop writes rows
> > 2112..2175, overflowing 16 rows (640 bytes) past the dirty bitmap into
> > subsequent VncState fields.
> >
> > Fix by passing the effective display height into
> > vnc_refresh_lossy_rect() and clamping the inner loop.
> >
> > Fixes: CVE-2026-61475
> > Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3935
> > Reported-by: "Vulnerability Report" <vr@darknavy.com>
> > Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
> > Signed-off-by: Marc-Andre Lureau <marcandre.lureau@redhat.com>
> > ---
> > ui/vnc.c | 8 ++++----
> > 1 file changed, 4 insertions(+), 4 deletions(-)
> >
> > diff --git a/ui/vnc.c b/ui/vnc.c
> > index 8d91cee4d9f..c957731877f 100644
> > --- a/ui/vnc.c
> > +++ b/ui/vnc.c
> > @@ -3000,18 +3000,18 @@ void vnc_sent_lossy_rect(VncWorker *worker, int x, int y, int w, int h)
> > }
> > }
> >
> > -static int vnc_refresh_lossy_rect(VncDisplay *vd, int x, int y)
> > +static int vnc_refresh_lossy_rect(VncDisplay *vd, int x, int y,
> > + int height)
> > {
> > VncState *vs;
> > int sty = y / VNC_STAT_RECT;
> > int stx = x / VNC_STAT_RECT;
> > int has_dirty = 0;
> > - int height = MIN(pixman_image_get_height(vd->guest.fb),
> > - pixman_image_get_height(vd->server));
> > int rows;
> >
> > y = QEMU_ALIGN_DOWN(y, VNC_STAT_RECT);
> > x = QEMU_ALIGN_DOWN(x, VNC_STAT_RECT);
> > + rows = MIN(VNC_STAT_RECT, height - y);
>
> Hi. Coverity points out (CID 1664010) that this added line...
>
> > rows = MIN(VNC_STAT_RECT, height - y);
>
> ...is a duplicate of this pre-existing line, so it does nothing.
>
> Were you intending to clamp a different variable here ?
it's a rebase/merge mistake, original patch:
https://patchew.org/QEMU/20260710134921.2321027-1-marcandre.lureau@redhat.com/
Are you sending a patch?
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [GIT PULL 07/15] ui/vnc: fix out-of-bounds write in lossy refresh dirty marking
2026-07-21 8:23 ` Marc-André Lureau
@ 2026-07-21 8:34 ` Peter Maydell
0 siblings, 0 replies; 26+ messages in thread
From: Peter Maydell @ 2026-07-21 8:34 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel
On Tue, 21 Jul 2026 at 09:23, Marc-André Lureau
<marcandre.lureau@redhat.com> wrote:
>
> Hi
>
> On Tue, Jul 21, 2026 at 12:18 PM Peter Maydell <peter.maydell@linaro.org> wrote:
> >
> > On Fri, 17 Jul 2026 at 12:54, Marc-André Lureau
> > <marcandre.lureau@redhat.com> wrote:
> > > + rows = MIN(VNC_STAT_RECT, height - y);
> >
> > Hi. Coverity points out (CID 1664010) that this added line...
> >
> > > rows = MIN(VNC_STAT_RECT, height - y);
> >
> > ...is a duplicate of this pre-existing line, so it does nothing.
> >
> > Were you intending to clamp a different variable here ?
>
> it's a rebase/merge mistake, original patch:
>
> https://patchew.org/QEMU/20260710134921.2321027-1-marcandre.lureau@redhat.com/
>
> Are you sending a patch?
It's probably easier if you send the patch -- I don't have a
setup to test VNC at all.
thanks
-- PMM
^ permalink raw reply [flat|nested] 26+ messages in thread
* [GIT PULL 08/15] ui/vnc: validate SetPixelFormat field ranges
2026-07-17 11:52 [GIT PULL 00/15] Various UI/security-related fixes for 11.1 Marc-André Lureau
` (6 preceding siblings ...)
2026-07-17 11:52 ` [GIT PULL 07/15] ui/vnc: fix out-of-bounds write in lossy refresh dirty marking Marc-André Lureau
@ 2026-07-17 11:52 ` Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 09/15] hw/display/virtio-gpu: fix dmabuf_fd leak on remap failure Marc-André Lureau
` (10 subsequent siblings)
18 siblings, 0 replies; 26+ messages in thread
From: Marc-André Lureau @ 2026-07-17 11:52 UTC (permalink / raw)
To: qemu-devel
The VNC SetPixelFormat message carries red/green/blue_max as 16-bit
values, but PixelFormat stores them as uint8_t. A client sending a
max value above 255 (e.g. 0x0100) passes the existing non-zero check
but silently truncates to 0 on assignment, leading to a division by
zero in the Tight PNG palette path.
Add explicit range checks if any channel max exceeds UINT8_MAX.
Fixes: CVE-2026-15578
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3976
Reported-by: dong ling
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Marc-Andre Lureau <marcandre.lureau@redhat.com>
---
ui/vnc.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/ui/vnc.c b/ui/vnc.c
index c957731877f..24aa40f7308 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2271,6 +2271,11 @@ static void set_pixel_format(VncState *vs, uint8_t bits_per_pixel,
return;
}
+ if (red_max > UINT8_MAX || green_max > UINT8_MAX || blue_max > UINT8_MAX) {
+ vnc_client_error(vs);
+ return;
+ }
+
if (red_shift >= bits_per_pixel || red_shift >= 32 ||
green_shift >= bits_per_pixel || green_shift >= 32 ||
blue_shift >= bits_per_pixel || blue_shift >= 32) {
--
2.55.0
^ permalink raw reply related [flat|nested] 26+ messages in thread* [GIT PULL 09/15] hw/display/virtio-gpu: fix dmabuf_fd leak on remap failure
2026-07-17 11:52 [GIT PULL 00/15] Various UI/security-related fixes for 11.1 Marc-André Lureau
` (7 preceding siblings ...)
2026-07-17 11:52 ` [GIT PULL 08/15] ui/vnc: validate SetPixelFormat field ranges Marc-André Lureau
@ 2026-07-17 11:52 ` Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 10/15] hw/display/qxl: fix TOCTOU in cursor chunk data_size handling Marc-André Lureau
` (9 subsequent siblings)
18 siblings, 0 replies; 26+ messages in thread
From: Marc-André Lureau @ 2026-07-17 11:52 UTC (permalink / raw)
To: qemu-devel
When virtio_gpu_create_udmabuf() succeeds but virtio_gpu_remap_udmabuf()
fails (mmap returns MAP_FAILED), virtio_gpu_init_udmabuf() returns early
without closing the dmabuf fd. Since res->blob is never set in this
path, later cleanup via virtio_gpu_cleanup_mapping() skips
virtio_gpu_fini_udmabuf() entirely, leaking the file descriptor.
Call virtio_gpu_destroy_udmabuf() before the early return to close
the fd. This function already handles partial state correctly: it
skips the munmap when res->remapped is NULL and closes the fd when
res->dmabuf_fd >= 0.
Fixes: 9b60cdf98723 ("virtio-gpu: Add udmabuf helpers")
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
hw/display/virtio-gpu-udmabuf.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c
index d5ac1cfca0e..5f08c855dde 100644
--- a/hw/display/virtio-gpu-udmabuf.c
+++ b/hw/display/virtio-gpu-udmabuf.c
@@ -143,6 +143,7 @@ void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
}
virtio_gpu_remap_udmabuf(res);
if (!res->remapped) {
+ virtio_gpu_destroy_udmabuf(res);
return;
}
pdata = res->remapped;
--
2.55.0
^ permalink raw reply related [flat|nested] 26+ messages in thread* [GIT PULL 10/15] hw/display/qxl: fix TOCTOU in cursor chunk data_size handling
2026-07-17 11:52 [GIT PULL 00/15] Various UI/security-related fixes for 11.1 Marc-André Lureau
` (8 preceding siblings ...)
2026-07-17 11:52 ` [GIT PULL 09/15] hw/display/virtio-gpu: fix dmabuf_fd leak on remap failure Marc-André Lureau
@ 2026-07-17 11:52 ` Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 11/15] hw/display/virtio-gpu: validate stride against width on scanout Marc-André Lureau
` (8 subsequent siblings)
18 siblings, 0 replies; 26+ messages in thread
From: Marc-André Lureau @ 2026-07-17 11:52 UTC (permalink / raw)
To: qemu-devel
Snapshot chunk.data_size into a host-local variable before passing it to
qxl_phys2virt() for validation, and pass it through qxl_cursor() and
qxl_unpack_chunks() so that no subsequent code re-reads the field.
Without this, a racing vCPU can inflate data_size between the
qxl_phys2virt() validation and the memcpy in qxl_unpack_chunks(),
causing a source read past the validated region. In practice the read
stays within the guest's own VRAM mmap, so the impact is limited.
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3757
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reported-by: Feifan Qian <bea1e@proton.me>
Signed-off-by: Marc-Andre Lureau <marcandre.lureau@redhat.com>
---
hw/display/qxl-render.c | 28 +++++++++++++++++-----------
1 file changed, 17 insertions(+), 11 deletions(-)
diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c
index 3bf634ee059..4799c9e8bef 100644
--- a/hw/display/qxl-render.c
+++ b/hw/display/qxl-render.c
@@ -217,7 +217,8 @@ void qxl_render_update_area_done(PCIQXLDevice *qxl, QXLCookie *cookie)
}
static void qxl_unpack_chunks(void *dest, size_t size, PCIQXLDevice *qxl,
- QXLDataChunk *chunk, uint32_t group_id)
+ QXLDataChunk *chunk, uint32_t group_id,
+ uint32_t chunk_data_size)
{
uint32_t max_chunks = 32;
size_t offset = 0;
@@ -225,22 +226,21 @@ static void qxl_unpack_chunks(void *dest, size_t size, PCIQXLDevice *qxl,
QXLPHYSICAL next_chunk_phys = 0;
for (;;) {
- bytes = MIN(size - offset, chunk->data_size);
+ bytes = MIN(size - offset, chunk_data_size);
memcpy(dest + offset, chunk->data, bytes);
offset += bytes;
if (offset == size) {
return;
}
next_chunk_phys = chunk->next_chunk;
- /* fist time, only get the next chunk's data size */
chunk = qxl_phys2virt(qxl, next_chunk_phys, group_id,
sizeof(QXLDataChunk));
if (!chunk) {
return;
}
- /* second time, check data size and get data */
+ chunk_data_size = chunk->data_size;
chunk = qxl_phys2virt(qxl, next_chunk_phys, group_id,
- sizeof(QXLDataChunk) + chunk->data_size);
+ sizeof(QXLDataChunk) + chunk_data_size);
if (!chunk) {
return;
}
@@ -252,7 +252,7 @@ static void qxl_unpack_chunks(void *dest, size_t size, PCIQXLDevice *qxl,
}
static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor,
- uint32_t group_id)
+ uint32_t group_id, uint32_t chunk_data_size)
{
QEMUCursor *c;
uint8_t *and_mask, *xor_mask;
@@ -272,11 +272,11 @@ static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor,
case SPICE_CURSOR_TYPE_MONO:
/* Assume that the full cursor is available in a single chunk. */
size = 2 * cursor_get_mono_bpl(c) * c->height;
- if (size != cursor->data_size || cursor->chunk.data_size < size) {
+ if (size != cursor->data_size || chunk_data_size < size) {
qxl_set_guest_bug(qxl, "%s: bad monochrome cursor %ux%u"
" data_size %u chunk_size %u",
__func__, c->width, c->height,
- cursor->data_size, cursor->chunk.data_size);
+ cursor->data_size, chunk_data_size);
goto fail;
}
and_mask = cursor->chunk.data;
@@ -288,7 +288,8 @@ static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor,
break;
case SPICE_CURSOR_TYPE_ALPHA:
size = sizeof(uint32_t) * c->width * c->height;
- qxl_unpack_chunks(c->data, size, qxl, &cursor->chunk, group_id);
+ qxl_unpack_chunks(c->data, size, qxl, &cursor->chunk, group_id,
+ chunk_data_size);
if (qxl->debug > 2) {
cursor_print_ascii_art(c, "qxl/alpha");
}
@@ -325,19 +326,23 @@ int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext)
}
switch (cmd->type) {
case QXL_CURSOR_SET:
+ {
+ uint32_t chunk_data_size;
+
/* First read the QXLCursor to get QXLDataChunk::data_size ... */
cursor = qxl_phys2virt(qxl, cmd->u.set.shape, ext->group_id,
sizeof(QXLCursor));
if (!cursor) {
return 1;
}
+ chunk_data_size = cursor->chunk.data_size;
/* Then read including the chunked data following QXLCursor. */
cursor = qxl_phys2virt(qxl, cmd->u.set.shape, ext->group_id,
- sizeof(QXLCursor) + cursor->chunk.data_size);
+ sizeof(QXLCursor) + chunk_data_size);
if (!cursor) {
return 1;
}
- c = qxl_cursor(qxl, cursor, ext->group_id);
+ c = qxl_cursor(qxl, cursor, ext->group_id, chunk_data_size);
if (c == NULL) {
c = cursor_builtin_left_ptr();
}
@@ -351,6 +356,7 @@ int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext)
qemu_mutex_unlock(&qxl->ssd.lock);
qemu_bh_schedule(qxl->ssd.cursor_bh);
break;
+ }
case QXL_CURSOR_MOVE:
qemu_mutex_lock(&qxl->ssd.lock);
qxl->ssd.mouse_x = cmd->u.position.x;
--
2.55.0
^ permalink raw reply related [flat|nested] 26+ messages in thread* [GIT PULL 11/15] hw/display/virtio-gpu: validate stride against width on scanout
2026-07-17 11:52 [GIT PULL 00/15] Various UI/security-related fixes for 11.1 Marc-André Lureau
` (9 preceding siblings ...)
2026-07-17 11:52 ` [GIT PULL 10/15] hw/display/qxl: fix TOCTOU in cursor chunk data_size handling Marc-André Lureau
@ 2026-07-17 11:52 ` Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 12/15] hw/display/virtio-gpu: cap submit_3d command buffer allocation Marc-André Lureau
` (7 subsequent siblings)
18 siblings, 0 replies; 26+ messages in thread
From: Marc-André Lureau @ 2026-07-17 11:52 UTC (permalink / raw)
To: qemu-devel
Validate that the framebuffer stride is at least width * bytes_per_pixel
in both virtio_gpu_scanout_blob_to_fb() and virtio_gpu_do_set_scanout().
A guest can set a very small stride while using a large width. The total
size check (offset + stride * height <= blob_size) passes because
stride * height is small, but pixman reads width * bytes_per_pixel per
row, causing heap OOB reads. The leaked data is rendered to the host
display.
The check is added in virtio_gpu_do_set_scanout() to cover all paths:
blob scanout, non-blob scanout and migration post_load. The additional
early check in virtio_gpu_scanout_blob_to_fb() rejects invalid blob
configurations early.
Fixes: CVE-2026-63109
Fixes: 7b5574225429 ("hw/display: check frame buffer can hold blob")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3989
Reported-by: Tristan @TristanInSec
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
hw/display/virtio-gpu.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 88526051a99..e00fb6effa5 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -646,6 +646,14 @@ static bool virtio_gpu_do_set_scanout(VirtIOGPU *g,
return false;
}
+ if (fb->stride < (uint64_t)fb->width * fb->bytes_pp) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: stride %u too small for width %u at %u bpp\n",
+ __func__, fb->stride, fb->width, fb->bytes_pp);
+ *error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+ return false;
+ }
+
g->parent_obj.enable = 1;
if (res->blob) {
@@ -753,6 +761,14 @@ bool virtio_gpu_scanout_blob_to_fb(struct virtio_gpu_framebuffer *fb,
fb->width = ss->width;
fb->height = ss->height;
fb->stride = ss->strides[0];
+
+ if (fb->stride < (uint64_t)fb->width * fb->bytes_pp) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: stride %u too small for width %u at %u bpp\n",
+ __func__, fb->stride, fb->width, fb->bytes_pp);
+ return false;
+ }
+
fb->offset = ss->offsets[0] + ss->r.x * fb->bytes_pp + ss->r.y * fb->stride;
fbend = fb->offset;
--
2.55.0
^ permalink raw reply related [flat|nested] 26+ messages in thread* [GIT PULL 12/15] hw/display/virtio-gpu: cap submit_3d command buffer allocation
2026-07-17 11:52 [GIT PULL 00/15] Various UI/security-related fixes for 11.1 Marc-André Lureau
` (10 preceding siblings ...)
2026-07-17 11:52 ` [GIT PULL 11/15] hw/display/virtio-gpu: validate stride against width on scanout Marc-André Lureau
@ 2026-07-17 11:52 ` Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 13/15] hw/display/virtio-gpu: handle migration iov allocation failure Marc-André Lureau
` (6 subsequent siblings)
18 siblings, 0 replies; 26+ messages in thread
From: Marc-André Lureau @ 2026-07-17 11:52 UTC (permalink / raw)
To: qemu-devel
Both virgl_cmd_submit_3d() and rutabaga_cmd_submit_3d() pass the
guest-controlled cs.size directly to malloc() without bounds checking. A
malicious guest can set cs.size to an arbitrarily large value, causing
an OOM abort that crashes the QEMU process.
Checking cs.size against the descriptor payload length (iov_size) is not
sufficient: indirect descriptor tables can repeat entries aliasing the
same guest-physical range, inflating iov_size() to nearly 4 GiB while
referring to only a small amount of unique memory.
Instead, cap cs.size at 4 MiB. With 4 KiB pages and QEMU's
VIRTQUEUE_MAX_SIZE (1024) mapped-iov limit, the Linux virtio driver
cannot carry more than ~4 MiB of inline command data, so legitimate
submissions are unaffected.
Fixes: 9d9e152136bd ("virtio-gpu: add 3d mode and virgl rendering support.")
Fixes: 1dcc6adbc168 ("gfxstream + rutabaga: add initial support for gfxstream")
Fixes: d52c454aadc ("contrib: add vhost-user-gpu")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3776
Reported-by: admin@fluentlogic.org
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
contrib/vhost-user-gpu/vugpu.h | 9 +++++++++
include/hw/virtio/virtio-gpu.h | 9 +++++++++
contrib/vhost-user-gpu/virgl.c | 7 +++++++
hw/display/virtio-gpu-rutabaga.c | 8 ++++++++
hw/display/virtio-gpu-virgl.c | 8 ++++++++
5 files changed, 41 insertions(+)
diff --git a/contrib/vhost-user-gpu/vugpu.h b/contrib/vhost-user-gpu/vugpu.h
index 654c392fbbf..2374eb90cb9 100644
--- a/contrib/vhost-user-gpu/vugpu.h
+++ b/contrib/vhost-user-gpu/vugpu.h
@@ -22,6 +22,7 @@
#include "qemu/queue.h"
#include "qemu/iov.h"
#include "qemu/bswap.h"
+#include "qemu/units.h"
#include "vugbm.h"
typedef enum VhostUserGpuRequest {
@@ -163,6 +164,14 @@ struct virtio_gpu_ctrl_command {
QTAILQ_ENTRY(virtio_gpu_ctrl_command) next;
};
+/*
+ * With 4 KiB pages and QEMU's VIRTQUEUE_MAX_SIZE (1024) mapped-iov
+ * limit, the largest inline command is ~4 MiB. Cap submit_3d
+ * allocations to this value to prevent a malicious guest from
+ * triggering an OOM abort via an inflated cs.size field.
+ */
+#define VIRTIO_GPU_MAX_CMD_SUBMIT_SIZE (4 * MiB)
+
#define VUGPU_FILL_CMD(out) do { \
size_t vugpufillcmd_s_ = \
iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, 0, \
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index f69fc194627..b9bad27c97a 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -15,6 +15,7 @@
#define HW_VIRTIO_GPU_H
#include "qemu/queue.h"
+#include "qemu/units.h"
#include "ui/qemu-pixman.h"
#include "ui/console.h"
#include "hw/virtio/virtio.h"
@@ -299,6 +300,14 @@ struct VirtIOGPURutabaga {
struct rutabaga *rutabaga;
};
+/*
+ * With 4 KiB pages and QEMU's VIRTQUEUE_MAX_SIZE (1024) mapped-iov
+ * limit, the largest inline command is ~4 MiB. Cap submit_3d
+ * allocations to this value to prevent a malicious guest from
+ * triggering an OOM abort via an inflated cs.size field.
+ */
+#define VIRTIO_GPU_MAX_CMD_SUBMIT_SIZE (4 * MiB)
+
#define VIRTIO_GPU_FILL_CMD(out) do { \
size_t virtiogpufillcmd_s_ = \
iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, 0, \
diff --git a/contrib/vhost-user-gpu/virgl.c b/contrib/vhost-user-gpu/virgl.c
index 51da0e3667f..550fd03bf5c 100644
--- a/contrib/vhost-user-gpu/virgl.c
+++ b/contrib/vhost-user-gpu/virgl.c
@@ -202,6 +202,13 @@ virgl_cmd_submit_3d(VuGpu *g,
VUGPU_FILL_CMD(cs);
+ if (cs.size > VIRTIO_GPU_MAX_CMD_SUBMIT_SIZE) {
+ g_critical("%s: command buffer too large (%u)",
+ __func__, cs.size);
+ cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+ return;
+ }
+
buf = g_malloc(cs.size);
s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
sizeof(cs), buf, cs.size);
diff --git a/hw/display/virtio-gpu-rutabaga.c b/hw/display/virtio-gpu-rutabaga.c
index 6ff12639012..4d7d7b24592 100644
--- a/hw/display/virtio-gpu-rutabaga.c
+++ b/hw/display/virtio-gpu-rutabaga.c
@@ -351,6 +351,14 @@ rutabaga_cmd_submit_3d(VirtIOGPU *g,
VIRTIO_GPU_FILL_CMD(cs);
trace_virtio_gpu_cmd_ctx_submit(cs.hdr.ctx_id, cs.size);
+ if (cs.size > VIRTIO_GPU_MAX_CMD_SUBMIT_SIZE) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: command buffer too large (%u)\n",
+ __func__, cs.size);
+ cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+ return;
+ }
+
buf = g_new0(uint8_t, cs.size);
s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
sizeof(cs), buf, cs.size);
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 60c78af06a4..d9e5b011049 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -607,6 +607,14 @@ static void virgl_cmd_submit_3d(VirtIOGPU *g,
VIRTIO_GPU_FILL_CMD(cs);
trace_virtio_gpu_cmd_ctx_submit(cs.hdr.ctx_id, cs.size);
+ if (cs.size > VIRTIO_GPU_MAX_CMD_SUBMIT_SIZE) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: command buffer too large (%u)\n",
+ __func__, cs.size);
+ cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+ return;
+ }
+
buf = g_malloc(cs.size);
s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
sizeof(cs), buf, cs.size);
--
2.55.0
^ permalink raw reply related [flat|nested] 26+ messages in thread* [GIT PULL 13/15] hw/display/virtio-gpu: handle migration iov allocation failure
2026-07-17 11:52 [GIT PULL 00/15] Various UI/security-related fixes for 11.1 Marc-André Lureau
` (11 preceding siblings ...)
2026-07-17 11:52 ` [GIT PULL 12/15] hw/display/virtio-gpu: cap submit_3d command buffer allocation Marc-André Lureau
@ 2026-07-17 11:52 ` Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 14/15] hw/display/virtio-gpu: reject strides exceeding INT_MAX Marc-André Lureau
` (5 subsequent siblings)
18 siblings, 0 replies; 26+ messages in thread
From: Marc-André Lureau @ 2026-07-17 11:52 UTC (permalink / raw)
To: qemu-devel
An unbounded iov_cnt from the migration stream drives two g_new()
allocations whose combined size can exceed available memory, causing
GLib to abort the process.
Switch to g_try_new() and propagate the failure as a migration error.
Fixes: 0c244e50ee12 ("virtio-gpu: add live migration support")
Fixes: f66767f75c9c ("virtio-gpu: add virtio-gpu/blob vmstate subsection")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3753
Reported-by: Feifan Qian <bea1e@proton.me>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
hw/display/virtio-gpu.c | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index e00fb6effa5..048b151872e 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1365,8 +1365,15 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
return -EINVAL;
}
- res->addrs = g_new(uint64_t, res->iov_cnt);
- res->iov = g_new(struct iovec, res->iov_cnt);
+ res->addrs = g_try_new(uint64_t, res->iov_cnt);
+ res->iov = g_try_new(struct iovec, res->iov_cnt);
+ if (res->iov_cnt && (!res->addrs || !res->iov)) {
+ pixman_image_unref(res->image);
+ g_free(res->addrs);
+ g_free(res->iov);
+ g_free(res);
+ return -EINVAL;
+ }
/* read data */
for (i = 0; i < res->iov_cnt; i++) {
@@ -1440,8 +1447,15 @@ static int virtio_gpu_blob_load(QEMUFile *f, void *opaque, size_t size,
res->resource_id = resource_id;
res->blob_size = qemu_get_be32(f);
res->iov_cnt = qemu_get_be32(f);
- res->addrs = g_new(uint64_t, res->iov_cnt);
- res->iov = g_new(struct iovec, res->iov_cnt);
+
+ res->addrs = g_try_new(uint64_t, res->iov_cnt);
+ res->iov = g_try_new(struct iovec, res->iov_cnt);
+ if (res->iov_cnt && (!res->addrs || !res->iov)) {
+ g_free(res->addrs);
+ g_free(res->iov);
+ g_free(res);
+ return -EINVAL;
+ }
/* read data */
for (i = 0; i < res->iov_cnt; i++) {
--
2.55.0
^ permalink raw reply related [flat|nested] 26+ messages in thread* [GIT PULL 14/15] hw/display/virtio-gpu: reject strides exceeding INT_MAX
2026-07-17 11:52 [GIT PULL 00/15] Various UI/security-related fixes for 11.1 Marc-André Lureau
` (12 preceding siblings ...)
2026-07-17 11:52 ` [GIT PULL 13/15] hw/display/virtio-gpu: handle migration iov allocation failure Marc-André Lureau
@ 2026-07-17 11:52 ` Marc-André Lureau
2026-07-17 11:52 ` [GIT PULL 15/15] hw/display/virtio-gpu: Check pixman_image_create_bits() results Marc-André Lureau
` (4 subsequent siblings)
18 siblings, 0 replies; 26+ messages in thread
From: Marc-André Lureau @ 2026-07-17 11:52 UTC (permalink / raw)
To: qemu-devel
From: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
VIRTIO_GPU_CMD_SET_SCANOUT_BLOB supplies a guest-controlled uint32_t
stride, but some downstream consumers take it as int. They may interpret
a value greater than INT_MAX as negative and cause issues:
- pixman_image_create_bits() takes the stride as int, and Pixman may
later access memory before the blob buffer.
- eglCreateImageKHR() also takes the stride as EGLint when importing the
DMA-BUF, and Mesa rejects it.
Reject such strides before scanout.
The check in virtio_gpu_scanout_blob_to_fb() rejects unsupported blob
configurations early. The check added in virtio_gpu_do_set_scanout()
covers migration post_load.
Fixes: 32db3c63ae11 ("virtio-gpu: Add virtio_gpu_set_scanout_blob")
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260717-int-v1-1-8aa05e1791a0@rsg.ci.i.u-tokyo.ac.jp>
---
hw/display/virtio-gpu.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 048b151872e..3090edf89a8 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -654,6 +654,14 @@ static bool virtio_gpu_do_set_scanout(VirtIOGPU *g,
return false;
}
+ if (fb->stride > INT_MAX) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: stride is %" PRIu32
+ ", larger than the supported maximum (%d)\n",
+ __func__, fb->stride, INT_MAX);
+ *error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+ return false;
+ }
+
g->parent_obj.enable = 1;
if (res->blob) {
@@ -769,6 +777,13 @@ bool virtio_gpu_scanout_blob_to_fb(struct virtio_gpu_framebuffer *fb,
return false;
}
+ if (fb->stride > INT_MAX) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: stride is %" PRIu32
+ ", larger than the supported maximum (%d)\n",
+ __func__, fb->stride, INT_MAX);
+ return false;
+ }
+
fb->offset = ss->offsets[0] + ss->r.x * fb->bytes_pp + ss->r.y * fb->stride;
fbend = fb->offset;
--
2.55.0
^ permalink raw reply related [flat|nested] 26+ messages in thread* [GIT PULL 15/15] hw/display/virtio-gpu: Check pixman_image_create_bits() results
2026-07-17 11:52 [GIT PULL 00/15] Various UI/security-related fixes for 11.1 Marc-André Lureau
` (13 preceding siblings ...)
2026-07-17 11:52 ` [GIT PULL 14/15] hw/display/virtio-gpu: reject strides exceeding INT_MAX Marc-André Lureau
@ 2026-07-17 11:52 ` Marc-André Lureau
2026-07-19 7:31 ` [GIT PULL 00/15] Various UI/security-related fixes for 11.1 Michael Tokarev
` (3 subsequent siblings)
18 siblings, 0 replies; 26+ messages in thread
From: Marc-André Lureau @ 2026-07-17 11:52 UTC (permalink / raw)
To: qemu-devel
From: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
pixman_image_create_bits() returns NULL for allocation failures and
unaligned strides, which may be supplied by the guest with
VIRTIO_GPU_CMD_SET_SCANOUT_BLOB, and virtio_gpu_do_set_scanout()
subsequently dereferences it.
Fixes: fa06e5cb7b10 ("virtio-gpu: fix scanout rectangles")
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260717-pixman-v1-1-89ea33b50b75@rsg.ci.i.u-tokyo.ac.jp>
---
hw/display/virtio-gpu.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 3090edf89a8..718ba303929 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -690,6 +690,10 @@ static bool virtio_gpu_do_set_scanout(VirtIOGPU *g,
void *ptr = data + fb->offset;
rect = pixman_image_create_bits(fb->format, r->width, r->height,
ptr, fb->stride);
+ if (!rect) {
+ *error = VIRTIO_GPU_RESP_ERR_UNSPEC;
+ return false;
+ }
if (res->image) {
pixman_image_ref(res->image);
--
2.55.0
^ permalink raw reply related [flat|nested] 26+ messages in thread* Re: [GIT PULL 00/15] Various UI/security-related fixes for 11.1
2026-07-17 11:52 [GIT PULL 00/15] Various UI/security-related fixes for 11.1 Marc-André Lureau
` (14 preceding siblings ...)
2026-07-17 11:52 ` [GIT PULL 15/15] hw/display/virtio-gpu: Check pixman_image_create_bits() results Marc-André Lureau
@ 2026-07-19 7:31 ` Michael Tokarev
2026-07-19 7:33 ` Michael Tokarev
` (2 subsequent siblings)
18 siblings, 0 replies; 26+ messages in thread
From: Michael Tokarev @ 2026-07-19 7:31 UTC (permalink / raw)
To: Marc-André Lureau, qemu-devel; +Cc: qemu-stable, Akihiko Odaki
On 7/17/26 14:52, Marc-André Lureau wrote:
> Various UI/security-related fixes for 11.1
>
> ----------------------------------------------------------------
> Akihiko Odaki (3):
> ui/gtk: Narrow DMA-BUF critical section
> hw/display/virtio-gpu: reject strides exceeding INT_MAX
> hw/display/virtio-gpu: Check pixman_image_create_bits() results
>
> Marc-André Lureau (12):
> i386/tdx: fix uninitialized variable warning in tdx_check_features
> ui/vnc: fix OOB write in vnc_refresh_lossy_rect
> ui/vnc: validate color shifts in SetPixelFormat
> ui/vnc: use RFB wire types for client message handlers
> ui/input-barrier: fix off-by-one in keycode bounds check
> ui/vnc: fix out-of-bounds write in lossy refresh dirty marking
> ui/vnc: validate SetPixelFormat field ranges
> hw/display/virtio-gpu: fix dmabuf_fd leak on remap failure
> hw/display/qxl: fix TOCTOU in cursor chunk data_size handling
> hw/display/virtio-gpu: validate stride against width on scanout
> hw/display/virtio-gpu: cap submit_3d command buffer allocation
> hw/display/virtio-gpu: handle migration iov allocation failure
Hi!
Is there anything in there which should *not* go
to the stable qemu series?
(besides fixes for code which is not in releases, if any)
It feels like everything in this pullreq should be picked up
for qemu-stable.
Thanks,
/mjt
> contrib/vhost-user-gpu/vugpu.h | 9 ++++++
> include/hw/virtio/virtio-gpu.h | 9 ++++++
> contrib/vhost-user-gpu/virgl.c | 7 +++++
> hw/display/qxl-render.c | 28 ++++++++++-------
> hw/display/virtio-gpu-rutabaga.c | 8 +++++
> hw/display/virtio-gpu-udmabuf.c | 1 +
> hw/display/virtio-gpu-virgl.c | 8 +++++
> hw/display/virtio-gpu.c | 57 ++++++++++++++++++++++++++++++++---
> target/i386/kvm/tdx.c | 2 +-
> ui/gtk-egl.c | 6 ++--
> ui/gtk-gl-area.c | 23 +-------------
> ui/input-barrier.c | 2 +-
> ui/vnc.c | 65 ++++++++++++++++++++++++----------------
> 13 files changed, 157 insertions(+), 68 deletions(-)
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [GIT PULL 00/15] Various UI/security-related fixes for 11.1
2026-07-17 11:52 [GIT PULL 00/15] Various UI/security-related fixes for 11.1 Marc-André Lureau
` (15 preceding siblings ...)
2026-07-19 7:31 ` [GIT PULL 00/15] Various UI/security-related fixes for 11.1 Michael Tokarev
@ 2026-07-19 7:33 ` Michael Tokarev
2026-07-19 7:50 ` Akihiko Odaki
2026-07-20 9:59 ` Stefan Hajnoczi
2026-07-20 11:27 ` Michael Tokarev
18 siblings, 1 reply; 26+ messages in thread
From: Michael Tokarev @ 2026-07-19 7:33 UTC (permalink / raw)
To: Marc-André Lureau, qemu-devel; +Cc: qemu-stable, Akihiko Odaki
[Resending with the correct email of Akihiko Odaki, please excuse the duplicate]
On 7/17/26 14:52, Marc-André Lureau wrote:
> Various UI/security-related fixes for 11.1
>
> ----------------------------------------------------------------
> Akihiko Odaki (3):
> ui/gtk: Narrow DMA-BUF critical section
> hw/display/virtio-gpu: reject strides exceeding INT_MAX
> hw/display/virtio-gpu: Check pixman_image_create_bits() results
>
> Marc-André Lureau (12):
> i386/tdx: fix uninitialized variable warning in tdx_check_features
> ui/vnc: fix OOB write in vnc_refresh_lossy_rect
> ui/vnc: validate color shifts in SetPixelFormat
> ui/vnc: use RFB wire types for client message handlers
> ui/input-barrier: fix off-by-one in keycode bounds check
> ui/vnc: fix out-of-bounds write in lossy refresh dirty marking
> ui/vnc: validate SetPixelFormat field ranges
> hw/display/virtio-gpu: fix dmabuf_fd leak on remap failure
> hw/display/qxl: fix TOCTOU in cursor chunk data_size handling
> hw/display/virtio-gpu: validate stride against width on scanout
> hw/display/virtio-gpu: cap submit_3d command buffer allocation
> hw/display/virtio-gpu: handle migration iov allocation failure
Hi!
Is there anything in there which should *not* go
to the stable qemu series?
(besides fixes for code which is not in releases, if any)
It feels like everything in this pullreq should be picked up
for qemu-stable.
Thanks,
/mjt
> contrib/vhost-user-gpu/vugpu.h | 9 ++++++
> include/hw/virtio/virtio-gpu.h | 9 ++++++
> contrib/vhost-user-gpu/virgl.c | 7 +++++
> hw/display/qxl-render.c | 28 ++++++++++-------
> hw/display/virtio-gpu-rutabaga.c | 8 +++++
> hw/display/virtio-gpu-udmabuf.c | 1 +
> hw/display/virtio-gpu-virgl.c | 8 +++++
> hw/display/virtio-gpu.c | 57 ++++++++++++++++++++++++++++++++---
> target/i386/kvm/tdx.c | 2 +-
> ui/gtk-egl.c | 6 ++--
> ui/gtk-gl-area.c | 23 +-------------
> ui/input-barrier.c | 2 +-
> ui/vnc.c | 65 ++++++++++++++++++++++++----------------
> 13 files changed, 157 insertions(+), 68 deletions(-)
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [GIT PULL 00/15] Various UI/security-related fixes for 11.1
2026-07-19 7:33 ` Michael Tokarev
@ 2026-07-19 7:50 ` Akihiko Odaki
2026-07-19 8:07 ` Marc-André Lureau
0 siblings, 1 reply; 26+ messages in thread
From: Akihiko Odaki @ 2026-07-19 7:50 UTC (permalink / raw)
To: Michael Tokarev, Marc-André Lureau, qemu-devel; +Cc: qemu-stable
On 2026/07/19 16:33, Michael Tokarev wrote:
> [Resending with the correct email of Akihiko Odaki, please excuse the
> duplicate]
>
> On 7/17/26 14:52, Marc-André Lureau wrote:
>
>> Various UI/security-related fixes for 11.1
>>
>> ----------------------------------------------------------------
>> Akihiko Odaki (3):
>> ui/gtk: Narrow DMA-BUF critical section
>> hw/display/virtio-gpu: reject strides exceeding INT_MAX
>> hw/display/virtio-gpu: Check pixman_image_create_bits() results
>>
>> Marc-André Lureau (12):
>> i386/tdx: fix uninitialized variable warning in tdx_check_features
>> ui/vnc: fix OOB write in vnc_refresh_lossy_rect
>> ui/vnc: validate color shifts in SetPixelFormat
>> ui/vnc: use RFB wire types for client message handlers
>> ui/input-barrier: fix off-by-one in keycode bounds check
>> ui/vnc: fix out-of-bounds write in lossy refresh dirty marking
>> ui/vnc: validate SetPixelFormat field ranges
>> hw/display/virtio-gpu: fix dmabuf_fd leak on remap failure
>> hw/display/qxl: fix TOCTOU in cursor chunk data_size handling
>> hw/display/virtio-gpu: validate stride against width on scanout
>> hw/display/virtio-gpu: cap submit_3d command buffer allocation
>> hw/display/virtio-gpu: handle migration iov allocation failure
>
> Hi!
Hi Michael, Marc-André,
>
> Is there anything in there which should *not* go
> to the stable qemu series?
> (besides fixes for code which is not in releases, if any)
>
> It feels like everything in this pullreq should be picked up
> for qemu-stable.
The hw/display/virtio-gpu patches are generally good for stable, with
one exception:
"hw/display/virtio-gpu: validate stride against width on scanout"
This patch doesn't account for the late feedback I sent here:
https://lore.kernel.org/qemu-devel/ec997fca-6dc4-4268-9269-0e4be676b0fb@rsg.ci.i.u-tokyo.ac.jp/
Marc-André: My apologies for the timing, but please check the linked
thread.
Michael: You may holding off on that specific patch for qemu-stable
until we clear up that edge case, but at least it's not harmful. I think
my patches and the other virtio-gpu patches are ready.
Regards,
Akihiko Odaki
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [GIT PULL 00/15] Various UI/security-related fixes for 11.1
2026-07-19 7:50 ` Akihiko Odaki
@ 2026-07-19 8:07 ` Marc-André Lureau
2026-07-19 11:41 ` Akihiko Odaki
0 siblings, 1 reply; 26+ messages in thread
From: Marc-André Lureau @ 2026-07-19 8:07 UTC (permalink / raw)
To: Akihiko Odaki; +Cc: Michael Tokarev, qemu-devel, qemu-stable
Hi
On Sun, Jul 19, 2026 at 11:51 AM Akihiko Odaki
<odaki@rsg.ci.i.u-tokyo.ac.jp> wrote:
>
> On 2026/07/19 16:33, Michael Tokarev wrote:
> > [Resending with the correct email of Akihiko Odaki, please excuse the
> > duplicate]
> >
> > On 7/17/26 14:52, Marc-André Lureau wrote:
> >
> >> Various UI/security-related fixes for 11.1
> >>
> >> ----------------------------------------------------------------
> >> Akihiko Odaki (3):
> >> ui/gtk: Narrow DMA-BUF critical section
> >> hw/display/virtio-gpu: reject strides exceeding INT_MAX
> >> hw/display/virtio-gpu: Check pixman_image_create_bits() results
> >>
> >> Marc-André Lureau (12):
> >> i386/tdx: fix uninitialized variable warning in tdx_check_features
> >> ui/vnc: fix OOB write in vnc_refresh_lossy_rect
> >> ui/vnc: validate color shifts in SetPixelFormat
> >> ui/vnc: use RFB wire types for client message handlers
> >> ui/input-barrier: fix off-by-one in keycode bounds check
> >> ui/vnc: fix out-of-bounds write in lossy refresh dirty marking
> >> ui/vnc: validate SetPixelFormat field ranges
> >> hw/display/virtio-gpu: fix dmabuf_fd leak on remap failure
> >> hw/display/qxl: fix TOCTOU in cursor chunk data_size handling
> >> hw/display/virtio-gpu: validate stride against width on scanout
> >> hw/display/virtio-gpu: cap submit_3d command buffer allocation
> >> hw/display/virtio-gpu: handle migration iov allocation failure
> >
> > Hi!
>
> Hi Michael, Marc-André,
>
> >
> > Is there anything in there which should *not* go
> > to the stable qemu series?
> > (besides fixes for code which is not in releases, if any)
> >
> > It feels like everything in this pullreq should be picked up
> > for qemu-stable.
>
> The hw/display/virtio-gpu patches are generally good for stable, with
> one exception:
>
> "hw/display/virtio-gpu: validate stride against width on scanout"
>
> This patch doesn't account for the late feedback I sent here:
> https://lore.kernel.org/qemu-devel/ec997fca-6dc4-4268-9269-0e4be676b0fb@rsg.ci.i.u-tokyo.ac.jp/
>
> Marc-André: My apologies for the timing, but please check the linked
> thread.
>
Tampering with migration stream is still being discussed, in the
meantime the patch fixes malicious guest gpu usage. Can you send a
follow up patch?
> Michael: You may holding off on that specific patch for qemu-stable
> until we clear up that edge case, but at least it's not harmful. I think
> my patches and the other virtio-gpu patches are ready.
>
> Regards,
> Akihiko Odaki
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [GIT PULL 00/15] Various UI/security-related fixes for 11.1
2026-07-19 8:07 ` Marc-André Lureau
@ 2026-07-19 11:41 ` Akihiko Odaki
0 siblings, 0 replies; 26+ messages in thread
From: Akihiko Odaki @ 2026-07-19 11:41 UTC (permalink / raw)
To: Michael Tokarev, Marc-André Lureau; +Cc: qemu-devel, qemu-stable
On 2026/07/19 17:07, Marc-André Lureau wrote:
> Hi
>
> On Sun, Jul 19, 2026 at 11:51 AM Akihiko Odaki
> <odaki@rsg.ci.i.u-tokyo.ac.jp> wrote:
>>
>> On 2026/07/19 16:33, Michael Tokarev wrote:
>>> [Resending with the correct email of Akihiko Odaki, please excuse the
>>> duplicate]
>>>
>>> On 7/17/26 14:52, Marc-André Lureau wrote:
>>>
>>>> Various UI/security-related fixes for 11.1
>>>>
>>>> ----------------------------------------------------------------
>>>> Akihiko Odaki (3):
>>>> ui/gtk: Narrow DMA-BUF critical section
>>>> hw/display/virtio-gpu: reject strides exceeding INT_MAX
>>>> hw/display/virtio-gpu: Check pixman_image_create_bits() results
>>>>
>>>> Marc-André Lureau (12):
>>>> i386/tdx: fix uninitialized variable warning in tdx_check_features
>>>> ui/vnc: fix OOB write in vnc_refresh_lossy_rect
>>>> ui/vnc: validate color shifts in SetPixelFormat
>>>> ui/vnc: use RFB wire types for client message handlers
>>>> ui/input-barrier: fix off-by-one in keycode bounds check
>>>> ui/vnc: fix out-of-bounds write in lossy refresh dirty marking
>>>> ui/vnc: validate SetPixelFormat field ranges
>>>> hw/display/virtio-gpu: fix dmabuf_fd leak on remap failure
>>>> hw/display/qxl: fix TOCTOU in cursor chunk data_size handling
>>>> hw/display/virtio-gpu: validate stride against width on scanout
>>>> hw/display/virtio-gpu: cap submit_3d command buffer allocation
>>>> hw/display/virtio-gpu: handle migration iov allocation failure
>>>
>>> Hi!
>>
>> Hi Michael, Marc-André,
>>
>>>
>>> Is there anything in there which should *not* go
>>> to the stable qemu series?
>>> (besides fixes for code which is not in releases, if any)
>>>
>>> It feels like everything in this pullreq should be picked up
>>> for qemu-stable.
>>
>> The hw/display/virtio-gpu patches are generally good for stable, with
>> one exception:
>>
>> "hw/display/virtio-gpu: validate stride against width on scanout"
>>
>> This patch doesn't account for the late feedback I sent here:
>> https://lore.kernel.org/qemu-devel/ec997fca-6dc4-4268-9269-0e4be676b0fb@rsg.ci.i.u-tokyo.ac.jp/
>>
>> Marc-André: My apologies for the timing, but please check the linked
>> thread.
>>
>
> Tampering with migration stream is still being discussed, in the
> meantime the patch fixes malicious guest gpu usage. Can you send a
> follow up patch?
I sent one:
https://lore.kernel.org/qemu-devel/20260719-bpp-v1-1-9b91946d6cf3@rsg.ci.i.u-tokyo.ac.jp/
("[PATCH] hw/display/virtio-gpu: Remove the bytes_pp field")
>
>> Michael: You may holding off on that specific patch for qemu-stable
>> until we clear up that edge case, but at least it's not harmful. I think
>> my patches and the other virtio-gpu patches are ready.
One correction: we need to apply "hw/display/virtio-gpu: validate stride
against width on scanout" and the follow up patch at the same time.
Otherwise we will have a user of the bytes_pp field, which the follow up
patch drops.
Regards,
Akihiko Odaki
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [GIT PULL 00/15] Various UI/security-related fixes for 11.1
2026-07-17 11:52 [GIT PULL 00/15] Various UI/security-related fixes for 11.1 Marc-André Lureau
` (16 preceding siblings ...)
2026-07-19 7:33 ` Michael Tokarev
@ 2026-07-20 9:59 ` Stefan Hajnoczi
2026-07-20 11:27 ` Michael Tokarev
18 siblings, 0 replies; 26+ messages in thread
From: Stefan Hajnoczi @ 2026-07-20 9:59 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel
[-- 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] 26+ messages in thread* Re: [GIT PULL 00/15] Various UI/security-related fixes for 11.1
2026-07-17 11:52 [GIT PULL 00/15] Various UI/security-related fixes for 11.1 Marc-André Lureau
` (17 preceding siblings ...)
2026-07-20 9:59 ` Stefan Hajnoczi
@ 2026-07-20 11:27 ` Michael Tokarev
18 siblings, 0 replies; 26+ messages in thread
From: Michael Tokarev @ 2026-07-20 11:27 UTC (permalink / raw)
To: Marc-André Lureau, qemu-devel; +Cc: QEMU Stable
On 7/17/26 14:52, Marc-André Lureau wrote:
...
> Akihiko Odaki (3):
> ui/gtk: Narrow DMA-BUF critical section
> hw/display/virtio-gpu: reject strides exceeding INT_MAX
> hw/display/virtio-gpu: Check pixman_image_create_bits() results
>
> Marc-André Lureau (12):
> i386/tdx: fix uninitialized variable warning in tdx_check_features
> ui/vnc: fix OOB write in vnc_refresh_lossy_rect
> ui/vnc: validate color shifts in SetPixelFormat
> ui/vnc: use RFB wire types for client message handlers
> ui/input-barrier: fix off-by-one in keycode bounds check
> ui/vnc: fix out-of-bounds write in lossy refresh dirty marking
> ui/vnc: validate SetPixelFormat field ranges
> hw/display/virtio-gpu: fix dmabuf_fd leak on remap failure
> hw/display/qxl: fix TOCTOU in cursor chunk data_size handling
> hw/display/virtio-gpu: validate stride against width on scanout
> hw/display/virtio-gpu: cap submit_3d command buffer allocation
> hw/display/virtio-gpu: handle migration iov allocation failure
From this batch, I'm NOT picking up for stable:
i386/tdx: fix uninitialized variable warning in tdx_check_features
ui/vnc: use RFB wire types for client message handlers
(this one I'm not certain, maybe I should pick it up too)
queued, waiting for an addiitonal fix to land:
hw/display/virtio-gpu: validate stride against width on scanout
(as discussed)
hw/display/virtio-gpu: reject strides exceeding INT_MAX
(context depends on the previous one)
the rest are queued up for 10.0.x and 11.0.x.
BTW, a few of them, namely:
hw/display/qxl: fix TOCTOU in cursor chunk data_size handling
hw/display/virtio-gpu: fix dmabuf_fd leak on remap failure
has already been merged through misc tree.
Thanks,
/mjt
^ permalink raw reply [flat|nested] 26+ messages in thread