#1149847 trixie-pu: package qemu/1:10.0.14+ds-0+deb13u1

#1149847#5
Date:
2026-10-03 17:19:03 UTC
From:
To:
[ Reason ]
There's a new upstream stable/bugfix release, with a number
of security and correctness fixes.  Security fixes include:
CVE-2026-17588, CVE-2026-93834 (#1149064), CVE-2026-12080,
CVE-2026-66899, CVE-2026-66900, CVE-2026-66020, CVE-2026-84788,
CVE-2026-81627 (#1148473), CVE-2026-77913, CVE-2026-16271.

[ Tests ]
As usual, this release passes upstream testsuite (the bits
which are relevant still, since more and more environments
used in the testing becomes unavailable), and a bunch of
my regular testing VMs, including windows, linux and freebsd.
No regressions are observed.

[ Risks ]
There's relatively small amount of changes this time, and most
of them are easily understandable and verifiable.  I don't
expect much risks from this update.

[ Checklist ]
  [x] *all* changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in (old)stable
  [x] the issue is verified as fixed in unstable

[ Changes ]
The debian/changelog is below, in the debdiff output.
There are two obvious changes in debian/ - the changelog
and a version bump in debian/rules.  The rest are upstream
changes, which might better be viewed as git commits at
https://salsa.debian.org/qemu-team/qemu/-/commits/upstream-10.0
between v10.0.13 (already in debian) and v10.0.14 tags.

Thanks,

/mjt

diff -Nru qemu-10.0.13+ds/debian/changelog qemu-10.0.14+ds/debian/changelog
--- qemu-10.0.13+ds/debian/changelog	2026-08-29 20:55:40.000000000 +0300
+++ qemu-10.0.14+ds/debian/changelog	2026-10-03 20:01:57.000000000 +0300
@@ -1,3 +1,94 @@
+qemu (1:10.0.14+ds-0+deb13u1) trixie; urgency=medium
+
+  * new upstream stable/bugfix release, including multiple security fixes:
+   - Update version for 10.0.14 release
+   - target/sh4: Replace TB_FLAG_GUSA_EXCLUSIVE with CF_STEP_ATOMIC
+   - accel/tcg: Set CF_NOIRQ during cpu_exec_step_atomic
+   - target/i386: Mark MOVNTI as not valid with prefixes 0x66, 0xF2, 0xF3
+   - target/i386: Update FPU tag word for FXCH
+   - target/i386: Update FPU tag word for FSTP
+   - target/i386: Update FPU tag word for FXTRACT's old ST(0)
+   - target/i386: Fix FXCH to unconditionally clear C1
+   - target/ppc: Stop vCPU thread before calling parent_unrealize
+   - tests/qtest/usb-hcd-xhci: test isoch endpoint type mismatch
+   - tests/qtest/usb-hcd-xhci: test isoch pacing with MFINDEX above 2^32
+   - hw/usb/hcd-xhci: don't assert on NAK when retrying an isoch transfer
+   - hw/usb/hcd-xhci: fix interval alignment after MFINDEX passes 2^32
+   - hw/usb/hcd-xhci: Set reentrancy guard in timer functions
+     Closes: CVE-2026-17588
+   - tcg/riscv64: Set vtype before whole-register vector loads
+   - accel/tcg: Fix TLB_MMIO check in tlb_plugin_lookup()
+   - accel/tcg: Use TLB_FORCE_SLOW not TLB_MMIO for system plugins
+   - hw/9pfs: mutate FID path from main thread only
+     Closes: #1149064, CVE-2026-93834
+   - s390x/pci: fix DMA slot leak on I/O TLB entry replacement
+   - linux-user/loongarch64: Detect vector stores in host_signal_write()
+   - linux-user: implement mlock2(2) syscall
+   - linux-user/riscv: honor zicntr=false for base counterCSRs
+   - hw/uefi: add missing uefi_str_is_valid check to uefi_vars_mm_lock_variable
+   - hw/riscv/virt.c: fix aclint soc/mtimer nodename
+   - hw/intc/bcm2835_ic: reject out-of-range FIQ source values
+   - qga: Change effective user/group ID in guest-ssh-* commands
+     Closes: CVE-2026-12080
+   - vhost-user-gpu: validate command buffer size in submit_3d
+   - ui/cursor: make the cursor refcount atomic
+   - hw/display/qxl: hold ssd.lock while replacing ssd.cursor
+   - hw/cxl: fix the CDAT DOE overlapping the Flex Bus DVSEC when sn= is set
+   - virtio-scsi: set dataplane_started to false upon failure
+   - virtio-balloon: fix free-page BH teardown on unrealize
+     Closes: CVE-2026-66899
+   - hw/virtio: reject inverted virtio-iommu IOVA ranges
+   - hw/net/virtio-net: strip trailing padding when caching RSC segment
+     Closes: CVE-2026-66900
+   - hw/net/virtio-net: check packet size before VLAN tag access
+     in receive_filter()
+   - qapi/misc: Fix missed query-iothreads items
+   - hw/cxl: Fix guest-triggerable QEMU exit on reserved interleave ways
+   - virtio-gpu: clear res->blob on mapping cleanup
+   - virtio-gpu: disable blob scanouts on mapping cleanup
+     Closes: CVE-2026-66020
+   - tests/unit: cover blocked IO during the websock handshake
+   - io/channel-websock: do not lose QIO_CHANNEL_ERR_BLOCK while reading
+   - tests/unit: add websock handshake test
+   - io/channel-websock: handle a blocked write during the handshake
+   - io/channel-websock: send an HTTP 400 when the greeting has no space
+   - io/channel-socket: do not treat a zero length write as an error
+     (The above 5 changes) Closes: CVE-2026-84788
+   - hw/sd: sdhci: Accept version 4 enable without UHS-I
+   - target/arm: Make Thumb T1 hint space UNDEF before v6T2
+   - target/arm: Make IT insn undef when not present
+   - target/arm: Make CBZ/CBNZ UNDEF before v6T2
+   - target/arm: Correct reset value of SCTLR for arm926, arm1026
+   - target/arm: fix TTA instruction S bit for IDAU-exempt addresses
+   - i386/vapic: unref MemoryRegion if vapic_map_rom_writable fails
+   - vapic: confine the VAPIC region to 0xc0000..0xe0000
+     Closes: #1148473, CVE-2026-81627
+   - scsi: hide MODE SELECT block size change behind a quirk
+   - scsi-disk: fix out-of-bound read in WRITE SAME
+   - hw/ide: report the default CHS translation in IDENTIFY DEVICE
+   - tests/qtest/ide-test: cover a CHS translation with zero sectors
+   - hw/ide: reject an unsupported CHS translation
+   - s390x/sclp: pv: only copy the original SCCB buffer
+   - tests/qtest: Add seed CSR zero extension test
+   - target/riscv: Fix seed CSR sign extension
+   - target/riscv: tt-ascalon: Enable Zkr extension
+   - dirty-bitmap: fix integer overflow in serialization coverage
+   - block/monitor: allow dropping a bitmap never stored on disk
+   - migration/block-dirty-bitmap: reject bitmap load onto ro node
+   - block/monitor: reject persistent bitmap add on a read-only node
+   - tests/unit/test-blockjob: cover keeping a job paused
+     while a pause is pending
+   - job: keep job paused across overlapping pause requests
+   - hw/input/ps2: answer unknown mouse commands with a resend
+   - hw/display/vga: fix text-mode OOB write after a graphics surface switch
+     Closes: CVE-2026-77913
+   - crypto: fix build against nettle >= 4
+   - virtio-gpu: use g_try_malloc to avoid guest-triggered abort
+   - hw/display/qxl: validate primary surface stride against width
+     Closes: CVE-2026-16271
+
+ -- Michael Tokarev <mjt@tls.msk.ru>  Sat, 03 Oct 2026 20:01:57 +0300
+
 qemu (1:10.0.13+ds-0+deb13u1) trixie; urgency=medium

   * new upstream stable/bugfix release, including multiple security fixes:
diff -Nru qemu-10.0.13+ds/debian/control.mk qemu-10.0.14+ds/debian/control.mk
--- qemu-10.0.13+ds/debian/control.mk	2026-08-29 20:55:40.000000000 +0300
+++ qemu-10.0.14+ds/debian/control.mk	2026-10-02 22:51:51.000000000 +0300
@@ -9,7 +9,7 @@

 # since some files and/or lists differ from version to version,
 # ensure we have the expected qemu version, or else scream loudly
-checked-version := 10.0.13+ds
+checked-version := 10.0.14+ds
 # version of last vdso change for d/control Depends field:
 vdso-version := 1:9.2.0~rc3+ds-1~

diff -Nru qemu-10.0.13+ds/VERSION qemu-10.0.14+ds/VERSION
--- qemu-10.0.13+ds/VERSION	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/VERSION	2026-09-29 03:48:20.000000000 +0300
@@ -1 +1 @@
-10.0.13
+10.0.14
diff -Nru qemu-10.0.13+ds/accel/tcg/cpu-exec.c qemu-10.0.14+ds/accel/tcg/cpu-exec.c
--- qemu-10.0.13+ds/accel/tcg/cpu-exec.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/accel/tcg/cpu-exec.c	2026-09-29 03:48:20.000000000 +0300
@@ -580,7 +580,8 @@
         /* Execute in a serial context. */
         cflags &= ~CF_PARALLEL;
         /* After 1 insn, return and release the exclusive lock. */
-        cflags |= CF_NO_GOTO_TB | CF_NO_GOTO_PTR | 1;
+        cflags |= CF_NO_GOTO_TB | CF_NO_GOTO_PTR |
+                    CF_NOIRQ | CF_STEP_ATOMIC | 1;
         /*
          * No need to check_for_breakpoints here.
          * We only arrive in cpu_exec_step_atomic after beginning execution
diff -Nru qemu-10.0.13+ds/accel/tcg/cputlb.c qemu-10.0.14+ds/accel/tcg/cputlb.c
--- qemu-10.0.13+ds/accel/tcg/cputlb.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/accel/tcg/cputlb.c	2026-09-29 03:48:20.000000000 +0300
@@ -1363,7 +1363,6 @@
     uint64_t tlb_addr = tlb_read_idx(entry, access_type);
     vaddr page_addr = addr & TARGET_PAGE_MASK;
     int flags = TLB_FLAGS_MASK & ~TLB_FORCE_SLOW;
-    bool force_mmio = check_mem_cbs && cpu_plugin_mem_cbs_enabled(cpu);
     CPUTLBEntryFull *full;

     if (!tlb_hit_page(tlb_addr, page_addr)) {
@@ -1393,16 +1392,13 @@

     *pfull = full = &cpu->neg.tlb.d[mmu_idx].fulltlb[index];
     flags |= full->slow_flags[access_type];
-
-    /* Fold all "mmio-like" bits into TLB_MMIO.  This is not RAM.  */
-    if (unlikely(flags & ~(TLB_WATCHPOINT | TLB_NOTDIRTY | TLB_CHECK_ALIGNED))
-        || (access_type != MMU_INST_FETCH && force_mmio)) {
-        *phost = NULL;
-        return TLB_MMIO;
+    if (check_mem_cbs && cpu_plugin_mem_cbs_enabled(cpu)) {
+        flags |= TLB_FORCE_SLOW;
     }

-    /* Everything else is RAM. */
-    *phost = (void *)((uintptr_t)addr + entry->addend);
+    *phost = (flags & ~(TLB_WATCHPOINT | TLB_NOTDIRTY | TLB_CHECK_ALIGNED)
+              ? NULL
+              : (void *)((uintptr_t)addr + entry->addend));
     return flags;
 }

@@ -1587,7 +1583,7 @@
     data->phys_addr = full->phys_addr | (addr & ~TARGET_PAGE_MASK);

     /* We must have an iotlb entry for MMIO */
-    if (tlb_addr & TLB_MMIO) {
+    if (full->slow_flags[access_type] & TLB_MMIO) {
         MemoryRegionSection *section =
             iotlb_to_section(cpu, full->xlat_section & ~TARGET_PAGE_MASK,
                              full->attrs);
diff -Nru qemu-10.0.13+ds/block/dirty-bitmap.c qemu-10.0.14+ds/block/dirty-bitmap.c
--- qemu-10.0.13+ds/block/dirty-bitmap.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/block/dirty-bitmap.c	2026-09-29 03:48:20.000000000 +0300
@@ -612,7 +612,7 @@
                                                   const BdrvDirtyBitmap *bitmap)
 {
     uint64_t granularity = bdrv_dirty_bitmap_granularity(bitmap);
-    uint64_t limit = granularity * (serialized_chunk_size << 3);
+    uint64_t limit = granularity * ((uint64_t)serialized_chunk_size << 3);

     assert(QEMU_IS_ALIGNED(limit,
                            bdrv_dirty_bitmap_serialization_align(bitmap)));
diff -Nru qemu-10.0.13+ds/block/monitor/bitmap-qmp-cmds.c qemu-10.0.14+ds/block/monitor/bitmap-qmp-cmds.c
--- qemu-10.0.13+ds/block/monitor/bitmap-qmp-cmds.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/block/monitor/bitmap-qmp-cmds.c	2026-09-29 03:48:20.000000000 +0300
@@ -125,10 +125,17 @@
         disabled = false;
     }

-    if (persistent &&
-        !bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp))
-    {
-        return;
+    if (persistent) {
+        if (!bdrv_is_writable(bs)) {
+            error_setg(errp, "Cannot add a persistent bitmap to "
+                       "read-only or inactive node '%s'",
+                       bdrv_get_node_name(bs));
+            return;
+        }
+
+        if (!bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp)) {
+            return;
+        }
     }

     bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, errp);
@@ -158,11 +165,11 @@
         return NULL;
     }

-    if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY | BDRV_BITMAP_RO,
-                                errp)) {
+    if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY, errp)) {
         return NULL;
     }

+    /* Dropping a bitmap needs no write access unless it is actually stored. */
     if (bdrv_dirty_bitmap_get_persistence(bitmap) &&
         bdrv_remove_persistent_dirty_bitmap(bs, name, errp) < 0)
     {
diff -Nru qemu-10.0.13+ds/block/qcow2-bitmap.c qemu-10.0.14+ds/block/qcow2-bitmap.c
--- qemu-10.0.13+ds/block/qcow2-bitmap.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/block/qcow2-bitmap.c	2026-09-29 03:48:20.000000000 +0300
@@ -1487,6 +1487,15 @@
         goto out;
     }

+    if (!can_write(bs)) {
+        error_setg(errp, "Cannot remove persistent bitmap '%s': "
+                   "no write access to node '%s'", name,
+                   bdrv_get_node_name(bs));
+        ret = -EACCES;
+        bm = NULL;
+        goto out;
+    }
+
     QSIMPLEQ_REMOVE(bm_list, bm, Qcow2Bitmap, entry);

     ret = update_ext_header_and_dir(bs, bm_list);
diff -Nru qemu-10.0.13+ds/contrib/vhost-user-gpu/vhost-user-gpu.c qemu-10.0.14+ds/contrib/vhost-user-gpu/vhost-user-gpu.c
--- qemu-10.0.13+ds/contrib/vhost-user-gpu/vhost-user-gpu.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/contrib/vhost-user-gpu/vhost-user-gpu.c	2026-09-29 03:48:20.000000000 +0300
@@ -487,7 +487,7 @@
                       struct virtio_gpu_ctrl_command *cmd,
                       struct iovec **iov)
 {
-    struct virtio_gpu_mem_entry *ents;
+    g_autofree struct virtio_gpu_mem_entry *ents = NULL;
     size_t esize, s;
     int i;

@@ -498,17 +498,22 @@
     }

     esize = sizeof(*ents) * ab->nr_entries;
-    ents = g_malloc(esize);
+    ents = g_try_malloc(esize);
+    if (!ents && esize) {
+        return -1;
+    }
     s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
                    sizeof(*ab), ents, esize);
     if (s != esize) {
         g_critical("%s: command data size incorrect %zu vs %zu",
                    __func__, s, esize);
-        g_free(ents);
         return -1;
     }

-    *iov = g_new0(struct iovec, ab->nr_entries);
+    *iov = g_try_new0(struct iovec, ab->nr_entries);
+    if (!*iov && ab->nr_entries) {
+        return -1;
+    }
     for (i = 0; i < ab->nr_entries; i++) {
         uint64_t len = ents[i].length;
         (*iov)[i].iov_len = ents[i].length;
@@ -517,12 +522,10 @@
             g_critical("%s: resource %d element %d",
                        __func__, ab->resource_id, i);
             g_free(*iov);
-            g_free(ents);
             *iov = NULL;
             return -1;
         }
     }
-    g_free(ents);
     return 0;
 }

@@ -828,8 +831,14 @@
                 PIXMAN_FORMAT_BPP(pixman_image_get_format(res->image)) / 8;
             size_t size = width * height * bpp;

-            void *p = g_malloc(VHOST_USER_GPU_HDR_SIZE +
-                               sizeof(VhostUserGpuUpdate) + size);
+            void *p = g_try_malloc(VHOST_USER_GPU_HDR_SIZE +
+                                   sizeof(VhostUserGpuUpdate) + size);
+            if (!p) {
+                pixman_region_fini(®ion);
+                pixman_region_fini(&finalregion);
+                cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
+                break;
+            }
             VhostUserGpuMsg *msg = p;
             msg->request = VHOST_USER_GPU_UPDATE;
             msg->size = sizeof(VhostUserGpuUpdate) + size;
diff -Nru qemu-10.0.13+ds/contrib/vhost-user-gpu/virgl.c qemu-10.0.14+ds/contrib/vhost-user-gpu/virgl.c
--- qemu-10.0.13+ds/contrib/vhost-user-gpu/virgl.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/contrib/vhost-user-gpu/virgl.c	2026-09-29 03:48:20.000000000 +0300
@@ -197,19 +197,27 @@
                     struct virtio_gpu_ctrl_command *cmd)
 {
     struct virtio_gpu_cmd_submit cs;
+    size_t iov_len;
     void *buf;
     size_t s;

     VUGPU_FILL_CMD(cs);

-    if (cs.size > VIRTIO_GPU_MAX_CMD_SUBMIT_SIZE) {
-        g_critical("%s: command buffer too large (%u)",
-                   __func__, cs.size);
+    iov_len = iov_size(cmd->elem.out_sg, cmd->elem.out_num);
+    if (cs.size == 0 || iov_len < sizeof(cs) ||
+        cs.size > iov_len - sizeof(cs) ||
+        cs.size > VIRTIO_GPU_MAX_CMD_SUBMIT_SIZE) {
+        g_critical("%s: size out of range (%u/%zu)",
+                   __func__, cs.size, iov_len);
         cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
         return;
     }

-    buf = g_malloc(cs.size);
+    buf = g_try_malloc(cs.size);
+    if (!buf) {
+        cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
+        return;
+    }
     s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
                    sizeof(cs), buf, cs.size);
     if (s != cs.size) {
diff -Nru qemu-10.0.13+ds/contrib/vhost-user-gpu/vugbm.c qemu-10.0.14+ds/contrib/vhost-user-gpu/vugbm.c
--- qemu-10.0.13+ds/contrib/vhost-user-gpu/vugbm.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/contrib/vhost-user-gpu/vugbm.c	2026-09-29 03:48:20.000000000 +0300
@@ -13,7 +13,10 @@
 static bool
 mem_alloc_bo(struct vugbm_buffer *buf)
 {
-    buf->mmap = g_malloc((uint64_t)buf->width * buf->height * 4);
+    buf->mmap = g_try_malloc((uint64_t)buf->width * buf->height * 4);
+    if (!buf->mmap && buf->width && buf->height) {
+        return false;
+    }
     buf->stride = buf->width * 4;
     return true;
 }
diff -Nru qemu-10.0.13+ds/crypto/hash-nettle.c qemu-10.0.14+ds/crypto/hash-nettle.c
--- qemu-10.0.13+ds/crypto/hash-nettle.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/crypto/hash-nettle.c	2026-09-29 03:48:20.000000000 +0300
@@ -24,7 +24,8 @@
 #include "crypto/hash.h"
 #include "hashpriv.h"
 #include <nettle/md5.h>
-#include <nettle/sha.h>
+#include <nettle/sha1.h>
+#include <nettle/sha2.h>
 #include <nettle/ripemd160.h>
 #ifdef CONFIG_CRYPTO_SM3
 #include <nettle/sm3.h>
diff -Nru qemu-10.0.13+ds/hw/9pfs/cofile.c qemu-10.0.14+ds/hw/9pfs/cofile.c
--- qemu-10.0.13+ds/hw/9pfs/cofile.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/9pfs/cofile.c	2026-09-29 03:48:20.000000000 +0300
@@ -143,10 +143,11 @@
     cred.fc_mode = mode & 07777;
     cred.fc_uid = fidp->uid;
     cred.fc_gid = gid;
+    v9fs_path_init(&path);
     /*
      * Hold the directory fid lock so that directory path name
-     * don't change. Take the write lock to be sure this fid
-     * cannot be used by another operation.
+     * don't change. Take the write lock since the fid path is
+     * mutated below on success.
      */
     v9fs_path_write_lock(s);
     v9fs_co_run_in_worker(
@@ -156,23 +157,30 @@
             if (err < 0) {
                 err = -errno;
             } else {
-                v9fs_path_init(&path);
                 err = v9fs_name_to_path(s, &fidp->path, name->data, &path);
                 if (!err) {
                     err = s->ops->lstat(&s->ctx, &path, stbuf);
                     if (err < 0) {
                         err = -errno;
                         s->ops->close(&s->ctx, &fidp->fs);
-                    } else {
-                        v9fs_path_copy(&fidp->path, &path);
                     }
                 } else {
                     s->ops->close(&s->ctx, &fidp->fs);
                 }
-                v9fs_path_free(&path);
             }
         });
+    /*
+     * The fid path must not be mutated from the worker thread: other
+     * requests may access the same fid on the main thread, and the main
+     * thread never takes the path lock for reads. Mutate the new path
+     * here, on the main thread and still under the held write lock, like
+     * every other mutation of a fid path.
+     */
+    if (!err) {
+        v9fs_path_copy(&fidp->path, &path);
+    }
     v9fs_path_unlock(s);
+    v9fs_path_free(&path);
     if (!err) {
         total_open_fd++;
         if (total_open_fd > open_fd_hw) {
diff -Nru qemu-10.0.13+ds/hw/display/qxl-render.c qemu-10.0.14+ds/hw/display/qxl-render.c
--- qemu-10.0.13+ds/hw/display/qxl-render.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/display/qxl-render.c	2026-09-29 03:48:20.000000000 +0300
@@ -27,6 +27,7 @@
 static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect)
 {
     DisplaySurface *surface = qemu_console_surface(qxl->vga.con);
+    int dst_stride = surface_stride(surface);
     uint8_t *dst = surface_data(surface);
     uint8_t *src;
     int len, i;
@@ -45,14 +46,14 @@
     } else {
         src += rect->top * qxl->guest_primary.abs_stride;
     }
-    dst += rect->top  * qxl->guest_primary.abs_stride;
+    dst += rect->top  * dst_stride;
     src += rect->left * qxl->guest_primary.bytes_pp;
     dst += rect->left * qxl->guest_primary.bytes_pp;
     len  = (rect->right - rect->left) * qxl->guest_primary.bytes_pp;

     for (i = rect->top; i < rect->bottom; i++) {
         memcpy(dst, src, len);
-        dst += qxl->guest_primary.abs_stride;
+        dst += dst_stride;
         src += qxl->guest_primary.qxl_stride;
     }
 }
@@ -61,30 +62,13 @@
 {
     QXLSurfaceCreate *sc = &qxl->guest_primary.surface;

-    qxl->guest_primary.qxl_stride = sc->stride;
-    qxl->guest_primary.abs_stride = abs(sc->stride);
+    qxl->guest_primary.qxl_stride = le32_to_cpu(sc->stride);
+    qxl->guest_primary.abs_stride = abs(qxl->guest_primary.qxl_stride);
     qxl->guest_primary.resized++;
-    switch (sc->format) {
-    case SPICE_SURFACE_FMT_16_555:
-        qxl->guest_primary.bytes_pp = 2;
-        qxl->guest_primary.bits_pp = 15;
-        break;
-    case SPICE_SURFACE_FMT_16_565:
-        qxl->guest_primary.bytes_pp = 2;
-        qxl->guest_primary.bits_pp = 16;
-        break;
-    case SPICE_SURFACE_FMT_32_xRGB:
-    case SPICE_SURFACE_FMT_32_ARGB:
-        qxl->guest_primary.bytes_pp = 4;
-        qxl->guest_primary.bits_pp = 32;
-        break;
-    default:
-        fprintf(stderr, "%s: unhandled format: %x\n", __func__,
-                qxl->guest_primary.surface.format);
-        qxl->guest_primary.bytes_pp = 4;
-        qxl->guest_primary.bits_pp = 32;
-        break;
-    }
+    /* fallback to default bpp if format is unknown */
+    qxl_format_bpp(qxl, le32_to_cpu(sc->format),
+                   &qxl->guest_primary.bytes_pp,
+                   &qxl->guest_primary.bits_pp);
 }

 static void qxl_set_rect_to_surface(PCIQXLDevice *qxl, QXLRect *area)
@@ -101,15 +85,45 @@
     DisplaySurface *surface;
     int width = qxl->guest_head0_width ?: qxl->guest_primary.surface.width;
     int height = qxl->guest_head0_height ?: qxl->guest_primary.surface.height;
+    uint64_t map_height;
     int i;

+    if (width <= 0 || height <= 0) {
+        goto end;
+    }
+
+    if (qxl->guest_primary.bytes_pp > 0) {
+        int max_width = qxl->guest_primary.abs_stride
+                        / qxl->guest_primary.bytes_pp;
+        width = MIN(width, max_width);
+    }
+
+    if (qxl->guest_primary.qxl_stride < 0) {
+        /* qxl_blit() uses the primary height to find the first scanline. */
+        height = MIN(height, (int)qxl->guest_primary.surface.height);
+    }
+
+    if (qxl->guest_primary.abs_stride > 0) {
+        int max_height = qxl->vgamem_size / qxl->guest_primary.abs_stride;
+        height = MIN(height, max_height);
+    }
+
+    /*
+     * height limits the visible update, while map_height is the guest memory
+     * span validated by qxl_phys2virt().  With a negative stride qxl_blit()
+     * addresses scanlines from the declared primary height, so a shorter
+     * monitor still requires validating the full primary surface.
+     */
+    map_height = qxl->guest_primary.qxl_stride < 0 ?
+                 qxl->guest_primary.surface.height : height;
+
     if (qxl->guest_primary.resized) {
         qxl->guest_primary.resized = 0;
         qxl->guest_primary.data = qxl_phys2virt(qxl,
                                                 qxl->guest_primary.surface.mem,
                                                 MEMSLOT_GROUP_GUEST,
                                                 qxl->guest_primary.abs_stride
-                                                * height);
+                                                * map_height);
         if (!qxl->guest_primary.data) {
             goto end;
         }
diff -Nru qemu-10.0.13+ds/hw/display/qxl.c qemu-10.0.14+ds/hw/display/qxl.c
--- qemu-10.0.13+ds/hw/display/qxl.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/display/qxl.c	2026-09-29 03:48:20.000000000 +0300
@@ -299,10 +299,12 @@
     qemu_mutex_lock(&qxl->track_lock);
     qxl->guest_cursor = 0;
     qemu_mutex_unlock(&qxl->track_lock);
+    qemu_mutex_lock(&qxl->ssd.lock);
     if (qxl->ssd.cursor) {
         cursor_unref(qxl->ssd.cursor);
     }
     qxl->ssd.cursor = cursor_builtin_hidden();
+    qemu_mutex_unlock(&qxl->ssd.lock);
 }

 static uint32_t qxl_crc32(const uint8_t *p, unsigned len)
@@ -1507,6 +1509,47 @@
     qxl_render_resize(qxl);
 }

+/*
+ * Convert a SpiceSurfaceFormat to bytes per pixel and bits per pixel.
+ *
+ * Only valid for surface suitable for rendering.
+ */
+bool qxl_format_bpp(PCIQXLDevice *qxl, SpiceSurfaceFmt format,
+                    uint32_t *bytes_pp, uint32_t *bits_pp)
+{
+    uint32_t bypp = 4;
+    uint32_t bipp = 32;
+    bool ret = true;
+
+    switch (format) {
+    case SPICE_SURFACE_FMT_16_555:
+        bypp = 2;
+        bipp = 15;
+        break;
+    case SPICE_SURFACE_FMT_16_565:
+        bypp = 2;
+        bipp = 16;
+        break;
+    case SPICE_SURFACE_FMT_32_xRGB:
+    case SPICE_SURFACE_FMT_32_ARGB:
+        bypp = 4;
+        bipp = 32;
+        break;
+    default:
+        ret = false;
+        qxl_set_guest_bug(qxl, "%s: unhandled format: %x", __func__, format);
+    }
+
+    if (bytes_pp != NULL) {
+        *bytes_pp = bypp;
+    }
+    if (bits_pp != NULL) {
+        *bits_pp = bipp;
+    }
+
+    return ret;
+}
+
 static void qxl_create_guest_primary(PCIQXLDevice *qxl, int loadvm,
                                      qxl_async_io async)
 {
@@ -1514,6 +1557,7 @@
     QXLSurfaceCreate *sc = &qxl->guest_primary.surface;
     uint32_t requested_height = le32_to_cpu(sc->height);
     int requested_stride = le32_to_cpu(sc->stride);
+    uint32_t bytes_pp;

     if (requested_stride == INT32_MIN ||
         abs(requested_stride) * (uint64_t)requested_height
@@ -1550,6 +1594,23 @@
         return;
     }

+    if (!qxl_format_bpp(qxl, surface.format, &bytes_pp, NULL)) {
+        return;
+    }
+
+    if (surface.width == 0 || surface.height == 0) {
+        qxl_set_guest_bug(qxl, "%s: zero dimension %ux%u",
+                          __func__, surface.width, surface.height);
+        return;
+    }
+
+    if ((uint64_t)surface.width * bytes_pp > abs(surface.stride)) {
+        qxl_set_guest_bug(qxl, "%s: stride too small for width:"
+                          " stride %d width %u bpp %u",
+                          __func__, surface.stride, surface.width, bytes_pp);
+        return;
+    }
+
     surface.mouse_mode = true;
     surface.group_id   = MEMSLOT_GROUP_GUEST;
     if (loadvm) {
diff -Nru qemu-10.0.13+ds/hw/display/qxl.h qemu-10.0.14+ds/hw/display/qxl.h
--- qemu-10.0.13+ds/hw/display/qxl.h	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/display/qxl.h	2026-09-29 03:48:20.000000000 +0300
@@ -181,6 +181,8 @@
 void qxl_spice_reset_memslots(PCIQXLDevice *qxl);
 void qxl_spice_reset_image_cache(PCIQXLDevice *qxl);
 void qxl_spice_reset_cursor(PCIQXLDevice *qxl);
+bool qxl_format_bpp(PCIQXLDevice *qxl, SpiceSurfaceFmt format,
+                    uint32_t *bytes_pp, uint32_t *bits_pp);

 /* qxl-logger.c */
 int qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id);
diff -Nru qemu-10.0.13+ds/hw/display/vga.c qemu-10.0.14+ds/hw/display/vga.c
--- qemu-10.0.13+ds/hw/display/vga.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/display/vga.c	2026-09-29 03:48:20.000000000 +0300
@@ -1239,7 +1239,10 @@
         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;
@@ -1247,8 +1250,8 @@
         surface = qemu_console_surface(s->con);
         dpy_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;
@@ -1827,6 +1830,8 @@

     s->last_width = -1;
     s->last_height = -1;
+    s->last_text_width = -1;
+    s->last_text_height = -1;
 }

 void vga_common_reset(VGACommonState *s)
@@ -1869,6 +1874,8 @@
     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;
@@ -1920,8 +1927,8 @@
         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;
     }

@@ -1960,15 +1967,15 @@
             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);
             dpy_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;
@@ -2053,22 +2060,22 @@
     }

     /* Display a message */
-    s->last_width = 60;
-    s->last_height = height = 3;
+    s->last_text_width = 60;
+    s->last_text_height = height = 3;
     dpy_text_cursor(s->con, -1, -1);
-    dpy_text_resize(s->con, s->last_width, height);
+    dpy_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 ++)
         console_write_ch(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 ++)
         console_write_ch(dst ++, ATTR2CHTYPE(msg_buffer[i], QEMU_COLOR_BLUE,
                                              QEMU_COLOR_BLACK, 1));

-    dpy_text_update(s->con, 0, 0, s->last_width, height);
+    dpy_text_update(s->con, 0, 0, s->last_text_width, height);
 }

 static uint64_t vga_mem_read(void *opaque, hwaddr addr,
diff -Nru qemu-10.0.13+ds/hw/display/vga_int.h qemu-10.0.14+ds/hw/display/vga_int.h
--- qemu-10.0.13+ds/hw/display/vga_int.h	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/display/vga_int.h	2026-09-29 03:48:20.000000000 +0300
@@ -122,7 +122,8 @@
     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 -Nru qemu-10.0.13+ds/hw/display/virtio-gpu-rutabaga.c qemu-10.0.14+ds/hw/display/virtio-gpu-rutabaga.c
--- qemu-10.0.13+ds/hw/display/virtio-gpu-rutabaga.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/display/virtio-gpu-rutabaga.c	2026-09-29 03:48:20.000000000 +0300
@@ -366,10 +366,20 @@
         return;
     }

-    buf = g_new0(uint8_t, cs.size);
+    buf = g_try_new0(uint8_t, cs.size);
+    if (!buf && cs.size) {
+        cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
+        return;
+    }
     s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
                    sizeof(cs), buf, cs.size);
-    CHECK(s == cs.size, cmd);
+    if (s != cs.size) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: size mismatch (%zu/%u)\n",
+                      __func__, s, cs.size);
+        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+        return;
+    }

     rutabaga_cmd.ctx_id = cs.hdr.ctx_id;
     rutabaga_cmd.cmd = buf;
diff -Nru qemu-10.0.13+ds/hw/display/virtio-gpu-udmabuf.c qemu-10.0.14+ds/hw/display/virtio-gpu-udmabuf.c
--- qemu-10.0.13+ds/hw/display/virtio-gpu-udmabuf.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/display/virtio-gpu-udmabuf.c	2026-09-29 03:48:20.000000000 +0300
@@ -38,8 +38,11 @@
         return;
     }

-    list = g_malloc0(sizeof(struct udmabuf_create_list) +
-                     sizeof(struct udmabuf_create_item) * res->iov_cnt);
+    list = g_try_malloc0(sizeof(struct udmabuf_create_list) +
+                         sizeof(struct udmabuf_create_item) * res->iov_cnt);
+    if (!list) {
+        return;
+    }

     for (i = 0; i < res->iov_cnt; i++) {
         rcu_read_lock();
@@ -88,6 +91,7 @@
         close(res->dmabuf_fd);
         res->dmabuf_fd = -1;
     }
+    res->blob = NULL;
 }

 static int find_memory_backend_type(Object *obj, void *opaque)
diff -Nru qemu-10.0.13+ds/hw/display/virtio-gpu-virgl.c qemu-10.0.14+ds/hw/display/virtio-gpu-virgl.c
--- qemu-10.0.13+ds/hw/display/virtio-gpu-virgl.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/display/virtio-gpu-virgl.c	2026-09-29 03:48:20.000000000 +0300
@@ -499,7 +499,11 @@
         return;
     }

-    buf = g_malloc(cs.size);
+    buf = g_try_malloc(cs.size);
+    if (!buf && cs.size) {
+        cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
+        return;
+    }
     s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
                    sizeof(cs), buf, cs.size);
     if (s != cs.size) {
diff -Nru qemu-10.0.13+ds/hw/display/virtio-gpu.c qemu-10.0.14+ds/hw/display/virtio-gpu.c
--- qemu-10.0.13+ds/hw/display/virtio-gpu.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/display/virtio-gpu.c	2026-09-29 03:48:20.000000000 +0300
@@ -63,8 +63,16 @@
         }
         data = pixman_image_get_data(res->image);
     } else {
+        if (!res->blob) {
+            qemu_log_mask(LOG_GUEST_ERROR, "%s: resource %d has no blob\n",
+                          __func__, resource_id);
+            return;
+        }
         if (res->blob_size < (s->current_cursor->width *
                               s->current_cursor->height * 4)) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: blob size too small for resource %d\n",
+                          __func__, resource_id);
             return;
         }
         data = res->blob;
@@ -888,7 +896,10 @@
     }

     esize = sizeof(*ents) * nr_entries;
-    ents = g_malloc(esize);
+    ents = g_try_malloc(esize);
+    if (!ents && esize) {
+        return -1;
+    }
     s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
                    offset, ents, esize);
     if (s != esize) {
@@ -909,6 +920,7 @@
         hwaddr len;
         void *map;

+        /* TODO: a common DMA map SG helper */
         do {
             len = l;
             map = dma_memory_map(VIRTIO_DEVICE(g)->dma_as, a, &len,
@@ -917,20 +929,27 @@
             if (!map) {
                 qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO memory for"
                               " element %d\n", __func__, e);
-                virtio_gpu_cleanup_mapping_iov(g, *iov, v);
-                g_free(ents);
-                *iov = NULL;
-                if (addr) {
-                    g_free(*addr);
-                    *addr = NULL;
-                }
-                return -1;
+                goto err;
             }

             if (!(v % 16)) {
-                *iov = g_renew(struct iovec, *iov, v + 16);
+                struct iovec *new_iov;
+                new_iov = g_try_renew(struct iovec, *iov, v + 16);
+                if (!new_iov) {
+                    dma_memory_unmap(VIRTIO_DEVICE(g)->dma_as, map, len,
+                                     DMA_DIRECTION_TO_DEVICE, len);
+                    goto err;
+                }
+                *iov = new_iov;
                 if (addr) {
-                    *addr = g_renew(uint64_t, *addr, v + 16);
+                    uint64_t *new_addr;
+                    new_addr = g_try_renew(uint64_t, *addr, v + 16);
+                    if (!new_addr) {
+                        dma_memory_unmap(VIRTIO_DEVICE(g)->dma_as, map, len,
+                                         DMA_DIRECTION_TO_DEVICE, len);
+                        goto err;
+                    }
+                    *addr = new_addr;
                 }
             }
             (*iov)[v].iov_base = map;
@@ -948,6 +967,15 @@

     g_free(ents);
     return 0;
+
+err:
+    virtio_gpu_cleanup_mapping_iov(g, *iov, v);
+    *iov = NULL;
+    if (addr) {
+        g_clear_pointer(addr, g_free);
+    }
+    g_free(ents);
+    return -1;
 }

 void virtio_gpu_cleanup_mapping_iov(VirtIOGPU *g,
@@ -967,6 +995,16 @@
 void virtio_gpu_cleanup_mapping(VirtIOGPU *g,
                                 struct virtio_gpu_simple_resource *res)
 {
+    if (res->blob) {
+        int i, max_outputs = g->parent_obj.conf.max_outputs;
+
+        for (i = 0; i < max_outputs; i++) {
+            if (g->parent_obj.scanout[i].resource_id == res->resource_id) {
+                virtio_gpu_disable_scanout(g, i);
+            }
+        }
+    }
+
     virtio_gpu_cleanup_mapping_iov(g, res->iov, res->iov_cnt);
     res->iov = NULL;
     res->iov_cnt = 0;
diff -Nru qemu-10.0.13+ds/hw/i386/vapic.c qemu-10.0.14+ds/hw/i386/vapic.c
--- qemu-10.0.13+ds/hw/i386/vapic.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/i386/vapic.c	2026-09-29 03:48:20.000000000 +0300
@@ -30,6 +30,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,
@@ -586,6 +590,14 @@
     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));
@@ -596,13 +608,16 @@

     /* 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) {
+    if (rom_size == 0 || rom_size > OPTION_ROM_END - rom_paddr) {
+        memory_region_unref(section.mr);
         return -1;
     }
+
     s->rom_size = rom_size;

     /* We need to round to avoid creating subpages
@@ -610,6 +625,7 @@
     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 -Nru qemu-10.0.13+ds/hw/ide/core.c qemu-10.0.14+ds/hw/ide/core.c
--- qemu-10.0.13+ds/hw/ide/core.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/ide/core.c	2026-09-29 03:48:20.000000000 +0300
@@ -138,11 +138,12 @@
     memset(p, 0, sizeof(s->identify_data));

     put_le16(p + 0, 0x0040);
+    /* Words 1, 3 and 6 describe the default translation (ATA-5 8.16.8) */
     put_le16(p + 1, s->cylinders);
-    put_le16(p + 3, s->heads);
-    put_le16(p + 4, 512 * s->sectors); /* XXX: retired, remove ? */
+    put_le16(p + 3, s->drive_heads);
+    put_le16(p + 4, 512 * s->drive_sectors); /* XXX: retired, remove ? */
     put_le16(p + 5, 512); /* XXX: retired, remove ? */
-    put_le16(p + 6, s->sectors);
+    put_le16(p + 6, s->drive_sectors);
     padstr((char *)(p + 10), s->drive_serial_str, 20); /* serial number */
     put_le16(p + 20, 3); /* XXX: retired, remove ? */
     put_le16(p + 21, 512); /* cache size in sectors */
@@ -332,8 +333,8 @@

     put_le16(p + 0, 0x848a);                    /* CF Storage Card signature */
     put_le16(p + 1, s->cylinders);              /* Default cylinders */
-    put_le16(p + 3, s->heads);                  /* Default heads */
-    put_le16(p + 6, s->sectors);                /* Default sectors per track */
+    put_le16(p + 3, s->drive_heads);            /* Default heads */
+    put_le16(p + 6, s->drive_sectors);          /* Default sectors per track */
     /* *(p + 7) := nb_sectors >> 16 -- see ide_cfata_identify_size */
     /* *(p + 8) := nb_sectors       -- see ide_cfata_identify_size */
     padstr((char *)(p + 10), s->drive_serial_str, 20); /* serial number */
@@ -1655,14 +1656,21 @@
 /* INITIALIZE DEVICE PARAMETERS */
 static bool cmd_specify(IDEState *s, uint8_t cmd)
 {
-    if (s->blk && s->drive_kind != IDE_CD) {
-        s->heads = (s->select & (ATA_DEV_HS)) + 1;
-        s->sectors = s->nsector;
-        ide_bus_set_irq(s->bus);
-    } else {
+    if (!s->blk || s->drive_kind == IDE_CD) {
+        ide_abort_command(s);
+        return true;
+    }
+
+    /* ATA-2 D.2.8 limits IDENTIFY DEVICE word 56, and the count, to 1..255 */
+    if (s->nsector == 0 || s->nsector > 255) {
         ide_abort_command(s);
+        return true;
     }

+    s->heads = (s->select & (ATA_DEV_HS)) + 1;
+    s->sectors = s->nsector;
+    ide_bus_set_irq(s->bus);
+
     return true;
 }

diff -Nru qemu-10.0.13+ds/hw/input/ps2.c qemu-10.0.14+ds/hw/input/ps2.c
--- qemu-10.0.13+ds/hw/input/ps2.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/input/ps2.c	2026-09-29 03:48:20.000000000 +0300
@@ -72,6 +72,7 @@
 #define AUX_SET_DEFAULT     0xF6
 #define AUX_RESET           0xFF    /* Reset aux device */
 #define AUX_ACK             0xFA    /* Command byte ACK. */
+#define AUX_RESEND          0xFE    /* Command NACK, send the cmd again */

 #define MOUSE_STATUS_REMOTE     0x40
 #define MOUSE_STATUS_ENABLED    0x20
@@ -961,6 +962,11 @@
                 s->mouse_type);
             break;
         default:
+            /*
+             * A PS/2 device answers every command it is given; an unknown
+             * one draws a resend.
+             */
+            ps2_queue(ps2, AUX_RESEND);
             break;
         }
         break;
diff -Nru qemu-10.0.13+ds/hw/intc/bcm2835_ic.c qemu-10.0.14+ds/hw/intc/bcm2835_ic.c
--- qemu-10.0.13+ds/hw/intc/bcm2835_ic.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/intc/bcm2835_ic.c	2026-09-29 03:48:20.000000000 +0300
@@ -139,10 +139,19 @@
     BCM2835ICState *s = opaque;

     switch (offset) {
-    case FIQ_CONTROL:
-        s->fiq_select = extract32(val, 0, 7);
+    case FIQ_CONTROL: {
+        unsigned fiq_select = extract32(val, 0, 7);
+
+        if (fiq_select >= GPU_IRQS + ARM_IRQS) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: FIQ select %u out of range\n",
+                          __func__, fiq_select);
+            return;
+        }
+        s->fiq_select = fiq_select;
         s->fiq_enable = extract32(val, 7, 1);
         break;
+    }
     case IRQ_ENABLE_1:
         s->gpu_irq_enable |= val;
         break;
diff -Nru qemu-10.0.13+ds/hw/m68k/q800.c qemu-10.0.14+ds/hw/m68k/q800.c
--- qemu-10.0.13+ds/hw/m68k/q800.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/m68k/q800.c	2026-09-29 03:48:20.000000000 +0300
@@ -715,12 +715,14 @@

 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 -Nru qemu-10.0.13+ds/hw/mem/cxl_type3.c qemu-10.0.14+ds/hw/mem/cxl_type3.c
--- qemu-10.0.13+ds/hw/mem/cxl_type3.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/mem/cxl_type3.c	2026-09-29 03:48:20.000000000 +0300
@@ -903,8 +903,8 @@
     }

     /* DOE Initialization */
-    pcie_doe_init(pci_dev, &ct3d->doe_cdat, 0x190, doe_cdat_prot, true,
-                  CXL_T3_MSIX_PCIE_DOE_TABLE_ACCESS);
+    pcie_doe_init(pci_dev, &ct3d->doe_cdat, cxl_cstate->dvsec_offset,
+                  doe_cdat_prot, true, CXL_T3_MSIX_PCIE_DOE_TABLE_ACCESS);

     cxl_cstate->cdat.build_cdat_table = ct3_build_cdat_table;
     cxl_cstate->cdat.free_cdat_table = ct3_free_cdat_table;
@@ -1093,7 +1093,7 @@
         }
         if (((uint64_t)host_addr < decoder_base) ||
             (hpa_offset >= decoder_size)) {
-            int decoded_iw = cxl_interleave_ways_dec(iw, &error_fatal);
+            int decoded_iw = cxl_interleave_ways_dec(iw, NULL);

             if (decoded_iw == 0) {
                 return false;
diff -Nru qemu-10.0.13+ds/hw/net/virtio-net.c qemu-10.0.14+ds/hw/net/virtio-net.c
--- qemu-10.0.13+ds/hw/net/virtio-net.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/net/virtio-net.c	2026-09-29 03:48:20.000000000 +0300
@@ -1756,12 +1756,16 @@
     }

     ptr += n->host_hdr_len;
+    size -= n->host_hdr_len;
+
+    if (size < sizeof(struct eth_header)) {
+        return 0;
+    }

     if (!memcmp(&ptr[12], vlan, sizeof(vlan))) {
         int vid;

-        /* Truncated vlan packet */
-        if (size < n->host_hdr_len + 16) {
+        if (size < 16) {
             return 0;
         }
         vid = lduw_be_p(ptr + 14) & 0xfff;
@@ -2198,13 +2202,31 @@
 {
     uint16_t hdr_len;
     VirtioNetRscSeg *seg;
+    size_t ip_size;

     hdr_len = chain->n->guest_hdr_len;
+
+    /*
+     * Strip any trailing padding beyond the IP payload so that seg->size
+     * stays in sync with the IP length field used by the bounds check in
+     * virtio_net_rsc_coalesce_data(). virtio_net_rsc_sanity_check4/6()
+     * guarantees that ip_size <= size.
+     */
+    ip_size = hdr_len + sizeof(struct eth_header);
+    if (chain->proto == ETH_P_IP) {
+        struct ip_header *ip = (struct ip_header *)(buf + ip_size);
+        ip_size += htons(ip->ip_len);
+    } else {
+        struct ip6_header *ip6 = (struct ip6_header *)(buf + ip_size);
+        ip_size += sizeof(struct ip6_header)
+                   + htons(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen);
+    }
+
     seg = g_new(VirtioNetRscSeg, 1);
     seg->buf = g_malloc(hdr_len + sizeof(struct eth_header)
         + sizeof(struct ip6_header) + VIRTIO_NET_MAX_TCP_PAYLOAD);
-    memcpy(seg->buf, buf, size);
-    seg->size = size;
+    memcpy(seg->buf, buf, ip_size);
+    seg->size = ip_size;
     seg->packets = 1;
     seg->dup_ack = 0;
     seg->is_coalesced = 0;
diff -Nru qemu-10.0.13+ds/hw/riscv/virt.c qemu-10.0.14+ds/hw/riscv/virt.c
--- qemu-10.0.13+ds/hw/riscv/virt.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/riscv/virt.c	2026-09-29 03:48:20.000000000 +0300
@@ -405,7 +405,8 @@
             (memmap[VIRT_CLINT].size * socket);
         size = memmap[VIRT_CLINT].size - RISCV_ACLINT_SWI_SIZE;
     }
-    name = g_strdup_printf("/soc/mtimer@%lx", addr);
+    name = g_strdup_printf("/soc/mtimer@%lx",
+                           addr + RISCV_ACLINT_DEFAULT_MTIME);
     qemu_fdt_add_subnode(ms->fdt, name);
     qemu_fdt_setprop_string(ms->fdt, name, "compatible",
         "riscv,aclint-mtimer");
diff -Nru qemu-10.0.13+ds/hw/s390x/s390-pci-inst.c qemu-10.0.14+ds/hw/s390x/s390-pci-inst.c
--- qemu-10.0.13+ds/hw/s390x/s390-pci-inst.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/s390x/s390-pci-inst.c	2026-09-29 03:48:20.000000000 +0300
@@ -653,6 +653,7 @@
         goto out;
     } else {
         if (cache) {
+            /* valid->valid transitions reuse the DMA slot */
             if (cache->perm == entry->perm &&
                 cache->translated_addr == entry->translated_addr) {
                 goto out;
@@ -663,6 +664,9 @@
             memory_region_notify_iommu(&iommu->iommu_mr, 0, event);
             event.type = IOMMU_NOTIFIER_MAP;
             event.entry.perm = entry->perm;
+        } else {
+            /* invalid->valid transitions consume a new DMA slot */
+            dec_dma_avail(iommu);
         }

         cache = g_new(S390IOTLBEntry, 1);
@@ -671,7 +675,6 @@
         cache->len = TARGET_PAGE_SIZE;
         cache->perm = entry->perm;
         g_hash_table_replace(iommu->iotlb, &cache->iova, cache);
-        dec_dma_avail(iommu);
     }

     /*
diff -Nru qemu-10.0.13+ds/hw/s390x/sclp.c qemu-10.0.14+ds/hw/s390x/sclp.c
--- qemu-10.0.13+ds/hw/s390x/sclp.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/s390x/sclp.c	2026-09-29 03:48:20.000000000 +0300
@@ -291,7 +291,7 @@
     sclp_c->execute(sclp, work_sccb, code);
 out_write:
     s390_cpu_pv_mem_write(env_archcpu(env), 0, work_sccb,
-                          be16_to_cpu(work_sccb->h.length));
+                          be16_to_cpu(header.length));
     sclp_c->service_interrupt(sclp, SCLP_PV_DUMMY_ADDR);
     return 0;
 }
diff -Nru qemu-10.0.13+ds/hw/scsi/scsi-disk.c qemu-10.0.14+ds/hw/scsi/scsi-disk.c
--- qemu-10.0.13+ds/hw/scsi/scsi-disk.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/scsi/scsi-disk.c	2026-09-29 03:48:20.000000000 +0300
@@ -1695,8 +1695,12 @@
         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];

         /*
@@ -1933,6 +1937,7 @@
     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;
@@ -1952,7 +1957,7 @@
         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.  */
@@ -1978,7 +1983,7 @@
     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);
     }

@@ -3234,6 +3239,8 @@
     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),
 };

@@ -3292,6 +3299,8 @@
                     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, void *data)
diff -Nru qemu-10.0.13+ds/hw/scsi/virtio-scsi-dataplane.c qemu-10.0.14+ds/hw/scsi/virtio-scsi-dataplane.c
--- qemu-10.0.13+ds/hw/scsi/virtio-scsi-dataplane.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/scsi/virtio-scsi-dataplane.c	2026-09-29 03:48:20.000000000 +0300
@@ -230,7 +230,7 @@
 fail_guest_notifiers:
     s->dataplane_fenced = true;
     s->dataplane_starting = false;
-    s->dataplane_started = true;
+    s->dataplane_started = false;
     return -ENOSYS;
 }

diff -Nru qemu-10.0.13+ds/hw/sd/sdhci.c qemu-10.0.14+ds/hw/sd/sdhci.c
--- qemu-10.0.13+ds/hw/sd/sdhci.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/sd/sdhci.c	2026-09-29 03:48:20.000000000 +0300
@@ -1344,11 +1344,24 @@
         }
         sdhci_update_irq(s);
         break;
-    case SDHC_ACMD12ERRSTS:
+    case SDHC_ACMD12ERRSTS: {
+        uint16_t hostctl2_mask = mask >> 16;
+        uint16_t hostctl2_value = value >> 16;
+
         MASKED_WRITE(s->acmd12errsts, mask, value & UINT16_MAX);
-        if (s->uhs_mode >= UHS_I) {
-            MASKED_WRITE(s->hostctl2, mask >> 16, value >> 16);
+        if (s->uhs_mode < UHS_I) {
+            /*
+             * VERSION4 is writable even without UHS-I. Preserve all other
+             * Host Control 2 bits when UHS-I is not supported.
+             */
+            uint16_t independent = R_SDHC_HOSTCTL2_VERSION4_MASK;

+            hostctl2_mask |= ~independent;
+            hostctl2_value &= independent;
+        }
+        MASKED_WRITE(s->hostctl2, hostctl2_mask, hostctl2_value);
+
+        if (s->uhs_mode >= UHS_I) {
             if (FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, V18_ENA)) {
                 sdbus_set_voltage(&s->sdbus, SD_VOLTAGE_1_8V);
             } else {
@@ -1356,6 +1369,7 @@
             }
         }
         break;
+    }

     case SDHC_CAPAB:
     case SDHC_CAPAB + 4:
diff -Nru qemu-10.0.13+ds/hw/uefi/var-service-vars.c qemu-10.0.14+ds/hw/uefi/var-service-vars.c
--- qemu-10.0.13+ds/hw/uefi/var-service-vars.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/uefi/var-service-vars.c	2026-09-29 03:48:20.000000000 +0300
@@ -652,6 +652,10 @@
         return uefi_vars_mm_error(mhdr, mvar, EFI_BAD_BUFFER_SIZE);
     }

+    if (!uefi_str_is_valid(name, lv->name_size, true)) {
+        return uefi_vars_mm_error(mhdr, mvar, EFI_INVALID_PARAMETER);
+    }
+
     uefi_trace_variable(__func__, lv->guid, name, lv->name_size);

     pe = g_malloc0(sizeof(*pe) + lv->name_size);
diff -Nru qemu-10.0.13+ds/hw/usb/hcd-xhci.c qemu-10.0.14+ds/hw/usb/hcd-xhci.c
--- qemu-10.0.13+ds/hw/usb/hcd-xhci.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/usb/hcd-xhci.c	2026-09-29 03:48:20.000000000 +0300
@@ -458,9 +458,15 @@
 {
     XHCIState *xhci = opaque;
     XHCIEvent wrap = { ER_MFINDEX_WRAP, CC_SUCCESS };
+    MemReentrancyGuard *guard = &xhci->parent.mem_reentrancy_guard;
+
+    assert(!guard->engaged_in_io);
+    guard->engaged_in_io = true;

     xhci_event(xhci, &wrap, 0);
     xhci_mfwrap_update(xhci);
+
+    guard->engaged_in_io = false;
 }

 static void xhci_die(XHCIState *xhci)
