* [PULL 1/5] target/i386: tcg: remove FIXME
2026-07-22 7:39 [PULL 0/5] Misc 2026-07-22 changes for QEMU 11.1rc Paolo Bonzini
@ 2026-07-22 7:39 ` Paolo Bonzini
2026-07-22 7:39 ` [PULL 2/5] meson: propagate qemu_ldflags to Rust link step Paolo Bonzini
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Paolo Bonzini @ 2026-07-22 7:39 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/emit.c.inc | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
index 83c889cc3b2..e4ef5a87580 100644
--- a/target/i386/tcg/emit.c.inc
+++ b/target/i386/tcg/emit.c.inc
@@ -3424,7 +3424,9 @@ 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?
+ * A count that is a nonzero multiple of (8 << op) + 1 reduces to 0 and leaves
+ * CF and OF unmodified (confirmed against hardware that rcl $9,%al behaves
+ * exactly like rcl $0,%al).
*/
static MemOp gen_rotc_count(DisasContext *s, X86DecodedInsn *decode,
bool *can_be_zero, TCGv *count, int unit)
--
2.55.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PULL 2/5] meson: propagate qemu_ldflags to Rust link step
2026-07-22 7:39 [PULL 0/5] Misc 2026-07-22 changes for QEMU 11.1rc Paolo Bonzini
2026-07-22 7:39 ` [PULL 1/5] target/i386: tcg: remove FIXME Paolo Bonzini
@ 2026-07-22 7:39 ` Paolo Bonzini
2026-07-22 7:39 ` [PULL 3/5] target/i386: helper_sysret(): Check that RCX contains a canonical address when emulating an Intel CPU Paolo Bonzini
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Paolo Bonzini @ 2026-07-22 7:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Brian Cain, Pierrick Bouvier
From: Brian Cain <brian.cain@oss.qualcomm.com>
Sanitizer flags are added to qemu_ldflags and applied globally for
all_languages, but all_languages never includes 'rust'.
Fixes link errors like the ones below:
-Wl,-rpath,$ORIGIN/../qemu-macros:<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/lib"
= note: some arguments are omitted. use `--verbose` to show all linker arguments
= note: rust-lld: error: undefined symbol: __ubsan_handle_type_mismatch_v1
>>> referenced by event-loop-base.c:104 (../qemu_before_fix/event-loop-base.c:104)
>>> libevent-loop-base.a.p/event-loop-base.c.o:(event_loop_base_class_init)
>>> referenced by event-loop-base.c:105 (../qemu_before_fix/event-loop-base.c:105)
>>> libevent-loop-base.a.p/event-loop-base.c.o:(event_loop_base_class_init)
>>> referenced by event-loop-base.c:58 (../qemu_before_fix/event-loop-base.c:58)
>>> libevent-loop-base.a.p/event-loop-base.c.o:(event_loop_base_set_param)
>>> referenced 11240 more times
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20260714021236.2361604-1-brian.cain@oss.qualcomm.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
meson.build | 3 +++
1 file changed, 3 insertions(+)
diff --git a/meson.build b/meson.build
index 164328ded83..5f42bbf40c7 100644
--- a/meson.build
+++ b/meson.build
@@ -767,6 +767,9 @@ endif
add_project_arguments(cc.get_supported_arguments(qemu_common_flags + qemu_cflags + warn_flags),
native: false, language: 'c')
add_global_link_arguments(qemu_ldflags, native: false, language: all_languages)
+if have_rust
+ add_global_link_arguments(qemu_ldflags, native: false, language: 'rust')
+endif
if 'cpp' in all_languages
add_project_arguments(cxx.get_supported_arguments(qemu_common_flags + qemu_cxxflags),
--
2.55.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PULL 3/5] target/i386: helper_sysret(): Check that RCX contains a canonical address when emulating an Intel CPU
2026-07-22 7:39 [PULL 0/5] Misc 2026-07-22 changes for QEMU 11.1rc Paolo Bonzini
2026-07-22 7:39 ` [PULL 1/5] target/i386: tcg: remove FIXME Paolo Bonzini
2026-07-22 7:39 ` [PULL 2/5] meson: propagate qemu_ldflags to Rust link step Paolo Bonzini
@ 2026-07-22 7:39 ` Paolo Bonzini
2026-07-22 7:39 ` [PULL 4/5] scsi-disk: protect against guest sending truncated data for MODE SELECT commands Paolo Bonzini
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Paolo Bonzini @ 2026-07-22 7:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Andrey Polivoda, Richard Henderson
From: Andrey Polivoda <apolivodaa433@gmail.com>
Intel and AMD CPUs implement SYSRETQ instruction differently.
One of these differences is whether a canonicality check of the address that
will be loaded to RIP is performed: Intel CPUs do this check, AMD CPUs don't.
Currently, QEMU does not perform this check when emulating Intel CPUs.
This patch corrects this by implementing the canonlicality check on a new RIP
value from RCX and performing it only when emulating Intel CPUs.
Flags and segment registers' caches are updated only after checking the new RIP
value to ensure that CPU state is not modified in case the #GP(0) exception
is raised due to the check failure.
Cc: qemu-devel@nongnu.org
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Richard Henderson <richard.henderson@linaro.org>
Fixes: 14ce26e75513 ("x86_64 target support")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3223
Signed-off-by: Andrey Polivoda <apolivodaa433@gmail.com>
Link: https://lore.kernel.org/r/20260608091815.31303-1-apolivodaa433@gmail.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
target/i386/tcg/seg_helper.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/target/i386/tcg/seg_helper.c b/target/i386/tcg/seg_helper.c
index 58aac720119..d5c174b7fd7 100644
--- a/target/i386/tcg/seg_helper.c
+++ b/target/i386/tcg/seg_helper.c
@@ -1096,17 +1096,22 @@ void helper_sysret(CPUX86State *env, int dflag)
selector = (env->star >> 48) & 0xffff;
#ifdef TARGET_X86_64
if (env->hflags & HF_LMA_MASK) {
- cpu_load_eflags(env, (uint32_t)(env->regs[11]), TF_MASK | AC_MASK
- | ID_MASK | IF_MASK | IOPL_MASK | VM_MASK | RF_MASK |
- NT_MASK);
if (dflag == 2) {
+ uint64_t new_rip = env->regs[R_ECX];
+ if (IS_INTEL_CPU(env)) {
+ int shift = (get_pg_mode(env) & PG_MODE_LA57) ? 56 : 47;
+ int64_t sext = (int64_t)new_rip >> shift;
+ if (sext != 0 && sext != -1) {
+ raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
+ }
+ }
cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3,
0, 0xffffffff,
DESC_G_MASK | DESC_P_MASK |
DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK |
DESC_L_MASK);
- env->eip = env->regs[R_ECX];
+ env->eip = new_rip;
} else {
cpu_x86_load_seg_cache(env, R_CS, selector | 3,
0, 0xffffffff,
@@ -1120,6 +1125,10 @@ void helper_sysret(CPUX86State *env, int dflag)
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
DESC_W_MASK | DESC_A_MASK);
+
+ cpu_load_eflags(env, (uint32_t)(env->regs[11]), TF_MASK | AC_MASK
+ | ID_MASK | IF_MASK | IOPL_MASK | VM_MASK | RF_MASK |
+ NT_MASK);
} else
#endif
{
--
2.55.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PULL 4/5] scsi-disk: protect against guest sending truncated data for MODE SELECT commands
2026-07-22 7:39 [PULL 0/5] Misc 2026-07-22 changes for QEMU 11.1rc Paolo Bonzini
` (2 preceding siblings ...)
2026-07-22 7:39 ` [PULL 3/5] target/i386: helper_sysret(): Check that RCX contains a canonical address when emulating an Intel CPU Paolo Bonzini
@ 2026-07-22 7:39 ` Paolo Bonzini
2026-07-22 7:39 ` [PULL 5/5] scsi-disk: fix off by one in assertion Paolo Bonzini
2026-07-22 17:58 ` [PULL 0/5] Misc 2026-07-22 changes for QEMU 11.1rc Stefan Hajnoczi
5 siblings, 0 replies; 7+ messages in thread
From: Paolo Bonzini @ 2026-07-22 7:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Mark Cave-Ayland
scsi-disk has a MODE SELECT path where a truncated mode page can be
allowed by a compatibility quirk, but the parser continues to use the
page's declared length rather than the number of bytes actually remaining
in the request buffer. This means that scsi_disk_check_mode_select() and
scsi_disk_apply_mode_select() can read beyond the valid part of inbuf[],
potentially up to the emulated age's length.
Clamping page_len (the size of the page) to len (whatever the
guest provided) ensures that scsi_disk_check_mode_select() and
scsi_disk_apply_mode_select() do not access anything beyond bounds;
however, this requires care to accept and handle truncated input in
those two functions.
In particular, until scsi_disk_check_mode_select()'s first call to
mode_sense_page() the number of bytes to be cleared in mode_current[] is
unknown, so zero it completely. And for everything else, be conservative
and use len when providing inputs to other functions; but at the same time,
ensure all accesses to inbuf[] are bound by expected_len.
Note that pages longer than the emulated one are still rejected.
Fixes: 389e18eb9aa4 ("scsi-disk: add SCSI_DISK_QUIRK_MODE_PAGE_TRUNCATED quirk for Macintosh")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4051
Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/scsi/scsi-disk.c | 21 +++++++++++++--------
1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 5ba5b46c4f4..85d0bd0b811 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -1524,7 +1524,7 @@ static void scsi_disk_emulate_read_data(SCSIRequest *req)
static int scsi_disk_check_mode_select(SCSIDiskState *s, int page,
uint8_t *inbuf, int inlen)
{
- uint8_t mode_current[SCSI_MAX_MODE_LEN];
+ uint8_t mode_current[SCSI_MAX_MODE_LEN] = { 0 };
uint8_t mode_changeable[SCSI_MAX_MODE_LEN];
uint8_t *p;
int len, expected_len, changeable_len, i;
@@ -1543,21 +1543,21 @@ static int scsi_disk_check_mode_select(SCSIDiskState *s, int page,
}
p = mode_current;
- memset(mode_current, 0, inlen + 2);
len = mode_sense_page(s, page, &p, 0);
- if (len < 0 || len != expected_len) {
+ /* The guest may send a truncated page, but not a longer one. */
+ if (len < 0 || expected_len > len) {
return -1;
}
p = mode_changeable;
- memset(mode_changeable, 0, inlen + 2);
+ memset(mode_changeable, 0, len);
changeable_len = mode_sense_page(s, page, &p, 1);
assert(changeable_len == len);
/* Check that unchangeable bits are the same as what MODE SENSE
* would return.
*/
- for (i = 2; i < len; i++) {
+ for (i = 2; i < expected_len; i++) {
if (((mode_current[i] ^ inbuf[i - 2]) & ~mode_changeable[i]) != 0) {
return -1;
}
@@ -1565,11 +1565,15 @@ static int scsi_disk_check_mode_select(SCSIDiskState *s, int page,
return 0;
}
-static void scsi_disk_apply_mode_select(SCSIDiskState *s, int page, uint8_t *p)
+/* Note p may be truncated, so check any bytes you access against len. */
+static void scsi_disk_apply_mode_select(SCSIDiskState *s, int page,
+ uint8_t *p, int len)
{
switch (page) {
case MODE_PAGE_CACHING:
- blk_set_enable_write_cache(s->qdev.conf.blk, (p[0] & 4) != 0);
+ if (len > 0) {
+ blk_set_enable_write_cache(s->qdev.conf.blk, (p[0] & 4) != 0);
+ }
break;
default:
@@ -1612,6 +1616,7 @@ static int mode_select_pages(SCSIDiskReq *r, uint8_t *p, int len, bool change)
goto invalid_param_len;
}
trace_scsi_disk_mode_select_page_truncated(page, page_len, len);
+ page_len = len;
}
if (!change) {
@@ -1619,7 +1624,7 @@ static int mode_select_pages(SCSIDiskReq *r, uint8_t *p, int len, bool change)
goto invalid_param;
}
} else {
- scsi_disk_apply_mode_select(s, page, p);
+ scsi_disk_apply_mode_select(s, page, p, page_len);
}
p += page_len;
--
2.55.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PULL 5/5] scsi-disk: fix off by one in assertion
2026-07-22 7:39 [PULL 0/5] Misc 2026-07-22 changes for QEMU 11.1rc Paolo Bonzini
` (3 preceding siblings ...)
2026-07-22 7:39 ` [PULL 4/5] scsi-disk: protect against guest sending truncated data for MODE SELECT commands Paolo Bonzini
@ 2026-07-22 7:39 ` Paolo Bonzini
2026-07-22 17:58 ` [PULL 0/5] Misc 2026-07-22 changes for QEMU 11.1rc Stefan Hajnoczi
5 siblings, 0 replies; 7+ messages in thread
From: Paolo Bonzini @ 2026-07-22 7:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
When documenting the invariant that mode pages need to fit the smallest
output buffer of all callers (which is SCSI_MAX_MODE_LEN), the expression
used by the assertion was incorrect.
Even though SCSI_MAX_MODE_LEN is indeed 256, using "length < 256" had
two issues: 1) it used the wrong operator, since "length < ..." is more
related to having room for extra data; 2) it missed the extra two bytes
for page number and length.
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/scsi/scsi-disk.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 85d0bd0b811..1b0cce128c5 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -1321,7 +1321,7 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
return -1;
}
- assert(length < 256);
+ assert(length + 2 <= SCSI_MAX_MODE_LEN);
(*p_outbuf)[0] = page;
(*p_outbuf)[1] = length;
*p_outbuf += length + 2;
--
2.55.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PULL 0/5] Misc 2026-07-22 changes for QEMU 11.1rc
2026-07-22 7:39 [PULL 0/5] Misc 2026-07-22 changes for QEMU 11.1rc Paolo Bonzini
` (4 preceding siblings ...)
2026-07-22 7:39 ` [PULL 5/5] scsi-disk: fix off by one in assertion Paolo Bonzini
@ 2026-07-22 17:58 ` Stefan Hajnoczi
5 siblings, 0 replies; 7+ messages in thread
From: Stefan Hajnoczi @ 2026-07-22 17:58 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 116 bytes --]
Applied, thanks.
Please update the changelog at https://wiki.qemu.org/ChangeLog/11.1 for any user-visible changes.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread