public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Fiona Ebner <f.ebner@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH qemu v2 3/7] add more stable fixes for QEMU 11.1.1
Date: Wed,  9 Sep 2026 16:52:13 +0200	[thread overview]
Message-ID: <20260909145252.454610-4-f.ebner@proxmox.com> (raw)
In-Reply-To: <20260909145252.454610-1-f.ebner@proxmox.com>

Cherry pick from upstream master:
- vga display: fix possible OOB write
- scsi: fix possible OOB read
- vapic: fix potential memory region overlap
- socket iochannel: correctly handle zero-length write

Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---

New in v2.

 ...ix-text-mode-OOB-write-after-a-graph.patch | 164 ++++++++++++++++++
 ...-fix-out-of-bound-read-in-WRITE-SAME.patch |  71 ++++++++
 ...ELECT-block-size-change-behind-a-qui.patch |  89 ++++++++++
 ...-the-VAPIC-region-to-0xc0000.0xe0000.patch |  75 ++++++++
 ...-MemoryRegion-if-vapic_map_rom_writa.patch |  36 ++++
 ...t-do-not-treat-a-zero-length-write-a.patch |  54 ++++++
 debian/patches/series                         |   6 +
 7 files changed, 495 insertions(+)
 create mode 100644 debian/patches/extra/0006-hw-display-vga-fix-text-mode-OOB-write-after-a-graph.patch
 create mode 100644 debian/patches/extra/0007-scsi-disk-fix-out-of-bound-read-in-WRITE-SAME.patch
 create mode 100644 debian/patches/extra/0008-scsi-hide-MODE-SELECT-block-size-change-behind-a-qui.patch
 create mode 100644 debian/patches/extra/0009-vapic-confine-the-VAPIC-region-to-0xc0000.0xe0000.patch
 create mode 100644 debian/patches/extra/0010-i386-vapic-unref-MemoryRegion-if-vapic_map_rom_writa.patch
 create mode 100644 debian/patches/extra/0011-io-channel-socket-do-not-treat-a-zero-length-write-a.patch

diff --git a/debian/patches/extra/0006-hw-display-vga-fix-text-mode-OOB-write-after-a-graph.patch b/debian/patches/extra/0006-hw-display-vga-fix-text-mode-OOB-write-after-a-graph.patch
new file mode 100644
index 0000000000..9c7c7f6d32
--- /dev/null
+++ b/debian/patches/extra/0006-hw-display-vga-fix-text-mode-OOB-write-after-a-graph.patch
@@ -0,0 +1,164 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Warisjeet Singh <sinxx198@gmail.com>
+Date: Mon, 24 Aug 2026 12:47:26 -0400
+Subject: [PATCH] hw/display/vga: fix text-mode OOB write after a graphics
+ surface switch
+
+vga_draw_text() decides whether the console surface needs a resize from
+its geometry cache, but none of the cache terms observe the graphics
+renderer having replaced the console surface in between:
+
+- last_width/last_height are shared with vga_draw_graphic(), which
+  stores them in pixels while the text path stores characters;
+- last_depth stays 0 for legacy (non-VBE) graphics modes, because
+  vga_get_bpp() only reports a depth when VBE is enabled, so the
+  "s->last_depth" term that normally forces a resize after a graphics
+  frame does not fire.
+
+So a graphics frame that shrinks the console surface (e.g. 80x25
+pixels) followed by a text frame with matching character geometry
+(80x25 chars) skips the resize, and the glyph loop then paints
+width*cw x height*cheight pixels into the smaller surface, out of
+bounds, with guest-controlled (DAC palette) values, on every display
+refresh.
+
+Separate the geometry cache per renderer: text paths (vga_draw_text,
+vga_update_text, and the text handling in vga_invalidate_display /
+vga_common_reset) now only manipulate last_text_{width,height}, in
+characters; last_{width,height} become graphics-only, in pixels.
+Additionally, make the text path compare the pixel size it is about
+to paint against the console surface's actual dimensions.  The
+surface check is the load-bearing term: caches in either unit cannot
+see the other renderer swapping the surface, the surface can.
+
+Fixes: CVE-2026-77913
+Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4215
+Cc: qemu-stable@nongnu.org
+Signed-off-by: Warisjeet Singh (sin99xx) <sinxx198@gmail.com>
+Message-ID: <vga-v3-20260824.sinxx198@gmail.com>
+(cherry picked from commit 418396be8013386a81f8d8d89ac0effcf03a64b6)
+Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
+---
+ hw/display/vga.c     | 37 ++++++++++++++++++++++---------------
+ hw/display/vga_int.h |  3 ++-
+ 2 files changed, 24 insertions(+), 16 deletions(-)
+
+diff --git a/hw/display/vga.c b/hw/display/vga.c
+index da0c331486..cb0e28b79b 100644
+--- a/hw/display/vga.c
++++ b/hw/display/vga.c
+@@ -1241,7 +1241,10 @@ static void vga_draw_text(VGACommonState *s, int full_update)
+         return;
+     }
+ 
+-    if (width != s->last_width || height != s->last_height ||
++    if (surface == NULL ||
++        surface_width(surface) != width * cw ||
++        surface_height(surface) != height * cheight ||
++        width != s->last_text_width || height != s->last_text_height ||
+         cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
+         s->last_scr_width = width * cw;
+         s->last_scr_height = height * cheight;
+@@ -1249,8 +1252,8 @@ static void vga_draw_text(VGACommonState *s, int full_update)
+         surface = qemu_console_surface(s->con);
+         qemu_console_text_resize(s->con, width, height);
+         s->last_depth = 0;
+-        s->last_width = width;
+-        s->last_height = height;
++        s->last_text_width = width;
++        s->last_text_height = height;
+         s->last_ch = cheight;
+         s->last_cw = cw;
+         full_update = 1;
+@@ -1845,6 +1848,8 @@ static void vga_invalidate_display(void *opaque)
+ 
+     s->last_width = -1;
+     s->last_height = -1;
++    s->last_text_width = -1;
++    s->last_text_height = -1;
+ }
+ 
+ void vga_common_reset(VGACommonState *s)
+@@ -1887,6 +1892,8 @@ void vga_common_reset(VGACommonState *s)
+     s->last_ch = 0;
+     s->last_width = 0;
+     s->last_height = 0;
++    s->last_text_width = 0;
++    s->last_text_height = 0;
+     s->last_scr_width = 0;
+     s->last_scr_height = 0;
+     s->cursor_start = 0;
+@@ -1938,8 +1945,8 @@ static void vga_update_text(void *opaque, uint32_t *chardata)
+         s->graphic_mode = graphic_mode;
+         full_update = 1;
+     }
+-    if (s->last_width == -1) {
+-        s->last_width = 0;
++    if (s->last_text_width == -1) {
++        s->last_text_width = 0;
+         full_update = 1;
+     }
+ 
+@@ -1978,15 +1985,15 @@ static void vga_update_text(void *opaque, uint32_t *chardata)
+             break;
+         }
+ 
+-        if (width != s->last_width || height != s->last_height ||
++        if (width != s->last_text_width || height != s->last_text_height ||
+             cw != s->last_cw || cheight != s->last_ch) {
+             s->last_scr_width = width * cw;
+             s->last_scr_height = height * cheight;
+             qemu_console_resize(s->con, s->last_scr_width, s->last_scr_height);
+             qemu_console_text_resize(s->con, width, height);
+             s->last_depth = 0;
+-            s->last_width = width;
+-            s->last_height = height;
++            s->last_text_width = width;
++            s->last_text_height = height;
+             s->last_ch = cheight;
+             s->last_cw = cw;
+             full_update = 1;
+@@ -2071,22 +2078,22 @@ static void vga_update_text(void *opaque, uint32_t *chardata)
+     }
+ 
+     /* Display a message */
+-    s->last_width = 60;
+-    s->last_height = height = 3;
++    s->last_text_width = 60;
++    s->last_text_height = height = 3;
+     qemu_console_text_set_cursor(s->con, -1, -1);
+-    qemu_console_text_resize(s->con, s->last_width, height);
++    qemu_console_text_resize(s->con, s->last_text_width, height);
+ 
+-    for (dst = chardata, i = 0; i < s->last_width * height; i ++)
++    for (dst = chardata, i = 0; i < s->last_text_width * height; i ++)
+         *dst++ = ' ';
+ 
+     size = strlen(msg_buffer);
+-    width = (s->last_width - size) / 2;
+-    dst = chardata + s->last_width + width;
++    width = (s->last_text_width - size) / 2;
++    dst = chardata + s->last_text_width + width;
+     for (i = 0; i < size; i ++)
+         *dst++ = ATTR2CHTYPE(msg_buffer[i], QEMU_COLOR_BLUE,
+                              QEMU_COLOR_BLACK, 1);
+ 
+-    qemu_console_text_update(s->con, 0, 0, s->last_width, height);
++    qemu_console_text_update(s->con, 0, 0, s->last_text_width, height);
+ }
+ 
+ static uint64_t vga_mem_read(void *opaque, hwaddr addr,
+diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h
+index 5664317ecd..ca69ae9815 100644
+--- a/hw/display/vga_int.h
++++ b/hw/display/vga_int.h
+@@ -122,7 +122,8 @@ typedef struct VGACommonState {
+     uint32_t plane_updated;
+     uint32_t last_line_offset;
+     uint8_t last_cw, last_ch;
+-    uint32_t last_width, last_height; /* in chars or pixels */
++    uint32_t last_width, last_height; /* in pixels (graphics renderer) */
++    uint32_t last_text_width, last_text_height; /* in chars (text renderer) */
+     uint32_t last_scr_width, last_scr_height; /* in pixels */
+     uint32_t last_depth; /* in bits */
+     bool last_byteswap;
diff --git a/debian/patches/extra/0007-scsi-disk-fix-out-of-bound-read-in-WRITE-SAME.patch b/debian/patches/extra/0007-scsi-disk-fix-out-of-bound-read-in-WRITE-SAME.patch
new file mode 100644
index 0000000000..ffab5481da
--- /dev/null
+++ b/debian/patches/extra/0007-scsi-disk-fix-out-of-bound-read-in-WRITE-SAME.patch
@@ -0,0 +1,71 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Wed, 26 Aug 2026 19:22:41 +0200
+Subject: [PATCH] scsi-disk: fix out-of-bound read in WRITE SAME
+
+A guest with an attached scsi-hd can force QEMU's SCSI disk emulation
+to read roughly 60 KiB past the end of a heap buffer, copying that out
+of bounds host memory into the guest's own disk image.
+
+WRITE SAME computes the request transfer length at dev->blocksize
+when the request is prepared and sets cmd->xfer from dev->blocksize.
+scsi_disk_emulate_command() then uses cmd->xfer as the size of the
+request buffer.
+
+However, MODE SELECT can race with the WRITE SAME command and guest raise
+the logical block size to any value whose low bits fit 0xfe00, up to 65024.
+In the presence of this race, scsi_disk_emulate_write_same() will read
+from memory as many bytes as indicated by the *new* dev->blocksize,
+and write it to disk.
+
+The read length in WRITE SAME must be bounded by the buffer that was
+actually allocated, not by the mutable s->qdev.blocksize, so clamp the
+length used against inbuf to r->buflen.  Re-validating req->cmd.xfer
+against the current block size would not work because the race is
+intrinsic in the SCSI protocol.
+
+I am not sure if this is exploitable with virtio-scsi and other SG-capable
+HBAs, because it should process the WRITE SAME input immediately,
+without letting the MODE SELECT command race with it.
+
+Fixes: 356c4c441ec ("scsi-disk: allow MODE SELECT block descriptor to set the block size", 2022-07-13)
+Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4365
+Cc: qemu-stable@nongnu.org
+Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry picked from commit d30254aec93141d6b89262986a62764b2ae07177)
+Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
+---
+ hw/scsi/scsi-disk.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
+index 1b0cce128c..5bb7a974d6 100644
+--- a/hw/scsi/scsi-disk.c
++++ b/hw/scsi/scsi-disk.c
+@@ -1911,6 +1911,7 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf)
+     SCSIRequest *req = &r->req;
+     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
+     uint32_t nb_sectors = scsi_data_cdb_xfer(r->req.cmd.buf);
++    uint32_t buflen = MIN(s->qdev.blocksize, r->buflen);
+     WriteSameCBData *data;
+     uint8_t *buf;
+     int i, l;
+@@ -1930,7 +1931,7 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf)
+         return;
+     }
+ 
+-    if ((req->cmd.buf[1] & 0x1) || buffer_is_zero(inbuf, s->qdev.blocksize)) {
++    if ((req->cmd.buf[1] & 0x1) || buffer_is_zero(inbuf, buflen)) {
+         int flags = (req->cmd.buf[1] & 0x8) ? BDRV_REQ_MAY_UNMAP : 0;
+ 
+         /* The request is used as the AIO opaque value, so add a ref.  */
+@@ -1956,7 +1957,7 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf)
+     qemu_iovec_init_external(&data->qiov, &data->iov, 1);
+ 
+     for (i = 0; i < data->iov.iov_len; i += l) {
+-        l = MIN(s->qdev.blocksize, data->iov.iov_len - i);
++        l = MIN(buflen, data->iov.iov_len - i);
+         memcpy(&buf[i], inbuf, l);
+     }
+ 
diff --git a/debian/patches/extra/0008-scsi-hide-MODE-SELECT-block-size-change-behind-a-qui.patch b/debian/patches/extra/0008-scsi-hide-MODE-SELECT-block-size-change-behind-a-qui.patch
new file mode 100644
index 0000000000..28b60a97d2
--- /dev/null
+++ b/debian/patches/extra/0008-scsi-hide-MODE-SELECT-block-size-change-behind-a-qui.patch
@@ -0,0 +1,89 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Wed, 26 Aug 2026 19:53:31 +0200
+Subject: [PATCH] scsi: hide MODE SELECT block size change behind a quirk
+
+This is a dangerous operation in that the block size is not
+protected by a lock, but it can be written concurrently if
+you have a multi-queue virtio-scsi HBA.  Put it behind a quirk
+that is only enabled by the Q800 machine, since the MODE
+SELECT feature was added for A/UX.
+
+Cc: qemu-stable@nongnu.org
+Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry picked from commit 0f410adf6b0dead1f09938054da639954bda3bc1)
+Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
+---
+ hw/m68k/q800.c         |  2 ++
+ hw/scsi/scsi-disk.c    | 12 ++++++++++--
+ include/hw/scsi/scsi.h |  1 +
+ 3 files changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
+index ab64250c47..1ad3f93b29 100644
+--- a/hw/m68k/q800.c
++++ b/hw/m68k/q800.c
+@@ -710,12 +710,14 @@ static void q800_init(Object *obj)
+ 
+ static GlobalProperty hw_compat_q800[] = {
+     { "scsi-hd", "quirk_mode_page_vendor_specific_apple", "on" },
++    { "scsi-hd", "quirk_mode_page_set_block_size", "on" },
+     { "scsi-hd", "vendor", " SEAGATE" },
+     { "scsi-hd", "product", "          ST225N" },
+     { "scsi-hd", "ver", "1.0 " },
+     { "scsi-cd", "quirk_mode_page_apple_vendor", "on" },
+     { "scsi-cd", "quirk_mode_sense_rom_use_dbd", "on" },
+     { "scsi-cd", "quirk_mode_page_vendor_specific_apple", "on" },
++    { "scsi-cd", "quirk_mode_page_set_block_size", "on" },
+     { "scsi-cd", "quirk_mode_page_truncated", "on" },
+     { "scsi-cd", "vendor", "MATSHITA" },
+     { "scsi-cd", "product", "CD-ROM CR-8005" },
+diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
+index 5bb7a974d6..a42f7d8e77 100644
+--- a/hw/scsi/scsi-disk.c
++++ b/hw/scsi/scsi-disk.c
+@@ -1673,8 +1673,12 @@ static void scsi_disk_emulate_mode_select(SCSIDiskReq *r, uint8_t *inbuf)
+         goto invalid_param;
+     }
+ 
+-    /* Allow changing the block size */
+-    if (bd_len) {
++    /*
++     * Allow changing the block size only if the quirk is enabled for it.
++     * Writing s->qdev.blocksize is not thread safe!
++     */
++    if (bd_len && (s->quirks &
++                   (1 << SCSI_DISK_QUIRK_MODE_PAGE_SET_BLOCK_SIZE))) {
+         bs = p[5] << 16 | p[6] << 8 | p[7];
+ 
+         /*
+@@ -3247,6 +3251,8 @@ static const Property scsi_hd_properties[] = {
+     DEFINE_PROP_BIT("quirk_mode_page_vendor_specific_apple", SCSIDiskState,
+                     quirks, SCSI_DISK_QUIRK_MODE_PAGE_VENDOR_SPECIFIC_APPLE,
+                     0),
++    DEFINE_PROP_BIT("quirk_mode_page_set_block_size", SCSIDiskState,
++                    quirks, SCSI_DISK_QUIRK_MODE_PAGE_SET_BLOCK_SIZE, 0),
+     DEFINE_BLOCK_CHS_PROPERTIES(SCSIDiskState, qdev.conf),
+ };
+ 
+@@ -3352,6 +3358,8 @@ static const Property scsi_cd_properties[] = {
+                     0),
+     DEFINE_PROP_BIT("quirk_mode_page_truncated", SCSIDiskState, quirks,
+                     SCSI_DISK_QUIRK_MODE_PAGE_TRUNCATED, 0),
++    DEFINE_PROP_BIT("quirk_mode_page_set_block_size", SCSIDiskState,
++                    quirks, SCSI_DISK_QUIRK_MODE_PAGE_SET_BLOCK_SIZE, 0),
+ };
+ 
+ static void scsi_cd_class_initfn(ObjectClass *klass, const void *data)
+diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
+index c60c6e8810..3eab339b0d 100644
+--- a/include/hw/scsi/scsi.h
++++ b/include/hw/scsi/scsi.h
+@@ -262,5 +262,6 @@ bool scsi_generic_pr_state_preempt(SCSIDevice *s, Error **errp);
+ #define SCSI_DISK_QUIRK_MODE_SENSE_ROM_USE_DBD             1
+ #define SCSI_DISK_QUIRK_MODE_PAGE_VENDOR_SPECIFIC_APPLE    2
+ #define SCSI_DISK_QUIRK_MODE_PAGE_TRUNCATED                3
++#define SCSI_DISK_QUIRK_MODE_PAGE_SET_BLOCK_SIZE           4
+ 
+ #endif
diff --git a/debian/patches/extra/0009-vapic-confine-the-VAPIC-region-to-0xc0000.0xe0000.patch b/debian/patches/extra/0009-vapic-confine-the-VAPIC-region-to-0xc0000.0xe0000.patch
new file mode 100644
index 0000000000..c0b17c6339
--- /dev/null
+++ b/debian/patches/extra/0009-vapic-confine-the-VAPIC-region-to-0xc0000.0xe0000.patch
@@ -0,0 +1,75 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Wed, 26 Aug 2026 20:02:56 +0200
+Subject: [PATCH] vapic: confine the VAPIC region to 0xc0000..0xe0000
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The VAPIC region is mapped as writable RAM, at very high priority,
+above existing memory.  If the guest is allowed to map it everywhere,
+it can overlap PCI BARs or even SMRAM.  Ensure that the whole
+region first in the 128K of low memory that are reserved to
+option ROMs.
+
+Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4206
+Reported-by: Artem Dinaburg <https://gitlab.com/artem35>
+Cc: qemu-stable@nongnu.org
+Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry picked from commit d61c8a6fb7388486353aa267ba0d75b098f16662)
+Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
+---
+ hw/i386/vapic.c | 16 +++++++++++++++-
+ 1 file changed, 15 insertions(+), 1 deletion(-)
+
+diff --git a/hw/i386/vapic.c b/hw/i386/vapic.c
+index 8dd9188d96..9adce17262 100644
+--- a/hw/i386/vapic.c
++++ b/hw/i386/vapic.c
+@@ -34,6 +34,10 @@
+ #define ROM_BLOCK_SIZE          512
+ #define ROM_BLOCK_MASK          (~(ROM_BLOCK_SIZE - 1))
+ 
++/* Option ROM window on PC/Q35 machines; the vapic ROM must live in here. */
++#define OPTION_ROM_START        0xc0000
++#define OPTION_ROM_END          0xe0000
++
+ typedef enum VAPICMode {
+     VAPIC_INACTIVE = 0,
+     VAPIC_ACTIVE   = 1,
+@@ -592,6 +596,14 @@ static int vapic_map_rom_writable(VAPICROMState *s)
+     size_t rom_size;
+     uint8_t *ram;
+ 
++    /*
++     * The VAPIC region should be mapped in place, refuse mapping it
++     * outside of the option ROM window.
++     */
++    if (rom_paddr < OPTION_ROM_START || rom_paddr >= OPTION_ROM_END) {
++        return -1;
++    }
++
+     if (s->rom_mapped_writable) {
+         memory_region_del_subregion(mr, &s->rom);
+         object_unparent(OBJECT(&s->rom));
+@@ -606,9 +618,10 @@ static int vapic_map_rom_writable(VAPICROMState *s)
+     }
+     ram = memory_region_get_ram_ptr(section.mr);
+     rom_size = ram[rom_paddr + 2] * ROM_BLOCK_SIZE;
+-    if (rom_size == 0) {
++    if (rom_size == 0 || rom_size > OPTION_ROM_END - rom_paddr) {
+         return -1;
+     }
++
+     s->rom_size = rom_size;
+ 
+     /* We need to round to avoid creating subpages
+@@ -616,6 +629,7 @@ static int vapic_map_rom_writable(VAPICROMState *s)
+     rom_size += rom_paddr & ~TARGET_PAGE_MASK;
+     rom_paddr &= TARGET_PAGE_MASK;
+     rom_size = TARGET_PAGE_ALIGN(rom_size);
++    assert(rom_paddr >= OPTION_ROM_START && rom_paddr + rom_size <= OPTION_ROM_END);
+ 
+     memory_region_init_alias(&s->rom, OBJECT(s), "kvmvapic-rom", section.mr,
+                              rom_paddr, rom_size);
diff --git a/debian/patches/extra/0010-i386-vapic-unref-MemoryRegion-if-vapic_map_rom_writa.patch b/debian/patches/extra/0010-i386-vapic-unref-MemoryRegion-if-vapic_map_rom_writa.patch
new file mode 100644
index 0000000000..c232e80930
--- /dev/null
+++ b/debian/patches/extra/0010-i386-vapic-unref-MemoryRegion-if-vapic_map_rom_writa.patch
@@ -0,0 +1,36 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Wed, 26 Aug 2026 19:47:32 +0200
+Subject: [PATCH] i386/vapic: unref MemoryRegion if vapic_map_rom_writable
+ fails
+
+memory_region_find returns the memory region with an elevated
+reference count.  Drop the reference count also if the memory
+region cannot be mapped writable.
+
+Cc: qemu-stable@nongnu.org
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+(cherry picked from commit cfa6e2c52ca8f756461fe41f4ce40e61a82fd914)
+Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
+---
+ hw/i386/vapic.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/hw/i386/vapic.c b/hw/i386/vapic.c
+index 9adce17262..5c3911cf9c 100644
+--- a/hw/i386/vapic.c
++++ b/hw/i386/vapic.c
+@@ -614,11 +614,13 @@ static int vapic_map_rom_writable(VAPICROMState *s)
+ 
+     /* read ROM size from RAM region */
+     if (rom_paddr + 2 >= memory_region_size(section.mr)) {
++        memory_region_unref(section.mr);
+         return -1;
+     }
+     ram = memory_region_get_ram_ptr(section.mr);
+     rom_size = ram[rom_paddr + 2] * ROM_BLOCK_SIZE;
+     if (rom_size == 0 || rom_size > OPTION_ROM_END - rom_paddr) {
++        memory_region_unref(section.mr);
+         return -1;
+     }
+ 
diff --git a/debian/patches/extra/0011-io-channel-socket-do-not-treat-a-zero-length-write-a.patch b/debian/patches/extra/0011-io-channel-socket-do-not-treat-a-zero-length-write-a.patch
new file mode 100644
index 0000000000..24834b364c
--- /dev/null
+++ b/debian/patches/extra/0011-io-channel-socket-do-not-treat-a-zero-length-write-a.patch
@@ -0,0 +1,54 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: "Denis V. Lunev" <den@openvz.org>
+Date: Mon, 31 Aug 2026 12:01:46 +0200
+Subject: [PATCH] io/channel-socket: do not treat a zero length write as an
+ error
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+qio_channel_socket_writev() checks "ret <= 0" after sendmsg(). A zero
+length iovec is written successfully and returns 0, so the success
+falls into the errno switch, which acts on whatever the last failing
+syscall left in errno. A stale EAGAIN turns it into
+QIO_CHANNEL_ERR_BLOCK with errp untouched, and a caller which treats
+every negative return as fatal then passes a NULL Error to
+error_get_pretty(). The websocket handshake does exactly that, so an
+unauthenticated client crashes QEMU during the greeting.
+
+Returning 0 is safe for callers which loop until everything is
+written. qio_channel_writev_full_all() has no zero progress guard, but
+iov_copy() yields no entries for a zero length write, so that loop is
+never entered. A connected stream socket returns 0 only when there is
+nothing to send.
+
+The WIN32 implementation in the same file uses "ret < 0".
+
+Fixes: CVE-2026-84788
+Fixes: 559607ea173a ("io: add QIOChannelSocket class")
+Cc: qemu-stable@nongnu.org
+Cc: Daniel P. Berrangé <berrange@redhat.com>
+Cc: Marc-André Lureau <marcandre.lureau@redhat.com>
+Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
+Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
+Signed-off-by: Denis V. Lunev <den@openvz.org>
+Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
+(cherry picked from commit a3de21bfa5d0c33110942d407ff5c7903965d3ad)
+Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
+---
+ io/channel-socket.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/io/channel-socket.c b/io/channel-socket.c
+index 12773b832c..7920cee639 100644
+--- a/io/channel-socket.c
++++ b/io/channel-socket.c
+@@ -667,7 +667,7 @@ static ssize_t qio_channel_socket_writev(QIOChannel *ioc,
+ 
+  retry:
+     ret = sendmsg(sioc->fd, &msg, sflags);
+-    if (ret <= 0) {
++    if (ret < 0) {
+         switch (errno) {
+         case EAGAIN:
+             return QIO_CHANNEL_ERR_BLOCK;
diff --git a/debian/patches/series b/debian/patches/series
index fb7cf89ab3..3bc35489ec 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -3,6 +3,12 @@ extra/0002-fdmon-io_uring-avoid-idle-event-loop-being-accounted.patch
 extra/0003-block-vmdk-tolerate-known-seSparse-reserved1-bit.patch
 extra/0004-hw-display-qxl-validate-primary-surface-stride-again.patch
 extra/0005-hw-scsi-lsi53c895a-gracefully-handle-re-entrant-DMA.patch
+extra/0006-hw-display-vga-fix-text-mode-OOB-write-after-a-graph.patch
+extra/0007-scsi-disk-fix-out-of-bound-read-in-WRITE-SAME.patch
+extra/0008-scsi-hide-MODE-SELECT-block-size-change-behind-a-qui.patch
+extra/0009-vapic-confine-the-VAPIC-region-to-0xc0000.0xe0000.patch
+extra/0010-i386-vapic-unref-MemoryRegion-if-vapic_map_rom_writa.patch
+extra/0011-io-channel-socket-do-not-treat-a-zero-length-write-a.patch
 bitmap-mirror/0001-drive-mirror-add-support-for-sync-bitmap-mode-never.patch
 bitmap-mirror/0002-drive-mirror-add-support-for-conditional-and-always-.patch
 bitmap-mirror/0003-mirror-add-check-for-bitmap-mode-without-bitmap.patch
-- 
2.47.3





  parent reply	other threads:[~2026-09-09 14:53 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-09 14:52 [PATCH-SERIES qemu/qemu-server v2 0/7] QEMU 11.1.1 Fiona Ebner
2026-09-09 14:52 ` [PATCH qemu v2 1/7] update submodule and patches to " Fiona Ebner
2026-09-09 14:52 ` [PATCH qemu v2 2/7] spice: work around broken input cleanup feature in libspice-server1 Fiona Ebner
2026-09-09 14:52 ` Fiona Ebner [this message]
2026-09-09 14:52 ` [PATCH qemu v2 4/7] bump version to 11.1.1-1 Fiona Ebner
2026-09-09 14:52 ` [PATCH qemu-server v2 5/7] test: cfg2cmd: add simple test case using an 11.0 binary Fiona Ebner
2026-09-09 14:52 ` [PATCH qemu-server v2 6/7] monitor: use new QOM syntax on the QEMU commandline for monitor objects Fiona Ebner
2026-09-09 14:52 ` [PATCH qemu-server v2 7/7] d/control: bump versioned build dependency for pve-qemu-kvm Fiona Ebner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260909145252.454610-4-f.ebner@proxmox.com \
    --to=f.ebner@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal