* [Stable-10.0.11 57/86] system/rtc: Fix a possible year-2038 integer overflow problem
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 58/86] linux-user: add preadv2/preadv2 Michael Tokarev
` (28 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-stable, Thomas Huth, Daniel P. Berrangé, Laurent Vivier,
Michael Tokarev
From: Thomas Huth <thuth@redhat.com>
rtc_realtime_clock_offset is initialized with:
rtc_realtime_clock_offset = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) / 1000;
And QEMU_CLOCK_REALTIME might be based on gettimeofday() in certain
cases (see get_clock_realtime() in include/qemu/timer.h). So this
counter will exceed 32 bits in the year 2038, thus we should not
store this value in a normal integer variable. Change it to a time_t
to fix the problem.
And while we're at it, also adjust the nearby rtc_host_datetime_offset
variable to be on the safe side in the related code.
Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Michael Tokarev <mjt@tls.msk.ru>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
(cherry picked from commit ae84c738e40339cc0f22773dd4692de529d88739)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/system/rtc.c b/system/rtc.c
index 56951288c4..f7eca982b0 100644
--- a/system/rtc.c
+++ b/system/rtc.c
@@ -40,8 +40,8 @@ static enum {
RTC_BASE_DATETIME,
} rtc_base_type = RTC_BASE_UTC;
static time_t rtc_ref_start_datetime;
-static int rtc_realtime_clock_offset; /* used only with QEMU_CLOCK_REALTIME */
-static int rtc_host_datetime_offset = -1; /* valid & used only with
+static time_t rtc_realtime_clock_offset; /* used only with QEMU_CLOCK_REALTIME */
+static time_t rtc_host_datetime_offset = -1; /* valid & used only with
RTC_BASE_DATETIME */
QEMUClockType rtc_clock;
/***********************************************************/
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 58/86] linux-user: add preadv2/preadv2
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 57/86] system/rtc: Fix a possible year-2038 integer overflow problem Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 59/86] amd_iommu: restrict command buffer head/tail ranges to ring size Michael Tokarev
` (27 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-stable, Dominique Martinet, Helge Deller, Michael Tokarev
From: Dominique Martinet <dominique.martinet@atmark-techno.com>
Some programs apparently use these, like the python test suite.
The flags argument (rwf_t) is an int, with values shared on all arches
and does not need translating.
This was tested manually with the following python script:
```
import os
fd = os.open('test', os.O_RDWR|os.O_CREAT)
os.pwritev(fd, [b'test', b'ok'], 0, os.RWF_HIPRI)
buf = [bytearray(3), bytearray(10)]
os.preadv(fd, buf, 0, os.RWF_HIPRI)
print(buf[0])
print(buf[1])
```
Signed-off-by: Dominique Martinet <dominique.martinet@atmark-techno.com>
Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Helge Deller <deller@gmx.de>
(cherry picked from commit fb4c08147ba79c552897427a42e3b24b38712786)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 710c1b5e38..ca12dbf779 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -745,6 +745,11 @@ safe_syscall5(ssize_t, preadv, int, fd, const struct iovec *, iov, int, iovcnt,
unsigned long, pos_l, unsigned long, pos_h)
safe_syscall5(ssize_t, pwritev, int, fd, const struct iovec *, iov, int, iovcnt,
unsigned long, pos_l, unsigned long, pos_h)
+safe_syscall6(ssize_t, preadv2, int, fd, const struct iovec *, iov, int, iovcnt,
+ unsigned long, pos_l, unsigned long, pos_h, __kernel_rwf_t, flags)
+safe_syscall6(ssize_t, pwritev2, int, fd, const struct iovec *, iov,
+ int, iovcnt, unsigned long, pos_l, unsigned long, pos_h,
+ __kernel_rwf_t, flags)
safe_syscall3(int, connect, int, fd, const struct sockaddr *, addr,
socklen_t, addrlen)
safe_syscall6(ssize_t, sendto, int, fd, const void *, buf, size_t, len,
@@ -11619,6 +11624,39 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
}
}
return ret;
+#endif
+#if defined(TARGET_NR_preadv2)
+ case TARGET_NR_preadv2:
+ {
+ struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
+ if (vec != NULL) {
+ unsigned long low, high;
+
+ target_to_host_low_high(arg4, arg5, &low, &high);
+ ret = get_errno(safe_preadv2(arg1, vec, arg3, low, high, arg6));
+ unlock_iovec(vec, arg2, arg3, 1);
+ } else {
+ ret = -host_to_target_errno(errno);
+ }
+ }
+ return ret;
+#endif
+#if defined(TARGET_NR_pwritev2)
+ case TARGET_NR_pwritev2:
+ {
+ struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
+ if (vec != NULL) {
+ unsigned long low, high;
+
+ target_to_host_low_high(arg4, arg5, &low, &high);
+ ret = get_errno(safe_pwritev2(arg1, vec, arg3, low, high,
+ arg6));
+ unlock_iovec(vec, arg2, arg3, 0);
+ } else {
+ ret = -host_to_target_errno(errno);
+ }
+ }
+ return ret;
#endif
case TARGET_NR_getsid:
return get_errno(getsid(arg1));
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 59/86] amd_iommu: restrict command buffer head/tail ranges to ring size
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 57/86] system/rtc: Fix a possible year-2038 integer overflow problem Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 58/86] linux-user: add preadv2/preadv2 Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 60/86] amd_iommu: Update command buffer head ptr in MMIO region after wraparound Michael Tokarev
` (26 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-stable, Paolo Bonzini, Yunhe Wang, Alejandro Jimenez,
Michael S. Tsirkin, Michael Tokarev
From: Paolo Bonzini <pbonzini@redhat.com>
The AMD IOMMU command buffer is a ring buffer of cmdbuf_len (a power
of two) entries. Each entry is 16 bytes and the head pointer cycles
through the set:
[0, 16, 32, ..., (cmdbuf_len - 1) * AMDVI_COMMAND_SIZE]
The tail pointer is written by the guest through the COMMAND_TAIL MMIO
register (offset 0x2008); the while loop in amdvi_cmdbuf_run() only
terminates when head == tail. If tail is set to a value higher than
cmdbuf_len * 16, head will cycle through all the elements of the ring
buffer indefinitely, without ever matching tail. Fix this by further
masking tail (and head, for consistency) against the size of the
ring buffer.
Reported-by: Yunhe Wang <yunhewwww@163.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Alejandro Jimenez <alejandro.j.jimenez@oracle.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260511113923.2478812-1-pbonzini@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 3097d54016ea9f8f0436f0b20e1b4d78a02b6aeb)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
index 37447dca25..4405ce8988 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -674,7 +674,8 @@ static inline void amdvi_handle_devtab_write(AMDVIState *s)
static inline void amdvi_handle_cmdhead_write(AMDVIState *s)
{
s->cmdbuf_head = amdvi_readq(s, AMDVI_MMIO_COMMAND_HEAD)
- & AMDVI_MMIO_CMDBUF_HEAD_MASK;
+ & AMDVI_MMIO_CMDBUF_HEAD_MASK
+ & (s->cmdbuf_len * AMDVI_COMMAND_SIZE - 1);
amdvi_cmdbuf_run(s);
}
@@ -690,7 +691,8 @@ static inline void amdvi_handle_cmdbase_write(AMDVIState *s)
static inline void amdvi_handle_cmdtail_write(AMDVIState *s)
{
s->cmdbuf_tail = amdvi_readq(s, AMDVI_MMIO_COMMAND_TAIL)
- & AMDVI_MMIO_CMDBUF_TAIL_MASK;
+ & AMDVI_MMIO_CMDBUF_TAIL_MASK
+ & (s->cmdbuf_len * AMDVI_COMMAND_SIZE - 1);
amdvi_cmdbuf_run(s);
}
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 60/86] amd_iommu: Update command buffer head ptr in MMIO region after wraparound
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (2 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 59/86] amd_iommu: restrict command buffer head/tail ranges to ring size Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 61/86] tests/qtest: Add amd-iommu command buffer head wrap test Michael Tokarev
` (25 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-stable, Alejandro Jimenez, Sairaj Kodilkar,
Michael S. Tsirkin, Michael Tokarev
From: Alejandro Jimenez <alejandro.j.jimenez@oracle.com>
When processing a command, amdvi_cmdbuf_run() increments cmdbuf_head and
writes it to the emulated MMIO register space before checking whether it
has reached the end of the command buffer.
If the incremented value reaches the end of the buffer and the tail pointer
is zero, the loop exits and the COMMAND_HEAD offset still contains an
unwrapped value. There are no errors in command processing since internal
cmdbuf_head state is always correctly updated, but the spec defines the
CmdHeadPtr field in MMIO Offset 2000h Command Buffer Head Pointer Register
as RW i.e. guest-visible, so it should be kept consistent.
Wrap cmdbuf_head before updating COMMAND_HEAD so the MMIO-visible register
always matches the internal command buffer head pointer position.
Cc: qemu-stable@nongnu.org
Signed-off-by: Alejandro Jimenez <alejandro.j.jimenez@oracle.com>
Reviewed-by: Sairaj Kodilkar <sarunkod@amd.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260512150044.334867-1-alejandro.j.jimenez@oracle.com>
(cherry picked from commit 3c98e446af825b5806c1e5cd1244b2431b15e884)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
index 4405ce8988..8efebd3eea 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -583,12 +583,12 @@ static void amdvi_cmdbuf_run(AMDVIState *s)
trace_amdvi_command_exec(s->cmdbuf_head, s->cmdbuf_tail, s->cmdbuf);
amdvi_cmdbuf_exec(s);
s->cmdbuf_head += AMDVI_COMMAND_SIZE;
- amdvi_writeq_raw(s, AMDVI_MMIO_COMMAND_HEAD, s->cmdbuf_head);
/* wrap head pointer */
if (s->cmdbuf_head >= s->cmdbuf_len * AMDVI_COMMAND_SIZE) {
s->cmdbuf_head = 0;
}
+ amdvi_writeq_raw(s, AMDVI_MMIO_COMMAND_HEAD, s->cmdbuf_head);
}
}
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 61/86] tests/qtest: Add amd-iommu command buffer head wrap test
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (3 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 60/86] amd_iommu: Update command buffer head ptr in MMIO region after wraparound Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 62/86] libvhost-user: fix buffer overflow in virtqueue_read_indirect_desc() Michael Tokarev
` (24 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-stable, Costas Argyris, Michael S. Tsirkin, Michael Tokarev
From: Costas Argyris <costas.argyris@amd.com>
Add a qtest for AMD IOMMU command buffer head pointer wraparound.
The test programs a command buffer, fills it with COMPLETION_WAIT commands,
advances the tail to consume all but the final entry, then wraps the tail
to zero to force the final command to advance CmdHeadPtr past the end of
the buffer. The guest-visible CmdHeadPtr register must then wrap back to zero.
This covers the case fixed by an earlier CmdHeadPtr wraparound patch.
The Linux kernel AMD IOMMU driver is not affected by this bug because it
uses COMPLETION_WAIT with a memory store doorbell to detect command progress.
Signed-off-by: Costas Argyris <costas.argyris@amd.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260530183458.7778-1-costas.argyris@amd.com>
(cherry picked from commit 8a1c09cbd3fe776a467398700c610cd126ee8a59)
(Mjt: context fixup in MAINTAINERS)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/MAINTAINERS b/MAINTAINERS
index c6d9b022f9..9ff777e190 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3766,6 +3766,7 @@ F: tests/qtest/intel-iommu-test.c
AMD-Vi Emulation
S: Orphan
F: hw/i386/amd_iommu.?
+F: tests/qtest/amd-iommu-test.c
OpenSBI Firmware
L: qemu-riscv@nongnu.org
diff --git a/tests/qtest/amd-iommu-test.c b/tests/qtest/amd-iommu-test.c
new file mode 100644
index 0000000000..fb28511588
--- /dev/null
+++ b/tests/qtest/amd-iommu-test.c
@@ -0,0 +1,76 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+#include "hw/i386/amd_iommu.h"
+
+#define CMDBUF_ADDR 0x200000
+#define CMDBUF_LEN_FIELD 8
+#define CMDBUF_ENTRIES (1U << CMDBUF_LEN_FIELD)
+
+static inline uint64_t amdvi_reg_readq(QTestState *s, uint64_t offset)
+{
+ return qtest_readq(s, AMDVI_BASE_ADDR + offset);
+}
+
+static inline void amdvi_reg_writeq(QTestState *s, uint64_t offset,
+ uint64_t val)
+{
+ qtest_writeq(s, AMDVI_BASE_ADDR + offset, val);
+}
+
+static void test_cmdbuf_head_wrap(void)
+{
+ QTestState *s;
+ uint64_t head;
+ int i;
+ /* 16 bytes per command */
+ struct {
+ uint64_t qw0;
+ uint64_t qw1;
+ } cmdbuf[CMDBUF_ENTRIES];
+
+ if (!qtest_has_machine("q35")) {
+ g_test_skip("q35 machine not available");
+ return;
+ }
+
+ s = qtest_init("-M q35 -device amd-iommu");
+
+ /* fill the command buffer with COMPLETION_WAIT (no-op) commands */
+ for (i = 0; i < CMDBUF_ENTRIES; i++) {
+ cmdbuf[i].qw0 = (uint64_t)AMDVI_CMD_COMPLETION_WAIT << 60;
+ cmdbuf[i].qw1 = 0;
+ }
+ qtest_memwrite(s, CMDBUF_ADDR, cmdbuf, sizeof(cmdbuf));
+
+ /* point the IOMMU at the command buffer and set its length */
+ amdvi_reg_writeq(s, AMDVI_MMIO_COMMAND_BASE,
+ CMDBUF_ADDR | ((uint64_t)CMDBUF_LEN_FIELD << 56));
+
+ /* enable the IOMMU and its command buffer processor */
+ amdvi_reg_writeq(s, AMDVI_MMIO_CONTROL,
+ AMDVI_MMIO_CONTROL_AMDVIEN | AMDVI_MMIO_CONTROL_CMDBUFLEN);
+
+ /* advance tail to the last entry, consuming all but the final entry */
+ amdvi_reg_writeq(s, AMDVI_MMIO_COMMAND_TAIL,
+ (CMDBUF_ENTRIES - 1) * AMDVI_COMMAND_SIZE);
+
+ /* wrap tail to 0, consuming the final entry and completing the buffer */
+ amdvi_reg_writeq(s, AMDVI_MMIO_COMMAND_TAIL, 0);
+
+ /* after consuming all entries the IOMMU must wrap CmdHeadPtr to 0 */
+ head = amdvi_reg_readq(s, AMDVI_MMIO_COMMAND_HEAD);
+ g_assert((head & AMDVI_MMIO_CMDBUF_HEAD_MASK) == 0);
+
+ qtest_quit(s);
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+ qtest_add_func("/q35/amd-iommu/cmdbuf-head-wrap", test_cmdbuf_head_wrap);
+ return g_test_run();
+}
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 3136d15e0f..6ea825e1d7 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -94,6 +94,7 @@ qtests_i386 = \
(config_all_devices.has_key('CONFIG_SB16') ? ['fuzz-sb16-test'] : []) + \
(config_all_devices.has_key('CONFIG_SDHCI_PCI') ? ['fuzz-sdcard-test'] : []) + \
(config_all_devices.has_key('CONFIG_ESP_PCI') ? ['am53c974-test'] : []) + \
+ (config_all_devices.has_key('CONFIG_AMD_IOMMU') ? ['amd-iommu-test'] : []) + \
(config_all_devices.has_key('CONFIG_VTD') ? ['intel-iommu-test'] : []) + \
(host_os != 'windows' and \
config_all_devices.has_key('CONFIG_ACPI_ERST') ? ['erst-test'] : []) + \
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 62/86] libvhost-user: fix buffer overflow in virtqueue_read_indirect_desc()
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (4 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 61/86] tests/qtest: Add amd-iommu command buffer head wrap test Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 63/86] libvduse: fix buffer overflow in vduse_queue_read_indirect_desc() Michael Tokarev
` (23 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-stable, Stefano Garzarella, DARKNAVY,
Daniel P. Berrangé, Michael S. Tsirkin, Michael Tokarev
From: Stefano Garzarella <sgarzare@redhat.com>
virtqueue_read_indirect_desc() copies an indirect descriptor table
into a buffer in chunks when the table crosses a memory region
boundary. The destination is a struct vring_desc pointer but is
advanced by a byte count, so each increment moves the pointer by
read_len elements instead of read_len bytes, writing beyond the
buffer.
Use a char pointer for the destination so that the arithmetic
advances correctly.
While at it, change the source from a struct vring_desc pointer
to a void pointer: when the table is split across regions,
vu_gpa_to_va() can return a pointer into the middle of a descriptor,
so casting it to a struct vring_desc pointer is wrong. The pointer is
only used as a memcpy() source, so a void pointer is fine.
Fixes: CVE-2026-6425
Fixes: 293084a719 ("libvhost-user: Support across-memory-boundary access")
Cc: qemu-stable@nongnu.org
Reported-by: DARKNAVY <vr@darknavy.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260417132645.121192-2-sgarzare@redhat.com>
(cherry picked from commit 85805ee887be4adddb1f1a34f526968adc95e582)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/subprojects/libvhost-user/libvhost-user.c b/subprojects/libvhost-user/libvhost-user.c
index 9c630c2170..014d210748 100644
--- a/subprojects/libvhost-user/libvhost-user.c
+++ b/subprojects/libvhost-user/libvhost-user.c
@@ -2391,8 +2391,9 @@ static int
virtqueue_read_indirect_desc(VuDev *dev, struct vring_desc *desc,
uint64_t addr, size_t len)
{
- struct vring_desc *ori_desc;
+ char *dst_desc = (char *)desc;
uint64_t read_len;
+ void *ori_desc;
if (len > (VIRTQUEUE_MAX_SIZE * sizeof(struct vring_desc))) {
return -1;
@@ -2409,10 +2410,10 @@ virtqueue_read_indirect_desc(VuDev *dev, struct vring_desc *desc,
return -1;
}
- memcpy(desc, ori_desc, read_len);
+ memcpy(dst_desc, ori_desc, read_len);
len -= read_len;
addr += read_len;
- desc += read_len;
+ dst_desc += read_len;
}
return 0;
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 63/86] libvduse: fix buffer overflow in vduse_queue_read_indirect_desc()
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (5 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 62/86] libvhost-user: fix buffer overflow in virtqueue_read_indirect_desc() Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 64/86] virtio: Allow to fill a whole virtqueue in order Michael Tokarev
` (22 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-stable, Stefano Garzarella, DARKNAVY,
Daniel P. Berrangé, Michael S. Tsirkin, Michael Tokarev
From: Stefano Garzarella <sgarzare@redhat.com>
vduse_queue_read_indirect_desc() copies an indirect descriptor table
into a buffer in chunks when the table crosses a memory region
boundary. The destination is a struct vring_desc pointer but is
advanced by a byte count, so each increment moves the pointer by
read_len elements instead of read_len bytes, writing beyond the
buffer.
Use a char pointer for the destination so that the arithmetic
advances correctly.
While at it, change the source from a struct vring_desc pointer
to a void pointer: when the table is split across regions,
iova_to_va() can return a pointer into the middle of a descriptor,
so casting it to a struct vring_desc pointer is wrong. The pointer is
only used as a memcpy() source, so a void pointer is fine.
Fixes: CVE-2026-6425
Fixes: a6caeee811 ("libvduse: Add VDUSE (vDPA Device in Userspace) library")
Cc: qemu-stable@nongnu.org
Reported-by: DARKNAVY <vr@darknavy.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260417132645.121192-3-sgarzare@redhat.com>
(cherry picked from commit 9f1b6d013d42b112680b435af9a9dff331b3fbaf)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/subprojects/libvduse/libvduse.c b/subprojects/libvduse/libvduse.c
index 21ffbb5b8d..df9ca5e56f 100644
--- a/subprojects/libvduse/libvduse.c
+++ b/subprojects/libvduse/libvduse.c
@@ -465,8 +465,9 @@ static int
vduse_queue_read_indirect_desc(VduseDev *dev, struct vring_desc *desc,
uint64_t addr, size_t len)
{
- struct vring_desc *ori_desc;
+ char *dst_desc = (char *)desc;
uint64_t read_len;
+ void *ori_desc;
if (len > (VIRTQUEUE_MAX_SIZE * sizeof(struct vring_desc))) {
return -1;
@@ -483,10 +484,10 @@ vduse_queue_read_indirect_desc(VduseDev *dev, struct vring_desc *desc,
return -1;
}
- memcpy(desc, ori_desc, read_len);
+ memcpy(dst_desc, ori_desc, read_len);
len -= read_len;
addr += read_len;
- desc += read_len;
+ dst_desc += read_len;
}
return 0;
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 64/86] virtio: Allow to fill a whole virtqueue in order
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (6 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 63/86] libvduse: fix buffer overflow in vduse_queue_read_indirect_desc() Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 65/86] target/riscv/cpu_helper.c: allow LOAD_ADDR_MIS promotion to AMO fault Michael Tokarev
` (21 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-stable, Eugenio Pérez, Michael S. Tsirkin,
Michael Tokarev
From: Eugenio Pérez <eperezma@redhat.com>
As the while steps < max_steps is already one less than the vq size, the
right maximum max_steps variable is queue length, not the maximum
possible remainder of % vq->vring.num.
Fixes: b44135daa37 ("virtio: virtqueue_ordered_fill - VIRTIO_F_IN_ORDER support")
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260304173535.2702587-2-eperezma@redhat.com>
(cherry picked from commit eceff0982f97cc79a26883b93f8eac05cd126dd8)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 34ef7b86d9..215c95eccf 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -937,7 +937,7 @@ static void virtqueue_ordered_fill(VirtQueue *vq, const VirtQueueElement *elem,
* We shouldn't need to increase 'i' by more than or equal to
* the distance between used_idx and last_avail_idx (max_steps).
*/
- max_steps = (vq->last_avail_idx - vq->used_idx) % vq->vring.num;
+ max_steps = MIN(vq->last_avail_idx - vq->used_idx, vq->vring.num);
/* Search for element in vq->used_elems */
while (steps < max_steps) {
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 65/86] target/riscv/cpu_helper.c: allow LOAD_ADDR_MIS promotion to AMO fault
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (7 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 64/86] virtio: Allow to fill a whole virtqueue in order Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 66/86] target/riscv/csr.c: do not allow mstatus MPV/GVA writes Michael Tokarev
` (20 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-stable, Daniel Henrique Barboza, Alistair Francis, Chao Liu,
Michael Tokarev
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
promote_load_fault() is missing the promotion of misaligned AMO load
addresses, i.e. RISCV_EXCP_LOAD_ADDR_MIS should be promoted to
RISCV_EXCP_STORE_AMO_ADDR_MIS when RISCV_UW2_ALWAYS_STORE_AMO (i.e.
always_storeamo is true).
All other load AMO faults are already being covered.
Cc: qemu-stable@nongnu.org
Fixes: 98f21c30f5 ("target/riscv: AMO operations always raise store/AMO fault")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3503
Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com>
Message-ID: <20260522181353.429782-1-daniel.barboza@oss.qualcomm.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
(cherry picked from commit d85a4ec06a65ccdd5c7d0f00b3e6695fc14a547a)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 59f6d00774..dc21c4ee44 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -2218,6 +2218,9 @@ static target_ulong promote_load_fault(target_ulong orig_cause)
case RISCV_EXCP_LOAD_PAGE_FAULT:
return RISCV_EXCP_STORE_PAGE_FAULT;
+
+ case RISCV_EXCP_LOAD_ADDR_MIS:
+ return RISCV_EXCP_STORE_AMO_ADDR_MIS;
}
/* if no promotion, return original cause */
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 66/86] target/riscv/csr.c: do not allow mstatus MPV/GVA writes
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (8 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 65/86] target/riscv/cpu_helper.c: allow LOAD_ADDR_MIS promotion to AMO fault Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 67/86] target/riscv/csr.c: fix mstatus.UXL reserved value Michael Tokarev
` (19 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-stable, Daniel Henrique Barboza, Alistair Francis,
Michael Tokarev
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
The priv spec states the following about mstatus.MPV:
"The MPV bit (Machine Previous Virtualization Mode) is written by the
implementation whenever a trap is taken into M-mode."
And, about mstatus.GVA:
"Field GVA (Guest Virtual Address) is written by the implementation
whenever a trap is taken into M-mode."
Both are written during riscv_cpu_do_interrupt(). They're not supposed
to be written by userspace. As far as write_mstatus goes these fields
are read only. The same applies for mstatush.MPV/mstatush.GVA.
Fixes: 03dd405dd5 ("target/riscv: Support MSTATUS.MPV/GVA only when RVH is enabled")
Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Message-ID: <20260514194537.2416243-2-daniel.barboza@oss.qualcomm.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
(cherry picked from commit 18645f19578955ec5ff2c40cd2c8753d6bc460c2)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index a62b16feae..5e1b840087 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -2014,9 +2014,6 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno,
}
if (xl != MXL_RV32 || env->debugger) {
- if (riscv_has_ext(env, RVH)) {
- mask |= MSTATUS_MPV | MSTATUS_GVA;
- }
if ((val & MSTATUS64_UXL) != 0) {
mask |= MSTATUS64_UXL;
}
@@ -2053,7 +2050,7 @@ static RISCVException write_mstatush(CPURISCVState *env, int csrno,
target_ulong val)
{
uint64_t valh = (uint64_t)val << 32;
- uint64_t mask = riscv_has_ext(env, RVH) ? MSTATUS_MPV | MSTATUS_GVA : 0;
+ uint64_t mask = 0;
if (riscv_cpu_cfg(env)->ext_smdbltrp) {
mask |= MSTATUS_MDT;
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 67/86] target/riscv/csr.c: fix mstatus.UXL reserved value
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (9 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 66/86] target/riscv/csr.c: do not allow mstatus MPV/GVA writes Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 68/86] disas/riscv.c: add 'cbo' insns to disassembler Michael Tokarev
` (18 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-stable, Daniel Henrique Barboza, Alistair Francis,
Michael Tokarev
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
By the priv spec the value "3" is marked as 'Reserved' for mstatus.UXL.
Handle a mstatus.UXL = 3 write by writing the current 'xl' instead.
Fixes: https://gitlab.com/qemu-project/qemu/-/work_items/3367
Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Message-ID: <20260514194537.2416243-3-daniel.barboza@oss.qualcomm.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
(cherry picked from commit ddfd33f1965804fc4a718d8d46bc150525c2f9db)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 5e1b840087..9d1ef159b5 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -2015,7 +2015,17 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno,
if (xl != MXL_RV32 || env->debugger) {
if ((val & MSTATUS64_UXL) != 0) {
+ uint64_t uxl = val & MSTATUS64_UXL >> 32;
mask |= MSTATUS64_UXL;
+
+ /*
+ * uxl = 3 is reserved so write the current xl instead.
+ * In case xl = MXL_RV128 (3) write MXL_RV64.
+ */
+ if (uxl == 3) {
+ uxl = xl == MXL_RV128 ? MXL_RV64 : xl;
+ val = deposit64(val, 32, 2, uxl);
+ }
}
}
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 68/86] disas/riscv.c: add 'cbo' insns to disassembler
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (10 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 67/86] target/riscv/csr.c: fix mstatus.UXL reserved value Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 69/86] target/riscv/insn_trans/trans_rvzicbo.c.inc: save opcode before helpers Michael Tokarev
` (17 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-stable, Daniel Henrique Barboza, Chao Liu, Richard Henderson,
Alistair Francis, Michael Tokarev
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
We forgot to add 'cbo' insns to disas/riscv.c. The result is that the
disassembler recognizes all of them as 'lq', an insn that happens to
share the same opcode space.
While we're at it reorder cbo_* entries in insn32.decode using opcode
order instead of insn name.
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3480
Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-ID: <20260519204714.1376551-1-daniel.barboza@oss.qualcomm.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
(cherry picked from commit 9273cda72293ed2f414a0f239c4ac78fb7838c0e)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/disas/riscv.c b/disas/riscv.c
index 85cd2a9c2a..980da7f7e1 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -984,6 +984,10 @@ typedef enum {
rv_op_ssamoswap_d = 953,
rv_op_c_sspush = 954,
rv_op_c_sspopchk = 955,
+ rv_op_cbo_inval = 956,
+ rv_op_cbo_clean = 957,
+ rv_op_cbo_flush = 958,
+ rv_op_cbo_zero = 959,
} rv_op;
/* register names */
@@ -2254,6 +2258,10 @@ const rv_opcode_data rvi_opcode_data[] = {
rv_op_sspush, 0 },
{ "c.sspopchk", rv_codec_cmop_ss, rv_fmt_rs1, NULL, rv_op_sspopchk,
rv_op_sspopchk, 0 },
+ { "cbo.inval", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
+ { "cbo.clean", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
+ { "cbo.flush", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
+ { "cbo.zero", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
};
/* CSR names */
@@ -2875,7 +2883,26 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa)
switch ((inst >> 12) & 0b111) {
case 0: op = rv_op_fence; break;
case 1: op = rv_op_fence_i; break;
- case 2: op = rv_op_lq; break;
+ case 2:
+ /*
+ * 'lq' shares the "(...) 010 ..... 0001111" opcode space
+ * with 'cbo' insns. Check the next 5 bits to select
+ * what we want:
+ *
+ * cbo_inval 0000000 00000 ..... 010 00000 0001111
+ * cbo_clean 0000000 00001 ..... 010 00000 0001111
+ * cbo_flush 0000000 00010 ..... 010 00000 0001111
+ * cbo_zero 0000000 00100 ..... 010 00000 0001111
+ *
+ * Anything that doesn't match these will default to 'lq'.
+ */
+ switch ((inst >> 17) & 0b11111) {
+ case 0: op = rv_op_cbo_inval; break;
+ case 1: op = rv_op_cbo_clean; break;
+ case 2: op = rv_op_cbo_flush; break;
+ case 4: op = rv_op_cbo_zero; break;
+ default: op = rv_op_lq; break;
+ }
}
break;
case 4:
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index cd23b1f3a9..564b745c48 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -199,9 +199,9 @@ ldu ............ ..... 111 ..... 0000011 @i
{
[
# *** RV32 Zicbom Standard Extension ***
+ cbo_inval 0000000 00000 ..... 010 00000 0001111 @sfence_vm
cbo_clean 0000000 00001 ..... 010 00000 0001111 @sfence_vm
cbo_flush 0000000 00010 ..... 010 00000 0001111 @sfence_vm
- cbo_inval 0000000 00000 ..... 010 00000 0001111 @sfence_vm
# *** RV32 Zicboz Standard Extension ***
cbo_zero 0000000 00100 ..... 010 00000 0001111 @sfence_vm
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 69/86] target/riscv/insn_trans/trans_rvzicbo.c.inc: save opcode before helpers
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (11 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 68/86] disas/riscv.c: add 'cbo' insns to disassembler Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 70/86] target/riscv/cpu_helper.c: fault with reserved PTE.PBMT val Michael Tokarev
` (16 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-stable, Daniel Henrique Barboza, Alistair Francis,
Michael Tokarev
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
All helpers from this file can trigger ILLEGAL_INSN exceptions via
check_zicbo_envcfg() directly, bypassing the usual exception code from
translate.c. If we don't save the opcode before each helper,
riscv_raise_exception() is triggered and env->bins won't be unwind during
cpu_loop_exit_restore() (code path cpu_restore_state ->
cpu_restore_state_from_tb() -> restore_state_to_opc()).
And finally, in riscv_cpu_do_interrupt(), we will set (m)tval = 0 when we can,
instead, set it to the cbo opcode that generated the exception.
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3380
Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-ID: <20260520214704.1943652-1-daniel.barboza@oss.qualcomm.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
(cherry picked from commit d6c5855c76b2ea849adb0fb91379dbb1e5a94dca)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/target/riscv/insn_trans/trans_rvzicbo.c.inc b/target/riscv/insn_trans/trans_rvzicbo.c.inc
index 15711c3140..096f7dde27 100644
--- a/target/riscv/insn_trans/trans_rvzicbo.c.inc
+++ b/target/riscv/insn_trans/trans_rvzicbo.c.inc
@@ -33,6 +33,8 @@ static bool trans_cbo_clean(DisasContext *ctx, arg_cbo_clean *a)
REQUIRE_ZICBOM(ctx);
TCGv src = get_address(ctx, a->rs1, 0);
+ /* The helper may raise ILLEGAL_INSN -- record binv for unwind. */
+ decode_save_opc(ctx, 0);
gen_helper_cbo_clean_flush(tcg_env, src);
return true;
}
@@ -42,6 +44,8 @@ static bool trans_cbo_flush(DisasContext *ctx, arg_cbo_flush *a)
REQUIRE_ZICBOM(ctx);
TCGv src = get_address(ctx, a->rs1, 0);
+ /* The helper may raise ILLEGAL_INSN -- record binv for unwind. */
+ decode_save_opc(ctx, 0);
gen_helper_cbo_clean_flush(tcg_env, src);
return true;
}
@@ -51,6 +55,8 @@ static bool trans_cbo_inval(DisasContext *ctx, arg_cbo_inval *a)
REQUIRE_ZICBOM(ctx);
TCGv src = get_address(ctx, a->rs1, 0);
+ /* The helper may raise ILLEGAL_INSN -- record binv for unwind. */
+ decode_save_opc(ctx, 0);
gen_helper_cbo_inval(tcg_env, src);
return true;
}
@@ -60,6 +66,8 @@ static bool trans_cbo_zero(DisasContext *ctx, arg_cbo_zero *a)
REQUIRE_ZICBOZ(ctx);
TCGv src = get_address(ctx, a->rs1, 0);
+ /* The helper may raise ILLEGAL_INSN -- record binv for unwind. */
+ decode_save_opc(ctx, 0);
gen_helper_cbo_zero(tcg_env, src);
return true;
}
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 70/86] target/riscv/cpu_helper.c: fault with reserved PTE.PBMT val
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (12 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 69/86] target/riscv/insn_trans/trans_rvzicbo.c.inc: save opcode before helpers Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 71/86] target/riscv/cpu_helper.c: add PMA access fault Michael Tokarev
` (15 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-stable, Daniel Henrique Barboza, Alistair Francis,
Michael Tokarev
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
We need to fault during any access done while PTE bits 62-61 are both
set, according to the RISC-V priv spec.
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3494
Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-ID: <20260521130727.2311629-1-daniel.barboza@oss.qualcomm.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
(cherry picked from commit 3e33da68f1db7ab586063b708aa571086e7400ce)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index dc21c4ee44..8703d136a2 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -1490,6 +1490,25 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
return TRANSLATE_FAIL;
}
+ /*
+ * priv spec, "Svpbmt" chapter:
+ * "For non-leaf PTEs, bits 62-61 are reserved for future
+ * standard use. Until their use is defined by a standard
+ * extension, they must be cleared by software for forward
+ * compatibility, or else a page-fault exception is raised."
+ *
+ * For leaf PTEs the same bits are also reserved but in that
+ * case the page-fault is mandatory. Make both cases consistent
+ * by also page faulting here.
+ */
+ if ((pte & PTE_PBMT) == PTE_PBMT) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: PBMT bits 62 and 61 are "
+ "reserved but are set in PTE: "
+ "addr: 0x%" HWADDR_PRIx " pte: 0x" TARGET_FMT_lx "\n",
+ __func__, pte_addr, pte);
+ return TRANSLATE_FAIL;
+ }
+
if (!riscv_cpu_cfg(env)->ext_svnapot && (pte & PTE_N)) {
/* Reserved without Svnapot extension */
qemu_log_mask(LOG_GUEST_ERROR, "%s: N bit set in PTE, "
@@ -1542,6 +1561,23 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
return TRANSLATE_FAIL;
}
+ /*
+ * priv spec, "Svpbmt" chapter:
+ * "For leaf PTEs, setting bits 62-61 to the value 3 is reserved
+ * for future standard use. Until this value is defined by a
+ * standard extension, using this reserved value in a leaf PTE
+ * raises a page-fault exception. "
+ *
+ * Raise a fault if 62-61 (i.e. PTE_PBMT) are set.
+ */
+ if ((pte & PTE_PBMT) == PTE_PBMT) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: PBMT bits 62 and 61 are "
+ "reserved but are set in leaf PTE: "
+ "addr: 0x%" HWADDR_PRIx " pte: 0x" TARGET_FMT_lx "\n",
+ __func__, pte_addr, pte);
+ return TRANSLATE_FAIL;
+ }
+
target_ulong rwx = pte & (PTE_R | PTE_W | PTE_X);
/* Check for reserved combinations of RWX flags. */
switch (rwx) {
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 71/86] target/riscv/cpu_helper.c: add PMA access fault
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (13 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 70/86] target/riscv/cpu_helper.c: fault with reserved PTE.PBMT val Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 72/86] disas/riscv.c: fix inst_length() Michael Tokarev
` (14 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-stable, Daniel Henrique Barboza, Alistair Francis, Chao Liu,
Michael Tokarev
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
We're not doing anything special w.r.t PMA (Physical Memory Access)
related faults, handling them like regular faults that will eventually
turn to be regular page faults.
Turns out we can't do that. Priv spec section "Virtual Address
Translation Process" mentions:
"If a store to the PTE at address a+va.vpn[i]×PTESIZE would violate a
PMA or PMP check, raise an access-fault exception corresponding to the
original access type."
This means that we should handle PMA violations with access faults, like
we're already doing with PMP. One clear code path where we should throw
a PMA failure, exposed by [1], is the error return from
address_space_ld* call.
There's a separated issue with the error code being returned by them (it
always return DECODE_ERROR even with 'rejected' reads) that we're going
to work around it by assuming that we did a good job with the PTE
address sanitization beforehand, and interpret that the error here is
related to PMA. This is of course not ideal but fixing this QEMU API is
out of scope for this work.
All this said, we'll set the new pmp_pma_violation flag when we have
either a PMP or a PMA fault, and everything else shall fall into place.
[1] https://gitlab.com/qemu-project/qemu/-/work_items/3502
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3502
Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com>
Message-ID: <20260522172502.320529-1-daniel.barboza@oss.qualcomm.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
(cherry picked from commit 8e090ecfa9e5d9c225a9f6aae1e39586c182afa7)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 6a89f00c49..8fb1928681 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -120,7 +120,8 @@ enum {
TRANSLATE_SUCCESS,
TRANSLATE_FAIL,
TRANSLATE_PMP_FAIL,
- TRANSLATE_G_STAGE_FAIL
+ TRANSLATE_G_STAGE_FAIL,
+ TRANSLATE_PMA_FAIL,
};
/* Extension context status */
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 8703d136a2..5e0d436c73 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -1468,7 +1468,22 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
}
if (res != MEMTX_OK) {
- return TRANSLATE_FAIL;
+ /*
+ * The result of address_space_* APIs above does not take into
+ * consideration reject reads, putting all errors in the same
+ * cathegory (DECODE_ERROR), although there's a clear
+ * distinction between a rejected read versus other errors
+ * (see memory_region_dispatch_read() ->
+ * memory_region_access_valid()). This is something that
+ * we might have to deal with core QEMU logic some other
+ * day.
+ *
+ * For this particular error path, given that we made checks
+ * w.r.t legal PTE address before calling those APIs, we'll
+ * assume that anything != MEMTX_OK means a rejected read,
+ * i.e. a PMA error.
+ */
+ return TRANSLATE_PMA_FAIL;
}
if (riscv_cpu_sxl(env) == MXL_RV32) {
@@ -1748,7 +1763,8 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
}
static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
- MMUAccessType access_type, bool pmp_violation,
+ MMUAccessType access_type,
+ bool pmp_pma_violation,
bool first_stage, bool two_stage,
bool two_stage_indirect)
{
@@ -1756,7 +1772,7 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
switch (access_type) {
case MMU_INST_FETCH:
- if (pmp_violation) {
+ if (pmp_pma_violation) {
cs->exception_index = RISCV_EXCP_INST_ACCESS_FAULT;
} else if (env->virt_enabled && !first_stage) {
cs->exception_index = RISCV_EXCP_INST_GUEST_PAGE_FAULT;
@@ -1765,7 +1781,7 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
}
break;
case MMU_DATA_LOAD:
- if (pmp_violation) {
+ if (pmp_pma_violation) {
cs->exception_index = RISCV_EXCP_LOAD_ACCESS_FAULT;
} else if (two_stage && !first_stage) {
cs->exception_index = RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT;
@@ -1774,7 +1790,7 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
}
break;
case MMU_DATA_STORE:
- if (pmp_violation) {
+ if (pmp_pma_violation) {
cs->exception_index = RISCV_EXCP_STORE_AMO_ACCESS_FAULT;
} else if (two_stage && !first_stage) {
cs->exception_index = RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT;
@@ -1900,7 +1916,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
vaddr im_address;
hwaddr pa = 0;
int prot, prot2, prot_pmp;
- bool pmp_violation = false;
+ bool pmp_pma_violation = false;
bool first_stage_error = true;
bool two_stage_lookup = mmuidx_2stage(mmu_idx);
bool two_stage_indirect_error = false;
@@ -2001,8 +2017,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
}
}
- if (ret == TRANSLATE_PMP_FAIL) {
- pmp_violation = true;
+ if (ret == TRANSLATE_PMP_FAIL || ret == TRANSLATE_PMA_FAIL) {
+ pmp_pma_violation = true;
}
if (ret == TRANSLATE_SUCCESS) {
@@ -2029,7 +2045,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
cpu_check_watchpoint(cs, address, size, MEMTXATTRS_UNSPECIFIED,
wp_access, retaddr);
- raise_mmu_exception(env, address, access_type, pmp_violation,
+ raise_mmu_exception(env, address, access_type, pmp_pma_violation,
first_stage_error, two_stage_lookup,
two_stage_indirect_error);
cpu_loop_exit_restore(cs, retaddr);
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 72/86] disas/riscv.c: fix inst_length()
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (14 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 71/86] target/riscv/cpu_helper.c: add PMA access fault Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 73/86] target/riscv: mask vxrm csrw write to the low 2 bits Michael Tokarev
` (13 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-stable, Daniel Henrique Barboza, Alistair Francis,
Michael Tokarev
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
inst_length() can return 0 if 'inst' happens to not match any known
encoding (like [1]). Returning 0 is not desirable, even for unknown
encodings, given that it will cause a loop in target_disas() later on.
The most recent version of the RISC-V unpriv spec ditched the
sophisticated instruction-length encoding. We're now supporting only
16-bit and 32-bit length instructions, where:
"All the 32-bit instructions in the base ISA have their lowest two bits
set to 11. The optional compressed 16-bit instruction-set extensions
have their lowest two bits equal to 00, 01, or 10."
So the code is now simpler, never returning 0, and in fact it's the same
thing we're already doing in insn_len() from target/riscv/internals.h.
Due to include shenarigans we can't use that function in disas/riscv.c,
but I believe we can cut ourselves some slack this time and not lose
sleep over a 1 line of duplicated logic. We're documenting it though!
[1] https://gitlab.com/qemu-project/qemu/-/work_items/3479
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3479
Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-ID: <20260527200355.2068879-2-daniel.barboza@oss.qualcomm.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
(cherry picked from commit 758dce9c98af4f3ef26eada48a484a7d60258636)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/disas/riscv.c b/disas/riscv.c
index 980da7f7e1..2d8add3212 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -5083,26 +5083,10 @@ static bool check_constraints(rv_decode *dec, const rvc_constraint *c)
return true;
}
-/* instruction length */
-
+/* Same as insn_len() from target/riscv/internals.h */
static size_t inst_length(rv_inst inst)
{
- /* NOTE: supports maximum instruction size of 64-bits */
-
- /*
- * instruction length coding
- *
- * aa - 16 bit aa != 11
- * bbb11 - 32 bit bbb != 111
- * 011111 - 48 bit
- * 0111111 - 64 bit
- */
-
- return (inst & 0b11) != 0b11 ? 2
- : (inst & 0b11100) != 0b11100 ? 4
- : (inst & 0b111111) == 0b011111 ? 6
- : (inst & 0b1111111) == 0b0111111 ? 8
- : 0;
+ return (inst & 3) == 3 ? 4 : 2;
}
/* format instruction */
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 73/86] target/riscv: mask vxrm csrw write to the low 2 bits
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (15 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 72/86] disas/riscv.c: fix inst_length() Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 74/86] hw/uefi: fix parse_hexstr Michael Tokarev
` (12 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-stable, Abhigyan Kumar, Alistair Francis,
Daniel Henrique Barboza, Michael Tokarev
From: Abhigyan Kumar <314abh@gmail.com>
Citing the RISC-V specification:
"The vector fixed-point rounding-mode register holds a two-bit
read-write rounding-mode field in the least-significant bits
(vxrm[1:0]). The upper bits, vxrm[XLEN-1:2], should be written as
zeros."
QEMU wrote full value into env->vxrm causing read of upper bits too.
Used existing macros for bit-masking. Previous had a hard-coded value.
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3470
Signed-off-by: Abhigyan Kumar <314abh@gmail.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
Message-ID: <20260530102100.78150-1-314abh@gmail.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
(cherry picked from commit 9f550a0b630672f4831d9115e66d208ed71cf252)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 9d1ef159b5..a5c1143a7b 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -955,7 +955,7 @@ static RISCVException write_vxrm(CPURISCVState *env, int csrno,
#if !defined(CONFIG_USER_ONLY)
env->mstatus |= MSTATUS_VS;
#endif
- env->vxrm = val;
+ env->vxrm = val & (VCSR_VXRM >> VCSR_VXRM_SHIFT);
return RISCV_EXCP_NONE;
}
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 74/86] hw/uefi: fix parse_hexstr
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (16 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 73/86] target/riscv: mask vxrm csrw write to the low 2 bits Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 75/86] target/i386: apply mod to immediate count of an RCL/RCR operation Michael Tokarev
` (11 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-stable, Gerd Hoffmann, Feifan Qian,
Philippe Mathieu-Daudé, Michael Tokarev
From: Gerd Hoffmann <kraxel@redhat.com>
Make sure we actually have two input characters available before going
to parse two hex digits. Fixes one byte buffer overflow of the output
buffer in case the input string has an odd number of characters.
Fixes: CVE-2026-48915
Fixes: 12058948abdf ("hw/uefi: add var-service-json.c + qapi for NV vars.")
Reported-by: Feifan Qian <bea1e@proton.me>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-ID: <20260526135948.599148-1-kraxel@redhat.com>
(cherry picked from commit d6601a7e1c2452100ed7e4b1d74a70b9acc0abe6)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/hw/uefi/var-service-json.c b/hw/uefi/var-service-json.c
index f5f1556833..8621b86c5c 100644
--- a/hw/uefi/var-service-json.c
+++ b/hw/uefi/var-service-json.c
@@ -98,7 +98,7 @@ static void parse_hexstr(void *dest, char *src, int len)
uint8_t *data = dest;
size_t i;
- for (i = 0; i < len; i += 2) {
+ for (i = 0; i + 1 < len; i += 2) {
*(data++) =
parse_hexchar(src[i]) << 4 |
parse_hexchar(src[i + 1]);
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 75/86] target/i386: apply mod to immediate count of an RCL/RCR operation
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (17 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 74/86] hw/uefi: fix parse_hexstr Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 76/86] gdbstub: Update x86 control register bits Michael Tokarev
` (10 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-stable, Paolo Bonzini, Michael Tokarev
From: Paolo Bonzini <pbonzini@redhat.com>
RCR and RCL instructions with a count of 9 are the same as if the
count was 0, but they generated incorrect code because the can_be_zero
flag is false. This causes 0 to underflow into -1 at
tcg_gen_subi_tl(count, count, 1).
Fix by absorbing the modulo computation into gen_shift_count(), now
renamed gen_shift_count_1(), so that it can handle both reductions.
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3452
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit e38d0afade7c134cd4d675f54d26c394cc3cc31f)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index a22673e4b4..af1cea92be 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -3237,8 +3237,9 @@ static void gen_PUSHF(DisasContext *s, X86DecodedInsn *decode)
gen_push_v(s, s->T0);
}
-static MemOp gen_shift_count(DisasContext *s, X86DecodedInsn *decode,
- bool *can_be_zero, TCGv *count, int unit)
+static MemOp gen_shift_count_1(DisasContext *s, X86DecodedInsn *decode,
+ bool *can_be_zero, TCGv *count, int unit,
+ int mod)
{
MemOp ot = decode->op[0].ot;
int mask = (ot <= MO_32 ? 0x1f : 0x3f);
@@ -3248,16 +3249,31 @@ static MemOp gen_shift_count(DisasContext *s, X86DecodedInsn *decode,
case X86_OP_INT:
*count = tcg_temp_new();
tcg_gen_andi_tl(*count, cpu_regs[R_ECX], mask);
+
+ if (mod < mask) {
+ TCGv temp = tcg_temp_new();
+ assert(mod * 4 >= mask);
+ if (mod * 2 < mask) {
+ tcg_gen_subi_tl(temp, *count, mod * 2);
+ tcg_gen_movcond_tl(TCG_COND_GE, *count, temp, tcg_constant_tl(0), temp, *count);
+ }
+ tcg_gen_subi_tl(temp, *count, mod);
+ tcg_gen_movcond_tl(TCG_COND_GE, *count, temp, tcg_constant_tl(0), temp, *count);
+ }
*can_be_zero = true;
break;
case X86_OP_IMM:
- if ((decode->immediate & mask) == 0) {
+ decode->immediate &= mask;
+ if (mod < mask) {
+ decode->immediate %= mod;
+ }
+ if (decode->immediate == 0) {
*count = NULL;
break;
}
*count = tcg_temp_new();
- tcg_gen_movi_tl(*count, decode->immediate & mask);
+ tcg_gen_movi_tl(*count, decode->immediate);
break;
case X86_OP_SKIP:
@@ -3272,6 +3288,13 @@ static MemOp gen_shift_count(DisasContext *s, X86DecodedInsn *decode,
return ot;
}
+static MemOp gen_shift_count(DisasContext *s, X86DecodedInsn *decode,
+ bool *can_be_zero, TCGv *count, int unit)
+{
+ return gen_shift_count_1(s, decode, can_be_zero, count, unit,
+ INT_MAX);
+}
+
/*
* Compute existing flags in decode->cc_src, for gen_* functions that wants
* to set the cc_op set to CC_OP_ADCOX. In particular, this allows rotate
@@ -3390,29 +3413,14 @@ static void gen_rot_overflow(X86DecodedInsn *decode, TCGv result, TCGv old,
/*
* RCx operations are invariant modulo 8*operand_size+1. For 8 and 16-bit operands,
* this is less than 0x1f (the mask applied by gen_shift_count) so reduce further.
+ * FIXME: are flags updated if the count is nonzero, but a multiple of (8 << op) + 1?
*/
-static void gen_rotc_mod(MemOp ot, TCGv count)
+static MemOp gen_rotc_count(DisasContext *s, X86DecodedInsn *decode,
+ bool *can_be_zero, TCGv *count, int unit)
{
- TCGv temp;
-
- switch (ot) {
- case MO_8:
- temp = tcg_temp_new();
- tcg_gen_subi_tl(temp, count, 18);
- tcg_gen_movcond_tl(TCG_COND_GE, count, temp, tcg_constant_tl(0), temp, count);
- tcg_gen_subi_tl(temp, count, 9);
- tcg_gen_movcond_tl(TCG_COND_GE, count, temp, tcg_constant_tl(0), temp, count);
- break;
-
- case MO_16:
- temp = tcg_temp_new();
- tcg_gen_subi_tl(temp, count, 17);
- tcg_gen_movcond_tl(TCG_COND_GE, count, temp, tcg_constant_tl(0), temp, count);
- break;
-
- default:
- break;
- }
+ MemOp ot = decode->op[0].ot;
+ return gen_shift_count_1(s, decode, can_be_zero, count, unit,
+ (8 << ot) + 1);
}
/*
@@ -3433,7 +3441,7 @@ static void gen_RCL(DisasContext *s, X86DecodedInsn *decode)
bool have_1bit_cin, can_be_zero;
TCGv count;
TCGLabel *zero_label = NULL;
- MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count, decode->op[2].unit);
+ MemOp ot = gen_rotc_count(s, decode, &can_be_zero, &count, decode->op[2].unit);
TCGv low, high, low_count;
if (!count) {
@@ -3444,7 +3452,6 @@ static void gen_RCL(DisasContext *s, X86DecodedInsn *decode)
high = tcg_temp_new();
low_count = tcg_temp_new();
- gen_rotc_mod(ot, count);
have_1bit_cin = gen_eflags_adcox(s, decode, true, can_be_zero);
if (can_be_zero) {
zero_label = gen_new_label();
@@ -3485,7 +3492,7 @@ static void gen_RCR(DisasContext *s, X86DecodedInsn *decode)
bool have_1bit_cin, can_be_zero;
TCGv count;
TCGLabel *zero_label = NULL;
- MemOp ot = gen_shift_count(s, decode, &can_be_zero, &count, decode->op[2].unit);
+ MemOp ot = gen_rotc_count(s, decode, &can_be_zero, &count, decode->op[2].unit);
TCGv low, high, high_count;
if (!count) {
@@ -3496,7 +3503,6 @@ static void gen_RCR(DisasContext *s, X86DecodedInsn *decode)
high = tcg_temp_new();
high_count = tcg_temp_new();
- gen_rotc_mod(ot, count);
have_1bit_cin = gen_eflags_adcox(s, decode, true, can_be_zero);
if (can_be_zero) {
zero_label = gen_new_label();
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 76/86] gdbstub: Update x86 control register bits
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (18 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 75/86] target/i386: apply mod to immediate count of an RCL/RCR operation Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 77/86] hw/9pfs: fix abort due to illegal name with Twstat rename Michael Tokarev
` (9 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-stable, Mathias Krause, Paolo Bonzini, Michael Tokarev
From: Mathias Krause <minipli@grsecurity.net>
The control register bits haven't been updated in a few years, making
them lack behind features QEMU ganied in these years.
Update them to the current version of the SDM and sort the 32bit version
to be in line with all the other definitions (descending order).
This should remove confusion when debugging, for example, CET-enabled
guests:
- before the change:
(gdb) info registers cr4
cr4 0x8000f0 [ PGE MCE PAE PSE ]
- after the change:
(gdb) info registers cr4
cr4 0x8000f0 [ CET PGE MCE PAE PSE ]
Signed-off-by: Mathias Krause <minipli@grsecurity.net>
Link: https://lore.kernel.org/r/20260327143413.254227-1-minipli@grsecurity.net
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 88d39a2937ebad64b8aed8247450e1a6ddf274be)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/gdb-xml/i386-32bit.xml b/gdb-xml/i386-32bit.xml
index 7a66a02b67..1dec40e1d2 100644
--- a/gdb-xml/i386-32bit.xml
+++ b/gdb-xml/i386-32bit.xml
@@ -87,27 +87,34 @@
</flags>
<flags id="i386_cr4" size="4">
- <field name="VME" start="0" end="0"/>
- <field name="PVI" start="1" end="1"/>
- <field name="TSD" start="2" end="2"/>
- <field name="DE" start="3" end="3"/>
- <field name="PSE" start="4" end="4"/>
- <field name="PAE" start="5" end="5"/>
- <field name="MCE" start="6" end="6"/>
- <field name="PGE" start="7" end="7"/>
- <field name="PCE" start="8" end="8"/>
- <field name="OSFXSR" start="9" end="9"/>
- <field name="OSXMMEXCPT" start="10" end="10"/>
- <field name="UMIP" start="11" end="11"/>
- <field name="LA57" start="12" end="12"/>
- <field name="VMXE" start="13" end="13"/>
- <field name="SMXE" start="14" end="14"/>
- <field name="FSGSBASE" start="16" end="16"/>
- <field name="PCIDE" start="17" end="17"/>
- <field name="OSXSAVE" start="18" end="18"/>
- <field name="SMEP" start="20" end="20"/>
- <field name="SMAP" start="21" end="21"/>
+ <field name="LAM_SUP" start="28" end="28"/>
+ <field name="LASS" start="27" end="27"/>
+ <field name="UINTR" start="25" end="25"/>
+ <field name="PKS" start="24" end="24"/>
+ <field name="CET" start="23" end="23"/>
+ <field name="PKE" start="22" end="22"/>
<field name="PKE" start="22" end="22"/>
+ <field name="SMAP" start="21" end="21"/>
+ <field name="SMEP" start="20" end="20"/>
+ <field name="KL" start="19" end="19"/>
+ <field name="OSXSAVE" start="18" end="18"/>
+ <field name="PCIDE" start="17" end="17"/>
+ <field name="FSGSBASE" start="16" end="16"/>
+ <field name="SMXE" start="14" end="14"/>
+ <field name="VMXE" start="13" end="13"/>
+ <field name="LA57" start="12" end="12"/>
+ <field name="UMIP" start="11" end="11"/>
+ <field name="OSXMMEXCPT" start="10" end="10"/>
+ <field name="OSFXSR" start="9" end="9"/>
+ <field name="PCE" start="8" end="8"/>
+ <field name="PGE" start="7" end="7"/>
+ <field name="MCE" start="6" end="6"/>
+ <field name="PAE" start="5" end="5"/>
+ <field name="PSE" start="4" end="4"/>
+ <field name="DE" start="3" end="3"/>
+ <field name="TSD" start="2" end="2"/>
+ <field name="PVI" start="1" end="1"/>
+ <field name="VME" start="0" end="0"/>
</flags>
<flags id="i386_efer" size="4">
diff --git a/gdb-xml/i386-64bit.xml b/gdb-xml/i386-64bit.xml
index 6d88969211..9ac9164e6a 100644
--- a/gdb-xml/i386-64bit.xml
+++ b/gdb-xml/i386-64bit.xml
@@ -102,9 +102,16 @@
</flags>
<flags id="x64_cr4" size="8">
+ <field name="FRED" start="32" end="32"/>
+ <field name="LAM_SUP" start="28" end="28"/>
+ <field name="LASS" start="27" end="27"/>
+ <field name="UINTR" start="25" end="25"/>
+ <field name="PKS" start="24" end="24"/>
+ <field name="CET" start="23" end="23"/>
<field name="PKE" start="22" end="22"/>
<field name="SMAP" start="21" end="21"/>
<field name="SMEP" start="20" end="20"/>
+ <field name="KL" start="19" end="19"/>
<field name="OSXSAVE" start="18" end="18"/>
<field name="PCIDE" start="17" end="17"/>
<field name="FSGSBASE" start="16" end="16"/>
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 77/86] hw/9pfs: fix abort due to illegal name with Twstat rename
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (19 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 76/86] gdbstub: Update x86 control register bits Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 78/86] hw/9pfs: reject . and .. in " Michael Tokarev
` (8 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-stable, Christian Schoenebeck, Feifan Qian, Michael Tokarev
From: Christian Schoenebeck <qemu_oss@crudebyte.com>
The legacy Twstat 9p request can be used to rename files and directories.
Unlike the other, more recent rename requests like Trename and Trenameat,
Twstat does not validate the submitted new name before passing it to
v9fs_complete_rename().
A priviliged guest user with direct communication access to 9p server
could pass a string containing '/' as new name, which causes an assertion
fault (DoS) in local_name_to_path().
Fix this by rejecting such strings by checking the client supplied new
name with name_is_illegal(), similar to how Trename and Trenameat handlers
do already.
Reported-by: Feifan Qian <bea1e@proton.me>
Fixes: 8cf89e007a ("virtio-9p: Add P9_TWSTAT support")
Link: https://lore.kernel.org/qemu-devel/ba09716828e82992f9d8cac7f00eee0bc1c43c61.1780072238.git.qemu_oss@crudebyte.com
Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
(cherry picked from commit 7f5445e7e4050cc117ed4b137bb7dd1474e49d57)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 7d53f070cc..0d58a5a74c 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -3617,6 +3617,11 @@ static void coroutine_fn v9fs_wstat(void *opaque)
err = -EOPNOTSUPP;
goto out;
}
+ if (name_is_illegal(v9stat.name.data)) {
+ err = -ENOENT;
+ goto out;
+ }
+
v9fs_path_write_lock(s);
err = v9fs_complete_rename(pdu, fidp, -1, &v9stat.name);
v9fs_path_unlock(s);
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 78/86] hw/9pfs: reject . and .. in Twstat rename
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (20 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 77/86] hw/9pfs: fix abort due to illegal name with Twstat rename Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 79/86] hw/9pfs: consolidate name validation with check_name() Michael Tokarev
` (7 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-stable, Christian Schoenebeck, Michael Tokarev
From: Christian Schoenebeck <qemu_oss@crudebyte.com>
The other Trename and Trenameat handlers already reject "." and ".."
as new name on rename requests by returning -EISDIR in this case.
The legacy Twstat rename handler is missing this validation. While passing
"." or ".." does not trigger a crash as fixed by the previous patch (since
the fs backend driver's system calls handle these gracefully), it creates
a behavioral inconsistency, as it is semantically meaningless to rename a
file to a directory reference in the first place.
Fix this by rejecting "." and ".." in Twstat rename handler with -EISDIR
to match behavior of Trename and Trenameat handlers.
Fixes: 8cf89e007a ("virtio-9p: Add P9_TWSTAT support")
Link: https://lore.kernel.org/qemu-devel/662333331d371c6c343c8091161de8eaa121880e.1780072238.git.qemu_oss@crudebyte.com
Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
(cherry picked from commit 08750e31fcdccf5352dc3b44475ed5ba6bc80221)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 0d58a5a74c..34ac2c3c9a 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -3621,6 +3621,10 @@ static void coroutine_fn v9fs_wstat(void *opaque)
err = -ENOENT;
goto out;
}
+ if (!strcmp(".", v9stat.name.data) || !strcmp("..", v9stat.name.data)) {
+ err = -EISDIR;
+ goto out;
+ }
v9fs_path_write_lock(s);
err = v9fs_complete_rename(pdu, fidp, -1, &v9stat.name);
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 79/86] hw/9pfs: consolidate name validation with check_name()
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (21 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 78/86] hw/9pfs: reject . and .. in " Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 7:15 ` Christian Schoenebeck
2026-06-24 5:02 ` [Stable-10.0.11 80/86] ui/sdl2: Set GL ES profile before creating initial GL context Michael Tokarev
` (6 subsequent siblings)
29 siblings, 1 reply; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-stable, Christian Schoenebeck, Michael Tokarev
From: Christian Schoenebeck <qemu_oss@crudebyte.com>
Add a new, shared helper function check_name() that consolidates the name
validation logic (illegal name check and "." / ".." rejection) currently
spread over multiple 9p handlers, unnecessarily duplicating code.
This is pure refactoring with no behavior change. The existing error code
semantics are preserved: rename operations return -EISDIR, create
operations return -EEXIST.
Note: These current error codes actually differ from native Linux system
calls (e.g. rename() returns -EBUSY, open(O_CREAT) returns -EISDIR). The 9P
protocol does not mandate specific error codes for these validation errors.
Hence consolidating to a single error code (e.g., -EINVAL) for all cases
could be considered in the future for simplicity reason.
This change reduces code duplication across 9 functions:
- v9fs_lcreate
- v9fs_create
- v9fs_symlink
- v9fs_link
- v9fs_rename
- v9fs_renameat
- v9fs_wstat
- v9fs_mknod
- v9fs_mkdir
Link: https://lore.kernel.org/qemu-devel/0573103880129eb543f07b68c77e86f2f572f6bf.1780072238.git.qemu_oss@crudebyte.com
Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
(cherry picked from commit 116db2986b11c914217bbd1547815b6c7efb944a)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 34ac2c3c9a..9718daab61 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -1802,6 +1802,25 @@ static bool name_is_illegal(const char *name)
return !*name || strchr(name, '/') != NULL;
}
+static int check_name(const char *name, V9fsPDU *pdu)
+{
+ int request_type = pdu->id;
+
+ if (name_is_illegal(name)) {
+ return -ENOENT;
+ }
+ if (!strcmp(name, ".") || !strcmp(name, "..")) {
+ /*
+ * TODO: The different error codes here are just there to preserve
+ * pre-existing behaviour of 9p server. In future it might make sense to
+ * consolidate this and e.g. just return -EINVAL for everyone.
+ */
+ return (request_type == P9_TRENAME || request_type == P9_TRENAMEAT ||
+ request_type == P9_TWSTAT) ? -EISDIR : -EEXIST;
+ }
+ return 0;
+}
+
static bool same_stat_id(const struct stat *a, const struct stat *b)
{
return a->st_dev == b->st_dev && a->st_ino == b->st_ino;
@@ -2152,13 +2171,8 @@ static void coroutine_fn v9fs_lcreate(void *opaque)
}
trace_v9fs_lcreate(pdu->tag, pdu->id, dfid, flags, mode, gid);
- if (name_is_illegal(name.data)) {
- err = -ENOENT;
- goto out_nofid;
- }
-
- if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
- err = -EEXIST;
+ err = check_name(name.data, pdu);
+ if (err < 0) {
goto out_nofid;
}
@@ -2840,13 +2854,8 @@ static void coroutine_fn v9fs_create(void *opaque)
}
trace_v9fs_create(pdu->tag, pdu->id, fid, name.data, perm, mode);
- if (name_is_illegal(name.data)) {
- err = -ENOENT;
- goto out_nofid;
- }
-
- if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
- err = -EEXIST;
+ err = check_name(name.data, pdu);
+ if (err < 0) {
goto out_nofid;
}
@@ -3034,13 +3043,8 @@ static void coroutine_fn v9fs_symlink(void *opaque)
}
trace_v9fs_symlink(pdu->tag, pdu->id, dfid, name.data, symname.data, gid);
- if (name_is_illegal(name.data)) {
- err = -ENOENT;
- goto out_nofid;
- }
-
- if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
- err = -EEXIST;
+ err = check_name(name.data, pdu);
+ if (err < 0) {
goto out_nofid;
}
@@ -3127,13 +3131,8 @@ static void coroutine_fn v9fs_link(void *opaque)
}
trace_v9fs_link(pdu->tag, pdu->id, dfid, oldfid, name.data);
- if (name_is_illegal(name.data)) {
- err = -ENOENT;
- goto out_nofid;
- }
-
- if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
- err = -EEXIST;
+ err = check_name(name.data, pdu);
+ if (err < 0) {
goto out_nofid;
}
@@ -3364,13 +3363,8 @@ static void coroutine_fn v9fs_rename(void *opaque)
goto out_nofid;
}
- if (name_is_illegal(name.data)) {
- err = -ENOENT;
- goto out_nofid;
- }
-
- if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
- err = -EISDIR;
+ err = check_name(name.data, pdu);
+ if (err < 0) {
goto out_nofid;
}
@@ -3505,14 +3499,12 @@ static void coroutine_fn v9fs_renameat(void *opaque)
goto out_err;
}
- if (name_is_illegal(old_name.data) || name_is_illegal(new_name.data)) {
- err = -ENOENT;
+ err = check_name(old_name.data, pdu);
+ if (err < 0) {
goto out_err;
}
-
- if (!strcmp(".", old_name.data) || !strcmp("..", old_name.data) ||
- !strcmp(".", new_name.data) || !strcmp("..", new_name.data)) {
- err = -EISDIR;
+ err = check_name(new_name.data, pdu);
+ if (err < 0) {
goto out_err;
}
@@ -3617,12 +3609,8 @@ static void coroutine_fn v9fs_wstat(void *opaque)
err = -EOPNOTSUPP;
goto out;
}
- if (name_is_illegal(v9stat.name.data)) {
- err = -ENOENT;
- goto out;
- }
- if (!strcmp(".", v9stat.name.data) || !strcmp("..", v9stat.name.data)) {
- err = -EISDIR;
+ err = check_name(v9stat.name.data, pdu);
+ if (err < 0) {
goto out;
}
@@ -3755,13 +3743,8 @@ static void coroutine_fn v9fs_mknod(void *opaque)
}
trace_v9fs_mknod(pdu->tag, pdu->id, fid, mode, major, minor);
- if (name_is_illegal(name.data)) {
- err = -ENOENT;
- goto out_nofid;
- }
-
- if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
- err = -EEXIST;
+ err = check_name(name.data, pdu);
+ if (err < 0) {
goto out_nofid;
}
@@ -3917,13 +3900,8 @@ static void coroutine_fn v9fs_mkdir(void *opaque)
}
trace_v9fs_mkdir(pdu->tag, pdu->id, fid, name.data, mode, gid);
- if (name_is_illegal(name.data)) {
- err = -ENOENT;
- goto out_nofid;
- }
-
- if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
- err = -EEXIST;
+ err = check_name(name.data, pdu);
+ if (err < 0) {
goto out_nofid;
}
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* Re: [Stable-10.0.11 79/86] hw/9pfs: consolidate name validation with check_name()
2026-06-24 5:02 ` [Stable-10.0.11 79/86] hw/9pfs: consolidate name validation with check_name() Michael Tokarev
@ 2026-06-24 7:15 ` Christian Schoenebeck
2026-06-24 7:35 ` Michael Tokarev
0 siblings, 1 reply; 33+ messages in thread
From: Christian Schoenebeck @ 2026-06-24 7:15 UTC (permalink / raw)
To: qemu-devel, Greg Kurz; +Cc: qemu-stable, Michael Tokarev
Hi Michael,
On Wednesday, 24 June 2026 07:02:50 CEST Michael Tokarev wrote:
> From: Christian Schoenebeck <qemu_oss@crudebyte.com>
>
> Add a new, shared helper function check_name() that consolidates the name
> validation logic (illegal name check and "." / ".." rejection) currently
> spread over multiple 9p handlers, unnecessarily duplicating code.
>
> This is pure refactoring with no behavior change. The existing error code
> semantics are preserved: rename operations return -EISDIR, create
> operations return -EEXIST.
Note that this particular patch is actually not a fix. It is just code
deduplication. So my expecation was that this patch would not go to the stable
branches, therefore I intentionally omitted to CC qemu-stable on this patch.
/Christian
> Note: These current error codes actually differ from native Linux system
> calls (e.g. rename() returns -EBUSY, open(O_CREAT) returns -EISDIR). The 9P
> protocol does not mandate specific error codes for these validation errors.
> Hence consolidating to a single error code (e.g., -EINVAL) for all cases
> could be considered in the future for simplicity reason.
>
> This change reduces code duplication across 9 functions:
>
> - v9fs_lcreate
> - v9fs_create
> - v9fs_symlink
> - v9fs_link
> - v9fs_rename
> - v9fs_renameat
> - v9fs_wstat
> - v9fs_mknod
> - v9fs_mkdir
>
> Link:
> https://lore.kernel.org/qemu-devel/0573103880129eb543f07b68c77e86f2f572f6bf
> .1780072238.git.qemu_oss@crudebyte.com Signed-off-by: Christian Schoenebeck
> <qemu_oss@crudebyte.com>
> (cherry picked from commit 116db2986b11c914217bbd1547815b6c7efb944a)
> Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [Stable-10.0.11 79/86] hw/9pfs: consolidate name validation with check_name()
2026-06-24 7:15 ` Christian Schoenebeck
@ 2026-06-24 7:35 ` Michael Tokarev
0 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 7:35 UTC (permalink / raw)
To: Christian Schoenebeck, qemu-devel, Greg Kurz; +Cc: qemu-stable
On 24.06.2026 10:15, Christian Schoenebeck wrote:
> Hi Michael,
>
> On Wednesday, 24 June 2026 07:02:50 CEST Michael Tokarev wrote:
>> From: Christian Schoenebeck <qemu_oss@crudebyte.com>
>>
>> Add a new, shared helper function check_name() that consolidates the name
>> validation logic (illegal name check and "." / ".." rejection) currently
>> spread over multiple 9p handlers, unnecessarily duplicating code.
>>
>> This is pure refactoring with no behavior change. The existing error code
>> semantics are preserved: rename operations return -EISDIR, create
>> operations return -EEXIST.
>
> Note that this particular patch is actually not a fix. It is just code
> deduplication. So my expecation was that this patch would not go to the stable
> branches, therefore I intentionally omitted to CC qemu-stable on this patch.
Aha. Ok.
You sent cover letter for this series to qemu-stable@, so I assumed the
whole thing should go. Removed it now (here and in other series too).
Thank you for letting me know!
/mjt
^ permalink raw reply [flat|nested] 33+ messages in thread
* [Stable-10.0.11 80/86] ui/sdl2: Set GL ES profile before creating initial GL context
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (22 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 79/86] hw/9pfs: consolidate name validation with check_name() Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 81/86] target/xtensa: add cpu_set_fcr/fsr helpers to sync fp_status Michael Tokarev
` (5 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-stable, Ryan Zhang, Marc-André Lureau, Michael Tokarev
From: Ryan Zhang <mailto>
When the user selects GLES via '-display sdl,gl=es', we need to set
SDL_GL_CONTEXT_PROFILE_MASK to SDL_GL_CONTEXT_PROFILE_ES before
calling SDL_GL_CreateContext(). This ensures SDL_GL_LoadLibrary()
loads the correct GLES driver instead of the desktop OpenGL driver.
Fix the below issue: qemu-system-aarch64: /usr/src/debug/libepoxy
/1.5.10/src/dispatch_common.c:872: epoxy_get_proc_address: Assertion
`0 && "Couldn't find current GLX or EGL context.\n"' failed.
sdl2_gl_create_context() already sets the profile mask correctly for
ES mode, but the initial context created in sdl2_window_create() is
missing the same treatment.
Fixes:da3f7a3ab9ea0091955b58f8909dfcee01f4043e ("ui/sdl: try to instantiate the matching opengl renderer")
Signed-off-by: ryan.zhang@nxp.com
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <DU2PR04MB9018BB3650BA218438C01F2A83042@DU2PR04MB9018.eurprd04.prod.outlook.com>
(cherry picked from commit 490a3e1867f025c68fa13db766b5c8da16c6eca4)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/ui/sdl2.c b/ui/sdl2.c
index b00e421f7f..c798654c99 100644
--- a/ui/sdl2.c
+++ b/ui/sdl2.c
@@ -109,6 +109,8 @@ void sdl2_window_create(struct sdl2_console *scon)
if (scon->opts->gl == DISPLAY_GL_MODE_ES) {
driver = "opengles2";
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
+ SDL_GL_CONTEXT_PROFILE_ES);
}
SDL_SetHint(SDL_HINT_RENDER_DRIVER, driver);
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 81/86] target/xtensa: add cpu_set_fcr/fsr helpers to sync fp_status
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (23 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 80/86] ui/sdl2: Set GL ES profile before creating initial GL context Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 82/86] linux-user/xtensa: save/restore FP registers across signal delivery Michael Tokarev
` (4 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-stable, Matt Turner, Richard Henderson, Helge Deller,
Michael Tokarev
From: Matt Turner <mattst88@gmail.com>
Factor FCR→fp_status and FSR→fp_status synchronisation out of the
wur_fpu{2k,}_fcr/wur_fpu_fsr helpers into cpu_set_fcr(), cpu_set_fsr(),
and cpu_get_fsr(). Signal delivery code needs to restore the FP rounding
mode and exception flags without duplicating the flag-mapping tables.
cpu_set_fcr() applies the union mask 0xfffff07f (superset of the
wur_fpu_fcr mask 0x0000007f and the wur_fpu2k_fcr mask 0xfffff07f) so
that FCR bits valid only on fpu2k configs are preserved while MBZ bits
7-11 are always cleared.
Signed-off-by: Matt Turner <mattst88@gmail.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Helge Deller <deller@gmx.de>
(cherry picked from commit 7e859bacea09a626c239f14ab9c01f13d5225723)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index 8d70bfc0cd..03bde931e8 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -641,6 +641,10 @@ static inline void xtensa_select_static_vectors(CPUXtensaState *env,
}
void xtensa_runstall(CPUXtensaState *env, bool runstall);
+uint32_t cpu_get_fsr(CPUXtensaState *env);
+void cpu_set_fcr(CPUXtensaState *env, uint32_t v);
+void cpu_set_fsr(CPUXtensaState *env, uint32_t v);
+
#define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
#define XTENSA_OPTION_ALL (~(uint64_t)0)
diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c
index 53fc7cfd2a..89190d75c8 100644
--- a/target/xtensa/fpu_helper.c
+++ b/target/xtensa/fpu_helper.c
@@ -65,46 +65,39 @@ void xtensa_use_first_nan(CPUXtensaState *env, bool use_first)
&env->fp_status);
}
-void HELPER(wur_fpu2k_fcr)(CPUXtensaState *env, uint32_t v)
+uint32_t cpu_get_fsr(CPUXtensaState *env)
{
- static const int rounding_mode[] = {
- float_round_nearest_even,
- float_round_to_zero,
- float_round_up,
- float_round_down,
- };
+ uint32_t flags = 0;
+ int fef = get_float_exception_flags(&env->fp_status);
+ unsigned i;
- env->uregs[FCR] = v & 0xfffff07f;
- set_float_rounding_mode(rounding_mode[v & 3], &env->fp_status);
+ for (i = 0; i < ARRAY_SIZE(xtensa_fp_flag_map); ++i) {
+ if (fef & xtensa_fp_flag_map[i].softfloat_fp_flag) {
+ flags |= xtensa_fp_flag_map[i].xtensa_fp_flag;
+ }
+ }
+ return flags << XTENSA_FSR_FLAGS_SHIFT;
}
-void HELPER(wur_fpu_fcr)(CPUXtensaState *env, uint32_t v)
+void cpu_set_fcr(CPUXtensaState *env, uint32_t v)
{
- static const int rounding_mode[] = {
+ static const FloatRoundMode rounding_mode[] = {
float_round_nearest_even,
float_round_to_zero,
float_round_up,
float_round_down,
};
- if (v & 0xfffff000) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "MBZ field of FCR is written non-zero: %08x\n", v);
- }
- env->uregs[FCR] = v & 0x0000007f;
+ env->uregs[FCR] = v & 0xfffff07f;
set_float_rounding_mode(rounding_mode[v & 3], &env->fp_status);
}
-void HELPER(wur_fpu_fsr)(CPUXtensaState *env, uint32_t v)
+void cpu_set_fsr(CPUXtensaState *env, uint32_t v)
{
uint32_t flags = v >> XTENSA_FSR_FLAGS_SHIFT;
int fef = 0;
unsigned i;
- if (v & 0xfffff000) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "MBZ field of FSR is written non-zero: %08x\n", v);
- }
env->uregs[FSR] = v & 0x00000f80;
for (i = 0; i < ARRAY_SIZE(xtensa_fp_flag_map); ++i) {
if (flags & xtensa_fp_flag_map[i].xtensa_fp_flag) {
@@ -114,19 +107,35 @@ void HELPER(wur_fpu_fsr)(CPUXtensaState *env, uint32_t v)
set_float_exception_flags(fef, &env->fp_status);
}
-uint32_t HELPER(rur_fpu_fsr)(CPUXtensaState *env)
+void HELPER(wur_fpu2k_fcr)(CPUXtensaState *env, uint32_t v)
{
- uint32_t flags = 0;
- int fef = get_float_exception_flags(&env->fp_status);
- unsigned i;
+ cpu_set_fcr(env, v);
+}
- for (i = 0; i < ARRAY_SIZE(xtensa_fp_flag_map); ++i) {
- if (fef & xtensa_fp_flag_map[i].softfloat_fp_flag) {
- flags |= xtensa_fp_flag_map[i].xtensa_fp_flag;
- }
+void HELPER(wur_fpu_fcr)(CPUXtensaState *env, uint32_t v)
+{
+ if (v & 0xfffff000) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "MBZ field of FCR is written non-zero: %08x\n", v);
}
- env->uregs[FSR] = flags << XTENSA_FSR_FLAGS_SHIFT;
- return flags << XTENSA_FSR_FLAGS_SHIFT;
+ cpu_set_fcr(env, v & 0x0000007f);
+}
+
+void HELPER(wur_fpu_fsr)(CPUXtensaState *env, uint32_t v)
+{
+ if (v & 0xfffff000) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "MBZ field of FSR is written non-zero: %08x\n", v);
+ }
+ cpu_set_fsr(env, v);
+}
+
+uint32_t HELPER(rur_fpu_fsr)(CPUXtensaState *env)
+{
+ uint32_t fsr = cpu_get_fsr(env);
+
+ env->uregs[FSR] = fsr;
+ return fsr;
}
float64 HELPER(abs_d)(float64 v)
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 82/86] linux-user/xtensa: save/restore FP registers across signal delivery
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (24 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 81/86] target/xtensa: add cpu_set_fcr/fsr helpers to sync fp_status Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 83/86] linux-user/xtensa: fix unlock of uninitialized frame pointer on sigreturn Michael Tokarev
` (3 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-stable, Matt Turner, Richard Henderson, Helge Deller,
Michael Tokarev
From: Matt Turner <mattst88@gmail.com>
Add support for saving and restoring f0-f15 across signal delivery.
The target_xtensa_xtregs_fp struct carries 32-bit f-regs for cores
with XTENSA_OPTION_FP_COPROCESSOR; target_xtensa_xtregs_dfp carries
64-bit f-regs for cores with XTENSA_OPTION_DFP_COPROCESSOR.
Lock the xtregs region via lock_user before reading on sigreturn,
since sc_xtregs is a user-space pointer that may lie outside the
locked sigframe.
Signed-off-by: Matt Turner <mattst88@gmail.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Helge Deller <deller@gmx.de>
(cherry picked from commit 6858e3a71cc41510937bec0950eb4e42e33ba5f2)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/linux-user/xtensa/signal.c b/linux-user/xtensa/signal.c
index 6514b8dd57..fb1a3b86c1 100644
--- a/linux-user/xtensa/signal.c
+++ b/linux-user/xtensa/signal.c
@@ -21,6 +21,7 @@
#include "user-internals.h"
#include "signal-common.h"
#include "linux-user/trace.h"
+#include "target/xtensa/cpu.h"
struct target_sigcontext {
abi_ulong sc_pc;
@@ -43,10 +44,25 @@ struct target_ucontext {
target_sigset_t tuc_sigmask;
};
+struct target_xtensa_xtregs_fp {
+ uint32_t f[16];
+ uint32_t fcr;
+ uint32_t fsr;
+};
+
+struct target_xtensa_xtregs_dfp {
+ uint64_t f[16];
+ uint32_t fcr;
+ uint32_t fsr;
+};
+
struct target_rt_sigframe {
target_siginfo_t info;
struct target_ucontext uc;
- /* TODO: xtregs */
+ union {
+ struct target_xtensa_xtregs_fp fp;
+ struct target_xtensa_xtregs_dfp dfp;
+ } xtregs;
uint8_t retcode[6];
abi_ulong window[4];
};
@@ -107,6 +123,7 @@ static int flush_window_regs(CPUXtensaState *env)
}
static int setup_sigcontext(struct target_rt_sigframe *frame,
+ abi_ulong frame_addr,
CPUXtensaState *env)
{
struct target_sigcontext *sc = &frame->uc.tuc_mcontext;
@@ -123,8 +140,25 @@ static int setup_sigcontext(struct target_rt_sigframe *frame,
for (i = 0; i < 16; ++i) {
__put_user(env->regs[i], sc->sc_a + i);
}
- __put_user(0, &sc->sc_xtregs);
- /* TODO: xtregs */
+ if (xtensa_option_enabled(env->config, XTENSA_OPTION_DFP_COPROCESSOR)) {
+ for (i = 0; i < 16; ++i) {
+ __put_user(env->fregs[i].f64, &frame->xtregs.dfp.f[i]);
+ }
+ __put_user(env->uregs[FCR], &frame->xtregs.dfp.fcr);
+ __put_user(cpu_get_fsr(env), &frame->xtregs.dfp.fsr);
+ __put_user(frame_addr + offsetof(struct target_rt_sigframe, xtregs),
+ &sc->sc_xtregs);
+ } else if (xtensa_option_enabled(env->config, XTENSA_OPTION_FP_COPROCESSOR)) {
+ for (i = 0; i < 16; ++i) {
+ __put_user(env->fregs[i].f32[FP_F32_LOW], &frame->xtregs.fp.f[i]);
+ }
+ __put_user(env->uregs[FCR], &frame->xtregs.fp.fcr);
+ __put_user(cpu_get_fsr(env), &frame->xtregs.fp.fsr);
+ __put_user(frame_addr + offsetof(struct target_rt_sigframe, xtregs),
+ &sc->sc_xtregs);
+ } else {
+ __put_user(0, &sc->sc_xtregs);
+ }
return 1;
}
@@ -190,7 +224,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
__put_user(0, &frame->uc.tuc_flags);
__put_user(0, &frame->uc.tuc_link);
target_save_altstack(&frame->uc.tuc_stack, env);
- if (!setup_sigcontext(frame, env)) {
+ if (!setup_sigcontext(frame, frame_addr, env)) {
unlock_user_struct(frame, frame_addr, 0);
goto give_sigsegv;
}
@@ -244,8 +278,8 @@ give_sigsegv:
return;
}
-static void restore_sigcontext(CPUXtensaState *env,
- struct target_rt_sigframe *frame)
+static int restore_sigcontext(CPUXtensaState *env,
+ struct target_rt_sigframe *frame)
{
struct target_sigcontext *sc = &frame->uc.tuc_mcontext;
uint32_t ps;
@@ -267,7 +301,51 @@ static void restore_sigcontext(CPUXtensaState *env,
for (i = 0; i < 16; ++i) {
__get_user(env->regs[i], sc->sc_a + i);
}
- /* TODO: xtregs */
+ {
+ abi_ulong xtregs_addr;
+
+ __get_user(xtregs_addr, &sc->sc_xtregs);
+ if (xtregs_addr) {
+ if (xtensa_option_enabled(env->config,
+ XTENSA_OPTION_DFP_COPROCESSOR)) {
+ struct target_xtensa_xtregs_dfp *xtregs;
+ uint32_t fcr, fsr;
+
+ xtregs = lock_user(VERIFY_READ, xtregs_addr,
+ sizeof(*xtregs), 1);
+ if (!xtregs) {
+ return 0;
+ }
+ for (i = 0; i < 16; ++i) {
+ __get_user(env->fregs[i].f64, &xtregs->f[i]);
+ }
+ __get_user(fcr, &xtregs->fcr);
+ __get_user(fsr, &xtregs->fsr);
+ unlock_user(xtregs, xtregs_addr, 0);
+ cpu_set_fcr(env, fcr);
+ cpu_set_fsr(env, fsr);
+ } else if (xtensa_option_enabled(env->config,
+ XTENSA_OPTION_FP_COPROCESSOR)) {
+ struct target_xtensa_xtregs_fp *xtregs;
+ uint32_t fcr, fsr;
+
+ xtregs = lock_user(VERIFY_READ, xtregs_addr,
+ sizeof(*xtregs), 1);
+ if (!xtregs) {
+ return 0;
+ }
+ for (i = 0; i < 16; ++i) {
+ __get_user(env->fregs[i].f32[FP_F32_LOW], &xtregs->f[i]);
+ }
+ __get_user(fcr, &xtregs->fcr);
+ __get_user(fsr, &xtregs->fsr);
+ unlock_user(xtregs, xtregs_addr, 0);
+ cpu_set_fcr(env, fcr);
+ cpu_set_fsr(env, fsr);
+ }
+ }
+ }
+ return 1;
}
long do_rt_sigreturn(CPUXtensaState *env)
@@ -283,7 +361,9 @@ long do_rt_sigreturn(CPUXtensaState *env)
target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
set_sigmask(&set);
- restore_sigcontext(env, frame);
+ if (!restore_sigcontext(env, frame)) {
+ goto badframe;
+ }
target_restore_altstack(&frame->uc.tuc_stack, env);
unlock_user_struct(frame, frame_addr, 0);
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 83/86] linux-user/xtensa: fix unlock of uninitialized frame pointer on sigreturn
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (25 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 82/86] linux-user/xtensa: save/restore FP registers across signal delivery Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 84/86] ppc/pnv_phb3: Error out on invalid config access Michael Tokarev
` (2 subsequent siblings)
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-stable, Matt Turner, Helge Deller, Michael Tokarev
From: Matt Turner <mattst88@gmail.com>
If lock_user_struct fails, frame is uninitialized but the badframe
label unconditionally calls unlock_user_struct on it. Handle the
lock failure inline so badframe is only reached with a valid lock.
Signed-off-by: Matt Turner <mattst88@gmail.com>
Cc: qemu-stable@nongnu.org
Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Helge Deller <deller@gmx.de>
(cherry picked from commit 54e08dbe8f2aeca57e3b1a5eab09a9fec88c1c67)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/linux-user/xtensa/signal.c b/linux-user/xtensa/signal.c
index fb1a3b86c1..49a4d4bb53 100644
--- a/linux-user/xtensa/signal.c
+++ b/linux-user/xtensa/signal.c
@@ -356,7 +356,8 @@ long do_rt_sigreturn(CPUXtensaState *env)
trace_user_do_rt_sigreturn(env, frame_addr);
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
- goto badframe;
+ force_sig(TARGET_SIGSEGV);
+ return -QEMU_ESIGRETURN;
}
target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
set_sigmask(&set);
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 84/86] ppc/pnv_phb3: Error out on invalid config access
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (26 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 83/86] linux-user/xtensa: fix unlock of uninitialized frame pointer on sigreturn Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 85/86] hw/pci: Replace assert with bounds check and return Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 86/86] linux-user: Fix AT_PHDR when program headers are relocated into their own segment Michael Tokarev
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-stable, Aditya Gupta, Zexiang Zhang, Michael S. Tsirkin,
Michael Tokarev
From: Aditya Gupta <adityag@linux.ibm.com>
PHB in Power8 supports 8 byte registers, and hence the ops structure
allows accessing of 8 bytes in 'pnv_phb3_reg_ops'
Both 'pnv_phb3_reg_read' & 'pnv_phb3_reg_write' pass the arguments as is
to 'pnv_phb3_config_{read,write}', if offset is PHB_CONFIG_DATA.
This when called with size as 8, causes following assert failure in
'pci_host_config_read_common' & 'pci_host_config_write_common':
assert(len <= 4);
Validate that size is <=4, before jumping to pci_host_config_{read,write}_common
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3334
Reported-by: Zexiang Zhang <chan9yan9@gmail.com>
Fixes: 9ae1329ee2fe ("ppc/pnv: Add models for POWER8 PHB3 PCIe Host bridge")
Signed-off-by: Aditya Gupta <adityag@linux.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260326190438.734239-2-adityag@linux.ibm.com>
(cherry picked from commit 218109781209f9d77242b2cdf743acac8bc3b893)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c
index 82884e1e92..3c0956f994 100644
--- a/hw/pci-host/pnv_phb3.c
+++ b/hw/pci-host/pnv_phb3.c
@@ -474,6 +474,11 @@ void pnv_phb3_reg_write(void *opaque, hwaddr off, uint64_t val, unsigned size)
/* Special case configuration data */
if ((off & 0xfffc) == PHB_CONFIG_DATA) {
+ if (size > 4) {
+ phb3_error(phb, "Invalid config access, offset: 0x%"PRIx64" size: %d",
+ off, size);
+ return;
+ }
pnv_phb3_config_write(phb, off & 0x3, size, val);
return;
}
@@ -596,6 +601,11 @@ uint64_t pnv_phb3_reg_read(void *opaque, hwaddr off, unsigned size)
uint64_t val;
if ((off & 0xfffc) == PHB_CONFIG_DATA) {
+ if (size > 4) {
+ phb3_error(phb, "Invalid config access, offset: 0x%"PRIx64" size: %d",
+ off, size);
+ return ~0ull;
+ }
return pnv_phb3_config_read(phb, off & 0x3, size);
}
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 85/86] hw/pci: Replace assert with bounds check and return
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (27 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 84/86] ppc/pnv_phb3: Error out on invalid config access Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
2026-06-24 5:02 ` [Stable-10.0.11 86/86] linux-user: Fix AT_PHDR when program headers are relocated into their own segment Michael Tokarev
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-stable, Aditya Gupta, Zexiang Zhang, Michael S. Tsirkin,
Michael Tokarev
From: Aditya Gupta <adityag@linux.ibm.com>
As reported in https://gitlab.com/qemu-project/qemu/-/work_items/3334,
callers of 'pci_host_config_{read,write}_common' can pass length as 8,
causing an assert failure
The original issue with pnv_phb3 triggering the assert was fixed in a
previous commit
Instead of asserting on invalid length, check if the length is valid
(<=4), otherwise return (with the failure error code in read)
Reported-by: Zexiang Zhang <chan9yan9@gmail.com>
Signed-off-by: Aditya Gupta <adityag@linux.ibm.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260326190438.734239-3-adityag@linux.ibm.com>
(cherry picked from commit c7209c56718107fefd5deae140a450954d31ff2b)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c
index 56f7f28a1a..37a8d186d6 100644
--- a/hw/pci/pci_host.c
+++ b/hw/pci/pci_host.c
@@ -81,7 +81,12 @@ void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,
return;
}
- assert(len <= 4);
+ if (len > 4) {
+ PCI_DPRINTF("%s: invalid length access: addr " HWADDR_FMT_plx " \
+ len %d val %"PRIx32"\n", __func__, addr, len, val);
+ return;
+ }
+
/* non-zero functions are only exposed when function 0 is present,
* allowing direct removal of unexposed functions.
*/
@@ -106,7 +111,12 @@ uint32_t pci_host_config_read_common(PCIDevice *pci_dev, uint32_t addr,
return ~0x0;
}
- assert(len <= 4);
+ if (len > 4) {
+ PCI_DPRINTF("%s: invalid length access: addr " HWADDR_FMT_plx " \
+ len %d val %"PRIx32"\n", __func__, addr, len, val);
+ return ~0x0;
+ }
+
/* non-zero functions are only exposed when function 0 is present,
* allowing direct removal of unexposed functions.
*/
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread* [Stable-10.0.11 86/86] linux-user: Fix AT_PHDR when program headers are relocated into their own segment
2026-06-24 5:02 [Stable-10.0.11 v2 00/86] Patch Round-up for stable 10.0.11, freeze on 2026-06-23 (frozen) Michael Tokarev
` (28 preceding siblings ...)
2026-06-24 5:02 ` [Stable-10.0.11 85/86] hw/pci: Replace assert with bounds check and return Michael Tokarev
@ 2026-06-24 5:02 ` Michael Tokarev
29 siblings, 0 replies; 33+ messages in thread
From: Michael Tokarev @ 2026-06-24 5:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-stable, Akshit Yadav, Helge Deller, Michael Tokarev
From: Akshit Yadav <valium7171@gmail.com>
When a binary is patched or relocated such that the program header table is
moved into a separate PT_LOAD segment (rather than sitting at the start of the
first loadable segment), QEMU's AT_PHDR auxv entry becomes incorrect. The
loader was computing AT_PHDR as load_addr + e_phoff, which assumes the headers
are mapped 1:1 from file offset 0. This breaks when the headers are elsewhere.
The Linux kernel instead locates the PT_LOAD segment that contains e_phoff,
then computes the in-memory address as p_vaddr + (e_phoff - p_offset). This
correctly handles relocated headers.
Fix by:
1. Add phdr_addr field to image_info to cache the resolved address.
2. Initialize to load_addr + e_phoff (fallback for headers outside any PT_LOAD).
3. In the PT_LOAD mapping loop, detect if the segment contains e_phoff and
override with the segment-relative address.
4. Use info->phdr_addr for AT_PHDR instead of the incorrect formula.
Signed-off-by: Akshit Yadav <valium7171@gmail.com>
Reviewed-by: Helge Deller <deller@gmx.de>
(cherry picked from commit 156e536a7b9700018aaa2437072c14e3376340a7)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index a791396ead..fdc84de4ba 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -2627,7 +2627,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
/* There must be exactly DLINFO_ITEMS entries here, or the assert
* on info->auxv_len will trigger.
*/
- NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff));
+ NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->phdr_addr));
NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
@@ -3398,6 +3398,12 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
info->data_offset = load_bias;
info->load_addr = load_addr;
info->entry = ehdr->e_entry + load_bias;
+ /*
+ * Fallback for AT_PHDR if the program headers do not fall within
+ * any PT_LOAD segment (see the loop below, which overrides this with
+ * the correct in-memory address when a containing segment is found).
+ */
+ info->phdr_addr = load_addr + ehdr->e_phoff;
info->start_code = -1;
info->end_code = 0;
info->start_data = -1;
@@ -3452,6 +3458,19 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
vaddr_ef = vaddr + eppnt->p_filesz;
vaddr_em = vaddr + eppnt->p_memsz;
+ /*
+ * If this segment contains the program headers, record their
+ * in-memory address for AT_PHDR. This matches the kernel, which
+ * locates the headers via the containing PT_LOAD rather than
+ * assuming load_addr + e_phoff (false when the phdrs are not
+ * mapped 1:1 from file offset 0, e.g. relocated into their own
+ * segment by a binary patcher).
+ */
+ if (eppnt->p_offset <= ehdr->e_phoff &&
+ ehdr->e_phoff < eppnt->p_offset + eppnt->p_filesz) {
+ info->phdr_addr = vaddr + (ehdr->e_phoff - eppnt->p_offset);
+ }
+
/*
* Some segments may be completely empty, with a non-zero p_memsz
* but no backing file segment.
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index f2b16ef54b..a8ead75074 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -25,6 +25,7 @@
struct image_info {
abi_ulong load_bias;
abi_ulong load_addr;
+ abi_ulong phdr_addr;
abi_ulong start_code;
abi_ulong end_code;
abi_ulong start_data;
--
2.47.3
^ permalink raw reply related [flat|nested] 33+ messages in thread