@@ -1087,7 +1093,14 @@
 static void xhci_ep_kick_timer(void *opaque)
 {
     XHCIEPContext *epctx = opaque;
+    MemReentrancyGuard *guard = &epctx->xhci->parent.mem_reentrancy_guard;
+
+    assert(!guard->engaged_in_io);
+    guard->engaged_in_io = true;
+
     xhci_kick_epctx(epctx, 0);
+
+    guard->engaged_in_io = false;
 }

 static XHCIEPContext *xhci_alloc_epctx(XHCIState *xhci,
@@ -1744,8 +1757,7 @@
 static void xhci_calc_intr_kick(XHCIState *xhci, XHCITransfer *xfer,
                                 XHCIEPContext *epctx, uint64_t mfindex)
 {
-    uint64_t asap = ((mfindex + epctx->interval - 1) &
-                     ~(epctx->interval-1));
+    uint64_t asap = ROUND_UP(mfindex, epctx->interval);
     uint64_t kick = epctx->mfindex_last + epctx->interval;

     assert(epctx->interval != 0);
@@ -1756,8 +1768,7 @@
                                XHCIEPContext *epctx, uint64_t mfindex)
 {
     if (xfer->trbs[0].control & TRB_TR_SIA) {
-        uint64_t asap = ((mfindex + epctx->interval - 1) &
-                         ~(epctx->interval-1));
+        uint64_t asap = ROUND_UP(mfindex, epctx->interval);
         if (asap >= epctx->mfindex_last &&
             asap <= epctx->mfindex_last + epctx->interval * 4) {
             xfer->mfindex_kick = epctx->mfindex_last + epctx->interval;
@@ -1916,26 +1927,15 @@
             xfer->timed_xfer = 0;
             xfer->running_retry = 1;
         }
-        if (xfer->iso_xfer) {
-            /* retry iso transfer */
-            if (xhci_setup_packet(xfer) < 0) {
-                return;
-            }
-            usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
-            assert(xfer->packet.status != USB_RET_NAK);
-            xhci_try_complete_packet(xfer);
-        } else {
-            /* retry nak'ed transfer */
-            if (xhci_setup_packet(xfer) < 0) {
-                return;
-            }
-            usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
-            if (xfer->packet.status == USB_RET_NAK) {
-                xhci_xfer_unmap(xfer);
-                return;
-            }
-            xhci_try_complete_packet(xfer);
+        if (xhci_setup_packet(xfer) < 0) {
+            return;
+        }
+        usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
+        if (xfer->packet.status == USB_RET_NAK) {
+            xhci_xfer_unmap(xfer);
+            return;
         }
+        xhci_try_complete_packet(xfer);
         assert(!xfer->running_retry);
         if (xfer->complete) {
             /* update ring dequeue ptr */
diff -Nru qemu-10.0.13+ds/hw/virtio/virtio-balloon.c qemu-10.0.14+ds/hw/virtio/virtio-balloon.c
--- qemu-10.0.13+ds/hw/virtio/virtio-balloon.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/virtio/virtio-balloon.c	2026-09-29 03:48:20.000000000 +0300
@@ -34,6 +34,7 @@
 #include "system/reset.h"
 #include "hw/virtio/virtio-bus.h"
 #include "hw/virtio/virtio-access.h"
+#include "block/aio-wait.h"

 #define BALLOON_PAGE_SIZE  (1 << VIRTIO_BALLOON_PFN_SHIFT)

@@ -518,6 +519,9 @@
     int i;

     while (dev->block_iothread) {
+        if (dev->free_page_hint_status == FREE_PAGE_HINT_S_UNREALIZE) {
+            return false;
+        }
         qemu_cond_wait(&dev->free_page_cond, &dev->free_page_lock);
     }

@@ -914,6 +918,11 @@
     qemu_register_resettable(OBJECT(dev));
 }

+static void dummy_bh(void *opaque)
+{
+    /* Do nothing */
+}
+
 static void virtio_balloon_device_unrealize(DeviceState *dev)
 {
     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
@@ -921,9 +930,17 @@

     qemu_unregister_resettable(OBJECT(dev));
     if (s->free_page_bh) {
+        AioContext *ctx = iothread_get_aio_context(s->iothread);
+
         qemu_bh_delete(s->free_page_bh);
+
+        qemu_mutex_lock(&s->free_page_lock);
+        s->free_page_hint_status = FREE_PAGE_HINT_S_UNREALIZE;
+        qemu_cond_signal(&s->free_page_cond);
+        qemu_mutex_unlock(&s->free_page_lock);
+        aio_wait_bh_oneshot(ctx, dummy_bh, NULL);
+
         object_unref(OBJECT(s->iothread));
-        virtio_balloon_free_page_stop(s);
         precopy_remove_notifier(&s->free_page_hint_notify);
     }
     balloon_stats_destroy_timer(s);
diff -Nru qemu-10.0.13+ds/hw/virtio/virtio-iommu.c qemu-10.0.14+ds/hw/virtio/virtio-iommu.c
--- qemu-10.0.13+ds/hw/virtio/virtio-iommu.c	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/hw/virtio/virtio-iommu.c	2026-09-29 03:48:20.000000000 +0300
@@ -213,6 +213,10 @@
 {
     uint64_t delta = virt_end - virt_start;

+    if (virt_end < virt_start) {
+        return;
+    }
+
     event->entry.iova = virt_start;
     event->entry.addr_mask = delta;

@@ -808,6 +812,10 @@
         return VIRTIO_IOMMU_S_INVAL;
     }

+    if (virt_end < virt_start) {
+        return VIRTIO_IOMMU_S_INVAL;
+    }
+
     domain = g_tree_lookup(s->domains, GUINT_TO_POINTER(domain_id));
     if (!domain) {
         return VIRTIO_IOMMU_S_NOENT;
@@ -858,6 +866,10 @@

     trace_virtio_iommu_unmap(domain_id, virt_start, virt_end);

+    if (virt_end < virt_start) {
+        return VIRTIO_IOMMU_S_INVAL;
+    }
+
     domain = g_tree_lookup(s->domains, GUINT_TO_POINTER(domain_id));
     if (!domain) {
         return VIRTIO_IOMMU_S_NOENT;
@@ -880,7 +892,10 @@
                 virtio_iommu_notify_unmap(ep->iommu_mr, current_low,
                                           current_high);
             }
-            g_tree_remove(domain->mappings, iter_key);
+            if (!g_tree_remove(domain->mappings, iter_key)) {
+                ret = VIRTIO_IOMMU_S_DEVERR;
+                break;
+            }
             trace_virtio_iommu_unmap_done(domain_id, current_low, current_high);
         } else {
             ret = VIRTIO_IOMMU_S_RANGE;
diff -Nru qemu-10.0.13+ds/include/exec/translation-block.h qemu-10.0.14+ds/include/exec/translation-block.h
--- qemu-10.0.13+ds/include/exec/translation-block.h	2026-08-26 22:31:25.000000000 +0300
+++ qemu-10.0.14+ds/include/exec/translation-block.h	2026-09-29 03:48:20.000000000 +0300
@@ -80,6 +80,7 @@
 #define CF_NOIRQ         0x00010000 /* Generate an uninterruptible TB */
 #define CF_PCREL         0x00020000 /* Opcodes in TB are PC-relative */
 #define CF_BP_PAGE       0x00040000 /* Breakpoint present in code page */
+#define CF_STEP_ATOMIC   0x00080000 /* Running in cpu_exec_step_atomic */
 #define CF_CLUSTER_MASK  0xff000000 /* Top 8 bits are cluster ID */
 #define CF_CLUSTER_SHIFT 24

diff -Nru qemu-10.0.13+ds/include/hw/scsi/scsi.h qemu-10.0.14+ds/include/hw/scsi/scsi.h
--- qemu-10.0.13+ds/include/hw/scsi/scsi.h	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/include/hw/scsi/scsi.h	2026-09-29 03:48:20.000000000 +0300
@@ -250,5 +250,6 @@
 #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 -Nru qemu-10.0.13+ds/include/hw/virtio/virtio-balloon.h qemu-10.0.14+ds/include/hw/virtio/virtio-balloon.h
--- qemu-10.0.13+ds/include/hw/virtio/virtio-balloon.h	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/include/hw/virtio/virtio-balloon.h	2026-09-29 03:48:20.000000000 +0300
@@ -39,6 +39,7 @@
     FREE_PAGE_HINT_S_REQUESTED = 1,
     FREE_PAGE_HINT_S_START = 2,
     FREE_PAGE_HINT_S_DONE = 3,
+    FREE_PAGE_HINT_S_UNREALIZE = 4,
 };

 struct VirtIOBalloon {
diff -Nru qemu-10.0.13+ds/include/ui/console.h qemu-10.0.14+ds/include/ui/console.h
--- qemu-10.0.13+ds/include/ui/console.h	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/include/ui/console.h	2026-09-29 03:48:20.000000000 +0300
@@ -164,6 +164,15 @@
 } QEMUCursor;

 QEMUCursor *cursor_alloc(uint16_t width, uint16_t height);
+
+/*
+ * A cursor may be shared between the main loop, a vCPU thread and a
+ * display backend's own thread, so the refcount is atomic and these two
+ * may be called from any of them.  The object itself is not otherwise
+ * thread-safe: take a reference before publishing the pointer anywhere
+ * another thread can reach it, and never dereference a cursor you do
+ * not hold a reference to.
+ */
 QEMUCursor *cursor_ref(QEMUCursor *c);
 void cursor_unref(QEMUCursor *c);
 QEMUCursor *cursor_builtin_hidden(void);
diff -Nru qemu-10.0.13+ds/io/channel-socket.c qemu-10.0.14+ds/io/channel-socket.c
--- qemu-10.0.13+ds/io/channel-socket.c	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/io/channel-socket.c	2026-09-29 03:48:20.000000000 +0300
@@ -604,7 +604,7 @@

  retry:
     ret = sendmsg(sioc->fd, &msg, sflags);
-    if (ret <= 0) {
+    if (ret < 0) {
         switch (errno) {
         case EAGAIN:
             return QIO_CHANNEL_ERR_BLOCK;
diff -Nru qemu-10.0.13+ds/io/channel-websock.c qemu-10.0.14+ds/io/channel-websock.c
--- qemu-10.0.13+ds/io/channel-websock.c	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/io/channel-websock.c	2026-09-29 03:48:20.000000000 +0300
@@ -230,7 +230,7 @@
     tmp = strchr(buffer, ' ');
     if (!tmp) {
         error_setg(errp, "Missing HTTP path delimiter");
-        return 0;
+        goto bad_request;
     }
     *tmp = '\0';

@@ -492,6 +492,9 @@
     buffer_reserve(&ioc->encinput, want);
     ret = qio_channel_read(ioc->master,
                            (char *)buffer_end(&ioc->encinput), want, errp);
+    if (ret == QIO_CHANNEL_ERR_BLOCK) {
+        return 0;
+    }
     if (ret < 0) {
         return -1;
     }
@@ -562,6 +565,11 @@
                             wioc->encoutput.offset,
                             &err);

+    if (ret == QIO_CHANNEL_ERR_BLOCK) {
+        /* Socket buffer is full, the G_IO_OUT watch stays armed */
+        return TRUE;
+    }
+
     if (ret < 0) {
         trace_qio_channel_websock_handshake_fail(ioc, error_get_pretty(err));
         qio_task_set_error(task, err);
diff -Nru qemu-10.0.13+ds/job.c qemu-10.0.14+ds/job.c
--- qemu-10.0.13+ds/job.c	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/job.c	2026-09-29 03:48:20.000000000 +0300
@@ -629,7 +629,14 @@
                                     ? JOB_STATUS_STANDBY
                                     : JOB_STATUS_PAUSED);
         job->paused = true;
-        job_do_yield_locked(job, -1);
+        /*
+         * Stay paused across back-to-back pause requests: a transient
+         * paused == false while pause_count > 0 would be observed as
+         * "not paused" by job_set_aio_context() and other drain consumers.
+         */
+        do {
+            job_do_yield_locked(job, -1);
+        } while (job_should_pause_locked(job) && !job_is_cancelled_locked(job));
         job->paused = false;
         job_state_transition_locked(job, status);
     }
diff -Nru qemu-10.0.13+ds/linux-user/include/host/loongarch64/host-signal.h qemu-10.0.14+ds/linux-user/include/host/loongarch64/host-signal.h
--- qemu-10.0.13+ds/linux-user/include/host/loongarch64/host-signal.h	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/linux-user/include/host/loongarch64/host-signal.h	2026-09-29 03:48:20.000000000 +0300
@@ -61,6 +61,10 @@
             return true;
         }
         break;
+    case 0b001011: /* v{ld,st}, xv{ld,st} */
+        return (insn >> 22) & 1;
+    case 0b001100: /* v{ldrepl,stelm}, xv{ldrepl,stelm} */
+        return (insn >> 24) & 1;
     case 0b001110: /* indexed, atomic, bounds-checking memory operations */
         switch ((insn >> 15) & 0b11111111111) {
         case 0b00000100000: /* stx.b */
@@ -69,6 +73,8 @@
         case 0b00000111000: /* stx.d */
         case 0b00001110000: /* fstx.s */
         case 0b00001111000: /* fstx.d */
+        case 0b00010001000: /* vstx */
+        case 0b00010011000: /* xvstx */
         case 0b00011101100: /* fstgt.s */
         case 0b00011101101: /* fstgt.d */
         case 0b00011101110: /* fstle.s */
diff -Nru qemu-10.0.13+ds/linux-user/syscall.c qemu-10.0.14+ds/linux-user/syscall.c
--- qemu-10.0.13+ds/linux-user/syscall.c	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/linux-user/syscall.c	2026-09-29 03:48:20.000000000 +0300
@@ -10941,6 +10941,15 @@
     case TARGET_NR_mlock:
         return get_errno(mlock(g2h(cpu, arg1), arg2));
 #endif
+#ifdef TARGET_NR_mlock2
+    case TARGET_NR_mlock2:
+        if (arg3 & ~TARGET_MLOCK_ONFAULT) {
+            return -TARGET_EINVAL;
+        }
+        return get_errno(mlock2(g2h(cpu, arg1), arg2,
+                                 (arg3 & TARGET_MLOCK_ONFAULT) ?
+                                 MLOCK_ONFAULT : 0));
+#endif
 #ifdef TARGET_NR_munlock
     case TARGET_NR_munlock:
         return get_errno(munlock(g2h(cpu, arg1), arg2));
diff -Nru qemu-10.0.13+ds/linux-user/syscall_defs.h qemu-10.0.14+ds/linux-user/syscall_defs.h
--- qemu-10.0.13+ds/linux-user/syscall_defs.h	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/linux-user/syscall_defs.h	2026-09-29 03:48:20.000000000 +0300
@@ -2792,6 +2792,10 @@
 #ifndef RESOLVE_IN_ROOT
 #define RESOLVE_IN_ROOT         0x10
 #endif
+
+/* flags for mlock2() */
+#define TARGET_MLOCK_ONFAULT    0x01
+
 #if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \
     (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \
     defined(TARGET_M68K) || defined(TARGET_MICROBLAZE) || \
diff -Nru qemu-10.0.13+ds/migration/block-dirty-bitmap.c qemu-10.0.14+ds/migration/block-dirty-bitmap.c
--- qemu-10.0.13+ds/migration/block-dirty-bitmap.c	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/migration/block-dirty-bitmap.c	2026-09-29 03:48:20.000000000 +0300
@@ -808,13 +808,6 @@
         error_report("Bitmap with the same name ('%s') already exists on "
                      "destination", bdrv_dirty_bitmap_name(s->bitmap));
         return -EINVAL;
-    } else {
-        s->bitmap = bdrv_create_dirty_bitmap(s->bs, granularity,
-                                             s->bitmap_name, &local_err);
-        if (!s->bitmap) {
-            error_report_err(local_err);
-            return -EINVAL;
-        }
     }

     if (flags & DIRTY_BITMAP_MIG_START_FLAG_RESERVED_MASK) {
@@ -831,6 +824,21 @@
         persistent = flags & DIRTY_BITMAP_MIG_START_FLAG_PERSISTENT;
     }

+    /* Not bdrv_is_writable(): nodes stay inactive until migration ends. */
+    if (persistent && bdrv_is_read_only(s->bs)) {
+        error_report("Cannot make migrated bitmap '%s' persistent "
+                     "on read-only node '%s'", s->bitmap_name,
+                     bdrv_get_node_name(s->bs));
+        return -EINVAL;
+    }
+
+    s->bitmap = bdrv_create_dirty_bitmap(s->bs, granularity,
+                                         s->bitmap_name, &local_err);
+    if (!s->bitmap) {
+        error_report_err(local_err);
+        return -EINVAL;
+    }
+
     if (persistent) {
         bdrv_dirty_bitmap_set_persistence(s->bitmap, true);
     }
diff -Nru qemu-10.0.13+ds/qapi/block-core.json qemu-10.0.14+ds/qapi/block-core.json
--- qemu-10.0.13+ds/qapi/block-core.json	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/qapi/block-core.json	2026-09-29 03:48:20.000000000 +0300
@@ -2263,7 +2263,9 @@
 # @persistent: the bitmap is persistent, i.e. it will be saved to the
 #     corresponding block device image file on its close.  For now
 #     only Qcow2 disks support persistent bitmaps.  Default is false
-#     for block-dirty-bitmap-add.  (Since: 2.10)
+#     for block-dirty-bitmap-add.  This fails if the node is
+#     read-only or inactive, since such a bitmap could never be
+#     stored.  (Since: 2.10)
 #
 # @disabled: the bitmap is created in the disabled state, which means
 #     that it will not track drive changes.  The bitmap may be enabled
diff -Nru qemu-10.0.13+ds/qapi/misc.json qemu-10.0.14+ds/qapi/misc.json
--- qemu-10.0.13+ds/qapi/misc.json	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/qapi/misc.json	2026-09-29 03:48:20.000000000 +0300
@@ -117,11 +117,19 @@
 #     <- { "return": [
 #              {
 #                 "id":"iothread0",
-#                 "thread-id":3134
+#                 "thread-id":3134,
+#                 "poll-max-ns":32768,
+#                 "poll-grow":0,
+#                 "poll-shrink":0,
+#                 "aio-max-batch":0
 #              },
 #              {
 #                 "id":"iothread1",
-#                 "thread-id":3135
+#                 "thread-id":3135,
+#                 "poll-max-ns":32768,
+#                 "poll-grow":0,
+#                 "poll-shrink":0,
+#                 "aio-max-batch":0
 #              }
 #           ]
 #        }
diff -Nru qemu-10.0.13+ds/qga/commands-posix-ssh.c qemu-10.0.14+ds/qga/commands-posix-ssh.c
--- qemu-10.0.13+ds/qga/commands-posix-ssh.c	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/qga/commands-posix-ssh.c	2026-09-29 03:48:20.000000000 +0300
@@ -8,11 +8,34 @@
 #include <glib/gstdio.h>
 #include <locale.h>
 #include <pwd.h>
+#include <grp.h>

 #include "commands-common-ssh.h"
 #include "qapi/error.h"
 #include "qga-qapi-commands.h"

+typedef struct EffectiveUserInfo {
+    uid_t uid;
+    gid_t gid;
+} EffectiveUserInfo;
+
+typedef EffectiveUserInfo *PEffectiveUserInfo;
+
+static void rollback_effective_info(PEffectiveUserInfo info)
+{
+    if (info) {
+        /* There is nothing to do in case  when rollback to original user/group IDs
+         * fails. In that case, the process will be terminated by the kernel
+         * and systemd should restart the daemon again.
+         */
+        assert(seteuid(info->uid) == 0);
+        assert(setegid(info->gid) == 0);
+        g_free(info);
+    }
+}
+
+G_DEFINE_AUTO_CLEANUP_FREE_FUNC(PEffectiveUserInfo, rollback_effective_info, NULL);
+
 #ifdef QGA_BUILD_UNIT_TEST
 static struct passwd *
 test_get_passwd_entry(const gchar *user_name, GError **error)
@@ -109,6 +132,36 @@
     return true;
 }

+static PEffectiveUserInfo set_privileges_to_user(const struct passwd *p, Error **errp)
+{
+    g_auto(PEffectiveUserInfo) info = g_new0(EffectiveUserInfo, 1);
+
+    info->uid = geteuid();
+    info->gid = getegid();
+
+#ifndef QGA_BUILD_UNIT_TEST
+    /* The initgroups requires CAP_SETGID. During build time unit tests, we can't do this. */
+    if (initgroups(p->pw_name, p->pw_gid) == -1) {
+        error_setg_errno(errp, errno, "failed to set group for user '%s'",
+                         p->pw_name);
+        return NULL;
+    }
+#endif
+
+    if (setegid(p->pw_gid) == -1) {
+        error_setg_errno(errp, errno, "failed to set effective group ID for user '%s'",
+                         p->pw_name);
+        return NULL;
+    }
+    if (seteuid(p->pw_uid) == -1) {
+        error_setg_errno(errp, errno, "failed to set effective user ID for user '%s'",
+                         p->pw_name);
+        return NULL;
+    }
+
+    return g_steal_pointer(&info);
+}
+
 void
 qmp_guest_ssh_add_authorized_keys(const char *username, strList *keys,
                                   bool has_reset, bool reset,
@@ -120,6 +173,7 @@
     g_auto(GStrv) authkeys = NULL;
     strList *k;
     size_t nkeys, nauthkeys;
+    g_auto(PEffectiveUserInfo) effective_user_info = NULL;

     reset = has_reset && reset;

@@ -132,6 +186,11 @@
         return;
     }

+    effective_user_info = set_privileges_to_user(p, errp);
+    if (effective_user_info == NULL) {
+        return;
+    }
+
     ssh_path = g_build_filename(p->pw_dir, ".ssh", NULL);
     authkeys_path = g_build_filename(ssh_path, "authorized_keys", NULL);

@@ -169,6 +228,7 @@
     g_auto(GStrv) authkeys = NULL;
     GStrv a;
     size_t nkeys = 0;
+    g_auto(PEffectiveUserInfo) effective_user_info = NULL;

     if (!check_openssh_pub_keys(keys, NULL, errp)) {
         return;
@@ -179,6 +239,11 @@
         return;
     }

+    effective_user_info = set_privileges_to_user(p, errp);
+    if (effective_user_info == NULL) {
+        return;
+    }
+
     authkeys_path = g_build_filename(p->pw_dir, ".ssh",
                                      "authorized_keys", NULL);
     if (!g_file_test(authkeys_path, G_FILE_TEST_EXISTS)) {
@@ -216,12 +281,18 @@
     g_auto(GStrv) authkeys = NULL;
     g_autoptr(GuestAuthorizedKeys) ret = NULL;
     int i;
+    g_auto(PEffectiveUserInfo) effective_user_info = NULL;

     p = get_passwd_entry(username, errp);
     if (p == NULL) {
         return NULL;
     }

+    effective_user_info = set_privileges_to_user(p, errp);
+    if (effective_user_info == NULL) {
+        return NULL;
+    }
+
     authkeys_path = g_build_filename(p->pw_dir, ".ssh",
                                      "authorized_keys", NULL);
     authkeys = read_authkeys(authkeys_path, errp);
diff -Nru qemu-10.0.13+ds/target/arm/tcg/cpu32.c qemu-10.0.14+ds/target/arm/tcg/cpu32.c
--- qemu-10.0.13+ds/target/arm/tcg/cpu32.c	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/target/arm/tcg/cpu32.c	2026-09-29 03:48:20.000000000 +0300
@@ -134,7 +134,7 @@
     cpu->midr = 0x41069265;
     cpu->reset_fpsid = 0x41011090;
     cpu->ctr = 0x1dd20d2;
-    cpu->reset_sctlr = 0x00090078;
+    cpu->reset_sctlr = 0x00050078;

     /*
      * ARMv5 does not have the ID_ISAR registers, but we can still
@@ -175,7 +175,7 @@
     cpu->midr = 0x4106a262;
     cpu->reset_fpsid = 0x410110a0;
     cpu->ctr = 0x1dd20d2;
-    cpu->reset_sctlr = 0x00090078;
+    cpu->reset_sctlr = 0x00050078;
     cpu->reset_auxcr = 1;

     /*
diff -Nru qemu-10.0.13+ds/target/arm/tcg/m_helper.c qemu-10.0.14+ds/target/arm/tcg/m_helper.c
--- qemu-10.0.13+ds/target/arm/tcg/m_helper.c	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/target/arm/tcg/m_helper.c	2026-09-29 03:48:20.000000000 +0300
@@ -2839,8 +2839,9 @@
     }

     if (env->v7m.secure) {
+        /* Note that security check is done as Secure even if alt is true */
         v8m_security_lookup(env, addr, MMU_DATA_LOAD, mmu_idx,
-                            targetsec, &sattrs);
+                            env->v7m.secure, &sattrs);
         nsr = sattrs.ns && r;
         nsrw = sattrs.ns && rw;
     } else {
diff -Nru qemu-10.0.13+ds/target/arm/tcg/t16.decode qemu-10.0.14+ds/target/arm/tcg/t16.decode
--- qemu-10.0.13+ds/target/arm/tcg/t16.decode	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/target/arm/tcg/t16.decode	2026-09-29 03:48:20.000000000 +0300
@@ -224,6 +224,9 @@

 {
   {
+    # Before v6T2 this was not NOP space and must UNDEF
+    MAYBE_UNDEF_T1_HINT 1011 1111 ---- 0000
+
     YIELD       1011 1111 0001 0000
     WFE         1011 1111 0010 0000
     WFI         1011 1111 0011 0000
diff -Nru qemu-10.0.13+ds/target/arm/tcg/translate.c qemu-10.0.14+ds/target/arm/tcg/translate.c
--- qemu-10.0.13+ds/target/arm/tcg/translate.c	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/target/arm/tcg/translate.c	2026-09-29 03:48:20.000000000 +0300
@@ -1,3 +1,4 @@
+
 /*
  *  ARM translation
  *
@@ -4546,6 +4547,24 @@
     return true;
 }

+static bool trans_MAYBE_UNDEF_T1_HINT(DisasContext *s,
+                                      arg_MAYBE_UNDEF_T1_HINT *a)
+{
+    /*
+     * The Thumb T1 encoding hint space was only defined starting
+     * in v6T2 for A-profile. For M-profile it always exists, even
+     * in v6M.
+     */
+    if (arm_dc_feature(s, ARM_FEATURE_M) ||
+        arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
+        /* Allow decode to fall through to the hint insns and NOP space */
+        return false;
+    }
+    /* On the earlier cores, we must UNDEF */
+    unallocated_encoding(s);
+    return true;
+}
+
 static bool trans_MSR_imm(DisasContext *s, arg_MSR_imm *a)
 {
     uint32_t val = ror32(a->imm, a->rot * 2);
@@ -6991,7 +7010,14 @@

 static bool trans_CBZ(DisasContext *s, arg_CBZ *a)
 {
-    TCGv_i32 tmp = load_reg(s, a->rn);
+    TCGv_i32 tmp;
+
+    /* CBZ was introduced in v6T2 and v7M */
+    if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
+        return false;
+    }
+
+    tmp = load_reg(s, a->rn);

     arm_gen_condlabel(s);
     tcg_gen_brcondi_i32(a->nz ? TCG_COND_EQ : TCG_COND_NE,
@@ -7240,6 +7266,16 @@
     int cond_mask = a->cond_mask;

     /*
+     * IT insn introduced in v6T2 for A-profile; it is only present
+     * on M-profile if the Main Extension is implemented.
+     */
+    if (!(arm_dc_feature(s, ARM_FEATURE_M)
+          ? arm_dc_feature(s, ARM_FEATURE_M_MAIN)
+          : arm_dc_feature(s, ARM_FEATURE_THUMB2))) {
+        return false;
+    }
+
+    /*
      * No actual code generated for this insn, just setup state.
      *
      * Combinations of firstcond and mask which set up an 0b1111
diff -Nru qemu-10.0.13+ds/target/i386/tcg/decode-new.c.inc qemu-10.0.14+ds/target/i386/tcg/decode-new.c.inc
--- qemu-10.0.13+ds/target/i386/tcg/decode-new.c.inc	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/target/i386/tcg/decode-new.c.inc	2026-09-29 03:48:20.000000000 +0300
@@ -1265,7 +1265,7 @@
     [0xc0] = X86_OP_ENTRY2(XADD,       E,b, G,b,            lock),
     [0xc1] = X86_OP_ENTRY2(XADD,       E,v, G,v,            lock),
     [0xc2] = X86_OP_ENTRY4(VCMP,       V,x, H,x, W,x,       vex2_rep3 p_00_66_f3_f2),
-    [0xc3] = X86_OP_ENTRY3(MOV,        EM,y,G,y, None,None, cpuid(SSE2)), /* MOVNTI */
+    [0xc3] = X86_OP_ENTRY3(MOV,        EM,y,G,y, None,None, cpuid(SSE2) p_00), /* MOVNTI */
     [0xc4] = X86_OP_ENTRY4(PINSRW,     V,dq,H,dq,E,w,       vex5 mmx p_00_66),
     [0xc5] = X86_OP_ENTRY3(PEXTRW,     G,d, U,dq,I,b,       vex5 mmx p_00_66),
     [0xc6] = X86_OP_ENTRY4(VSHUF,      V,x, H,x, W,x,       vex4 p_00_66),
diff -Nru qemu-10.0.13+ds/target/i386/tcg/fpu_helper.c qemu-10.0.14+ds/target/i386/tcg/fpu_helper.c
--- qemu-10.0.13+ds/target/i386/tcg/fpu_helper.c	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/target/i386/tcg/fpu_helper.c	2026-09-29 03:48:20.000000000 +0300
@@ -510,6 +510,7 @@
 void helper_fmov_STN_ST0(CPUX86State *env, int st_index)
 {
     ST(st_index) = ST0;
+    env->fptags[(env->fpstt + st_index) & 7] = 0;
 }

 void helper_fxchg_ST0_STN(CPUX86State *env, int st_index)
@@ -519,6 +520,12 @@
     tmp = ST(st_index);
     ST(st_index) = ST0;
     ST0 = tmp;
+
+    env->fptags[env->fpstt] = 0;
+    env->fptags[(env->fpstt + st_index) & 7] = 0;
+
+    /* C1 is unconditionally cleared to 0 */
+    env->fpus &= ~0x0200;
 }

 /* FPU operations */
@@ -1804,6 +1811,13 @@
     merge_exception_flags(env, old_flags);
 }

+/* fpush() only validates the new top. FXTRACT also needs ST(1) validated. */
+static inline void fpush_fxtract(CPUX86State *env)
+{
+    fpush(env);
+    env->fptags[(env->fpstt + 1) & 7] = 0;
+}
+
 void helper_fxtract(CPUX86State *env)
 {
     int old_flags = save_exception_flags(env);
@@ -1815,22 +1829,22 @@
         /* Easy way to generate -inf and raising division by 0 exception */
         ST0 = floatx80_div(floatx80_chs(floatx80_one), floatx80_zero,
                            &env->fp_status);
-        fpush(env);
+        fpush_fxtract(env);
         ST0 = temp.d;
     } else if (floatx80_invalid_encoding(ST0, &env->fp_status)) {
         float_raise(float_flag_invalid, &env->fp_status);
         ST0 = floatx80_default_nan(&env->fp_status);
-        fpush(env);
+        fpush_fxtract(env);
         ST0 = ST1;
     } else if (floatx80_is_any_nan(ST0)) {
         if (floatx80_is_signaling_nan(ST0, &env->fp_status)) {
             float_raise(float_flag_invalid, &env->fp_status);
             ST0 = floatx80_silence_nan(ST0, &env->fp_status);
         }
-        fpush(env);
+        fpush_fxtract(env);
         ST0 = ST1;
     } else if (floatx80_is_infinity(ST0, &env->fp_status)) {
-        fpush(env);
+        fpush_fxtract(env);
         ST0 = ST1;
         ST1 = floatx80_default_inf(0, &env->fp_status);
     } else {
@@ -1846,7 +1860,7 @@
         }
         /* DP exponent bias */
         ST0 = int32_to_floatx80(expdif, &env->fp_status);
-        fpush(env);
+        fpush_fxtract(env);
         BIASEXPONENT(temp);
         ST0 = temp.d;
     }
diff -Nru qemu-10.0.13+ds/target/ppc/cpu_init.c qemu-10.0.14+ds/target/ppc/cpu_init.c
--- qemu-10.0.13+ds/target/ppc/cpu_init.c	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/target/ppc/cpu_init.c	2026-09-29 03:48:20.000000000 +0300
@@ -6969,10 +6969,10 @@
     PowerPCCPU *cpu = POWERPC_CPU(dev);
     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);

-    pcc->parent_unrealize(dev);
-
     cpu_remove_sync(CPU(cpu));

+    pcc->parent_unrealize(dev);
+
     destroy_ppc_opcodes(cpu);
 }

diff -Nru qemu-10.0.13+ds/target/riscv/cpu.c qemu-10.0.14+ds/target/riscv/cpu.c
--- qemu-10.0.13+ds/target/riscv/cpu.c	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/target/riscv/cpu.c	2026-09-29 03:48:20.000000000 +0300
@@ -646,6 +646,7 @@
     cpu->cfg.ext_zba = true;
     cpu->cfg.ext_zbb = true;
     cpu->cfg.ext_zbs = true;
+    cpu->cfg.ext_zkr = true;
     cpu->cfg.ext_zkt = true;
     cpu->cfg.ext_zvbb = true;
     cpu->cfg.ext_zvbc = true;
diff -Nru qemu-10.0.13+ds/target/riscv/cpu_bits.h qemu-10.0.14+ds/target/riscv/cpu_bits.h
--- qemu-10.0.13+ds/target/riscv/cpu_bits.h	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/target/riscv/cpu_bits.h	2026-09-29 03:48:20.000000000 +0300
@@ -1023,11 +1023,11 @@
     (HVICTL_VTI | HVICTL_IID | HVICTL_IPRIOM | HVICTL_IPRIO)

 /* seed CSR bits */
-#define SEED_OPST                        (0b11 << 30)
-#define SEED_OPST_BIST                   (0b00 << 30)
-#define SEED_OPST_WAIT                   (0b01 << 30)
-#define SEED_OPST_ES16                   (0b10 << 30)
-#define SEED_OPST_DEAD                   (0b11 << 30)
+#define SEED_OPST                        (0b11U << 30)
+#define SEED_OPST_BIST                   (0b00U << 30)
+#define SEED_OPST_WAIT                   (0b01U << 30)
+#define SEED_OPST_ES16                   (0b10U << 30)
+#define SEED_OPST_DEAD                   (0b11U << 30)
 /* PMU related bits */
 #define MIE_LCOFIE                         (1 << IRQ_PMU_OVF)

diff -Nru qemu-10.0.13+ds/target/riscv/csr.c qemu-10.0.14+ds/target/riscv/csr.c
--- qemu-10.0.13+ds/target/riscv/csr.c	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/target/riscv/csr.c	2026-09-29 03:48:20.000000000 +0300
@@ -107,6 +107,13 @@

 static RISCVException ctr(CPURISCVState *env, int csrno)
 {
+    if ((csrno >= CSR_CYCLE && csrno <= CSR_INSTRET) ||
+        (csrno >= CSR_CYCLEH && csrno <= CSR_INSTRETH)) {
+        if (!riscv_cpu_cfg(env)->ext_zicntr) {
+            return RISCV_EXCP_ILLEGAL_INST;
+        }
+    }
+
 #if !defined(CONFIG_USER_ONLY)
     RISCVCPU *cpu = env_archcpu(env);
     int ctr_index;
@@ -123,10 +130,6 @@

     if ((csrno >= CSR_CYCLE && csrno <= CSR_INSTRET) ||
         (csrno >= CSR_CYCLEH && csrno <= CSR_INSTRETH)) {
-        if (!riscv_cpu_cfg(env)->ext_zicntr) {
-            return RISCV_EXCP_ILLEGAL_INST;
-        }
-
         goto skip_ext_pmu_check;
     }

diff -Nru qemu-10.0.13+ds/target/sh4/cpu.h qemu-10.0.14+ds/target/sh4/cpu.h
--- qemu-10.0.13+ds/target/sh4/cpu.h	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/target/sh4/cpu.h	2026-09-29 03:48:20.000000000 +0300
@@ -83,8 +83,7 @@
 #define TB_FLAG_DELAY_SLOT_RTE   (1 << 2)
 #define TB_FLAG_PENDING_MOVCA    (1 << 3)
 #define TB_FLAG_GUSA_SHIFT       4                      /* [11:4] */
-#define TB_FLAG_GUSA_EXCLUSIVE   (1 << 12)
-#define TB_FLAG_UNALIGN          (1 << 13)
+#define TB_FLAG_UNALIGN          (1 << 12)
 #define TB_FLAG_SR_FD            (1 << SR_FD)           /* 15 */
 #define TB_FLAG_FPSCR_PR         FPSCR_PR               /* 19 */
 #define TB_FLAG_FPSCR_SZ         FPSCR_SZ               /* 20 */
@@ -95,8 +94,7 @@
 #define TB_FLAG_DELAY_SLOT_MASK  (TB_FLAG_DELAY_SLOT |       \
                                   TB_FLAG_DELAY_SLOT_COND |  \
                                   TB_FLAG_DELAY_SLOT_RTE)
-#define TB_FLAG_GUSA_MASK        ((0xff << TB_FLAG_GUSA_SHIFT) | \
-                                  TB_FLAG_GUSA_EXCLUSIVE)
+#define TB_FLAG_GUSA_MASK        (0xff << TB_FLAG_GUSA_SHIFT)
 #define TB_FLAG_FPSCR_MASK       (TB_FLAG_FPSCR_PR | \
                                   TB_FLAG_FPSCR_SZ | \
                                   TB_FLAG_FPSCR_FR)
diff -Nru qemu-10.0.13+ds/target/sh4/translate.c qemu-10.0.14+ds/target/sh4/translate.c
--- qemu-10.0.13+ds/target/sh4/translate.c	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/target/sh4/translate.c	2026-09-29 03:48:20.000000000 +0300
@@ -47,6 +47,9 @@
     uint16_t opcode;

     bool has_movcal;
+#ifdef CONFIG_USER_ONLY
+    bool in_gusa_exclusive;
+#endif
 } DisasContext;

 #if defined(CONFIG_USER_ONLY)
@@ -220,7 +223,11 @@

 static inline bool use_exit_tb(DisasContext *ctx)
 {
-    return (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) != 0;
+#ifdef CONFIG_USER_ONLY
+    return ctx->in_gusa_exclusive;
+#else
+    return false;
+#endif
 }

 static bool use_goto_tb(DisasContext *ctx, target_ulong dest)
@@ -273,7 +280,8 @@
     TCGLabel *l1 = gen_new_label();
     TCGCond cond_not_taken = jump_if_true ? TCG_COND_EQ : TCG_COND_NE;

-    if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) {
+#ifdef CONFIG_USER_ONLY
+    if (ctx->in_gusa_exclusive) {
         /* When in an exclusive region, we must continue to the end.
            Therefore, exit the region on a taken branch, but otherwise
            fall through to the next instruction.  */
@@ -286,6 +294,7 @@
         ctx->base.is_jmp = DISAS_NEXT;
         return;
     }
+#endif

     gen_save_cpu_state(ctx, false);
     tcg_gen_brcondi_i32(cond_not_taken, cpu_sr_t, 0, l1);
@@ -304,7 +313,8 @@
     tcg_gen_mov_i32(ds, cpu_delayed_cond);
     tcg_gen_discard_i32(cpu_delayed_cond);

-    if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) {
+#ifdef CONFIG_USER_ONLY
+    if (ctx->in_gusa_exclusive) {
         /* When in an exclusive region, we must continue to the end.
            Therefore, exit the region on a taken branch, but otherwise
            fall through to the next instruction.  */
@@ -318,6 +328,7 @@
         ctx->base.is_jmp = DISAS_NEXT;
         return;
     }
+#endif

     tcg_gen_brcondi_i32(TCG_COND_NE, ds, 0, l1);
     gen_goto_tb(ctx, 1, ctx->base.pc_next + 2);
@@ -1800,16 +1811,18 @@
         /* go out of the delay slot */
         ctx->envflags &= ~TB_FLAG_DELAY_SLOT_MASK;

+#ifdef CONFIG_USER_ONLY
         /* When in an exclusive region, we must continue to the end
            for conditional branches.  */
-        if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE
-            && old_flags & TB_FLAG_DELAY_SLOT_COND) {
+        if (ctx->in_gusa_exclusive && old_flags & TB_FLAG_DELAY_SLOT_COND) {
             gen_delayed_conditional_jump(ctx);
             return;
         }
+
         /* Otherwise this is probably an invalid gUSA region.
            Drop the GUSA bits so the next TB doesn't see them.  */
         ctx->envflags &= ~TB_FLAG_GUSA_MASK;
+#endif

         tcg_gen_movi_i32(cpu_flags, ctx->envflags);
         if (old_flags & TB_FLAG_DELAY_SLOT_COND) {
@@ -1827,7 +1840,6 @@
  */
 static void gen_restart_exclusive(DisasContext *ctx)
 {
-    ctx->envflags |= TB_FLAG_GUSA_EXCLUSIVE;
     gen_save_cpu_state(ctx, false);
     gen_helper_exclusive(tcg_env);
     ctx->base.is_jmp = DISAS_NORETURN;
@@ -2215,11 +2227,13 @@
         int backup = sextract32(ctx->tbflags, TB_FLAG_GUSA_SHIFT, 8);
         int max_insns = (pc_end - pc) / 2;

+        ctx->in_gusa_exclusive = ctx->base.tb->cflags & CF_STEP_ATOMIC;
+
         if (pc != pc_end + backup || max_insns < 2) {
             /* This is a malformed gUSA region.  Don't do anything special,
                since the interpreter is likely to get confused.  */
             ctx->envflags &= ~TB_FLAG_GUSA_MASK;
-        } else if (tbflags & TB_FLAG_GUSA_EXCLUSIVE) {
+        } else if (ctx->in_gusa_exclusive) {
             /* Regardless of single-stepping or the end of the page,
                we must complete execution of the gUSA region while
                holding the exclusive lock.  */
@@ -2253,7 +2267,7 @@

 #ifdef CONFIG_USER_ONLY
     if (unlikely(ctx->envflags & TB_FLAG_GUSA_MASK)
-        && !(ctx->envflags & TB_FLAG_GUSA_EXCLUSIVE)) {
+        && !ctx->in_gusa_exclusive) {
         /*
          * We're in an gUSA region, and we have not already fallen
          * back on using an exclusive region.  Attempt to parse the
@@ -2283,10 +2297,12 @@
 {
     DisasContext *ctx = container_of(dcbase, DisasContext, base);

-    if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) {
+#ifdef CONFIG_USER_ONLY
+    if (ctx->in_gusa_exclusive) {
         /* Ending the region of exclusivity.  Clear the bits.  */
         ctx->envflags &= ~TB_FLAG_GUSA_MASK;
     }
+#endif

     switch (ctx->base.is_jmp) {
     case DISAS_STOP:
diff -Nru qemu-10.0.13+ds/tcg/riscv/tcg-target.c.inc qemu-10.0.14+ds/tcg/riscv/tcg-target.c.inc
--- qemu-10.0.13+ds/tcg/riscv/tcg-target.c.inc	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/tcg/riscv/tcg-target.c.inc	2026-09-29 03:48:20.000000000 +0300
@@ -784,6 +784,7 @@
     case TCG_TYPE_V64:
     case TCG_TYPE_V128:
     case TCG_TYPE_V256:
+        tcg_debug_assert(s->riscv_cur_type != TCG_TYPE_COUNT);
         {
             int lmul = type - riscv_lg2_vlenb;
             int nf = 1 << MAX(lmul, 0);
@@ -1023,6 +1024,10 @@
             unsigned idx = type - riscv_lg2_vlenb;

             tcg_debug_assert(idx < ARRAY_SIZE(whole_reg_ld));
+            /* We must initialize vtype to something to avoid VILL. */
+            if (s->riscv_cur_type == TCG_TYPE_COUNT) {
+                set_vtype(s, type, MO_8);
+            }
             insn = whole_reg_ld[idx];
         } else {
             static const RISCVInsn unit_stride_ld[] = {
@@ -1055,6 +1060,7 @@
     case TCG_TYPE_V64:
     case TCG_TYPE_V128:
     case TCG_TYPE_V256:
+        tcg_debug_assert(s->riscv_cur_type != TCG_TYPE_COUNT);
         if (type >= riscv_lg2_vlenb) {
             static const RISCVInsn whole_reg_st[] = {
                 OPC_VS1R_V, OPC_VS2R_V, OPC_VS4R_V, OPC_VS8R_V
diff -Nru qemu-10.0.13+ds/tests/qemu-iotests/tests/migrate-bitmaps-test qemu-10.0.14+ds/tests/qemu-iotests/tests/migrate-bitmaps-test
--- qemu-10.0.13+ds/tests/qemu-iotests/tests/migrate-bitmaps-test	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/tests/qemu-iotests/tests/migrate-bitmaps-test	2026-09-29 03:48:20.000000000 +0300
@@ -206,6 +206,39 @@
             self.vm_b.launch()
             self.check_bitmap(self.vm_b, sha256 if persistent else False)

+    def test_migration_to_readonly_destination(self):
+        granularity = 512
+        mig_caps = [{'capability': 'events', 'state': True},
+                   {'capability': 'dirty-bitmaps', 'state': True}]
+
+        self.vm_b.add_incoming("defer")
+        self.vm_b.add_drive(disk_b, 'read-only=on')
+
+        self.add_bitmap(self.vm_a, granularity, True)
+        self.vm_a.hmp_qemu_io('drive0', 'write 0 4096')
+
+        self.vm_a.cmd('migrate-set-capabilities', capabilities=mig_caps)
+        self.vm_a.cmd('migrate', uri=mig_cmd)
+        while True:
+            event = self.vm_a.event_wait('MIGRATION')
+            if event['data']['status'] == 'completed':
+                break
+        self.vm_a.shutdown()
+
+        self.vm_b.launch()
+        self.vm_b.cmd('migrate-set-capabilities', capabilities=mig_caps)
+        self.vm_b.cmd('migrate-incoming', uri=incoming_cmd)
+        while True:
+            event = self.vm_b.event_wait('MIGRATION')
+            if event['data']['status'] in ('completed', 'failed'):
+                break
+
+        self.assert_qmp(event, 'data/status', 'failed')
+
+        # A failed incoming load makes the destination process exit on
+        # its own; reap it so tearDown()'s shutdown() is a clean no-op.
+        self.vm_b.wait()
+

 def inject_test_case(klass, suffix, method, *args, **kwargs):
     mc = operator.methodcaller(method, *args, **kwargs)
diff -Nru qemu-10.0.13+ds/tests/qemu-iotests/tests/migrate-bitmaps-test.out qemu-10.0.14+ds/tests/qemu-iotests/tests/migrate-bitmaps-test.out
--- qemu-10.0.13+ds/tests/qemu-iotests/tests/migrate-bitmaps-test.out	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/tests/qemu-iotests/tests/migrate-bitmaps-test.out	2026-09-29 03:48:20.000000000 +0300
@@ -1,5 +1,5 @@
-.....................................
+......................................
 ----------------------------------------------------------------------
-Ran 37 tests
+Ran 38 tests

 OK
diff -Nru qemu-10.0.13+ds/tests/qemu-iotests/tests/remove-bitmap-from-backing qemu-10.0.14+ds/tests/qemu-iotests/tests/remove-bitmap-from-backing
--- qemu-10.0.13+ds/tests/qemu-iotests/tests/remove-bitmap-from-backing	2026-08-26 22:31:26.000000000 +0300
+++ qemu-10.0.14+ds/tests/qemu-iotests/tests/remove-bitmap-from-backing	2026-09-29 03:48:20.000000000 +0300
@@ -35,7 +35,7 @@
 # Just assert that our method of checking bitmaps in the image works.
 assert 'bitmaps' in qemu_img_info(base)['format-specific']['data']

#1149847#12
Date:
2026-10-04 18:28:46 UTC
From:
To:
Hi Michael,

One small remark, CVE-2026-66020 is not yet fixed in unstable.

It is
https://gitlab.com/qemu-project/qemu/-/commit/3ece85b53c124142c7d5cbb1165d4da125b7c369
and backported to v10.0.14, via
https://gitlab.com/qemu-project/qemu/-/commit/8eebc546bbd54fdd7b6fa2ebb3b54036ab397564
but v11.1.2 misses it yet AFAICS.

Regards,
Salvatore

#1149847#17
Date:
2026-10-04 18:57:08 UTC
From:
To:
Heck. Indeed, I missed that single commit in 11.1.x series.  What a shame.
It will be included in next upstream 11.1.3 release, at about Oct-25, -
I already queued it up after this your note.

I can make a new upload for sid with this single commit on top of 11.1.2,
hopefully it will be enough to keep the peace.

Thank you for spotting it!

Things becomes more and more difficult with the number of changes
increasing (though the September series were smaller than before).
I wonder how come I missed it.  I'll try to find out :)

/mjt

#1149847#22
Date:
2026-10-15 05:21:24 UTC
From:
To:
FWIW, qemu with CVE-2026-66020 fixed is now in testing.

Thanks,

/mjt