all lists on 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal