* meson: propagate qemu_ldflags to Rust link step

* target/i386: helper_sysret(): Check that RCX contains a canonical address when emulating an Intel CPU
 * target/i386: tcg: remove FIXME
 * scsi-disk: protect against guest sending truncated data for MODE SELECT commands
 * scsi-disk: fix off by one in assertion
 -----BEGIN PGP SIGNATURE-----
 
 iQFIBAABCgAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmpgcwoUHHBib256aW5p
 QHJlZGhhdC5jb20ACgkQv/vSX3jHroPfhwf+PLJ73Xf71TyKsRp0q+aEBHuT0v+h
 KYSAzjqhKF3MvzTJXm/NBpnCQjxQ1FCypwcUvbDF/amOBjP/FQnFUORZMrFNkRIr
 LQqnuI4SSLkYBsx+/uCnZ2WsoELh0te/I/WqhjuimUhjQau93qLPByBaE0p3ifl6
 kWqeq7lgiLFSgJxOZPXfyFZPmYvfLQatO0LVArydkcNjIMhPi1sZ2ZEBrqbV/QnA
 pEpKkbeiS2t7x/kYCQ+X2scLiReWfVz1VHnufSI6L8+8/S4UE1Y3FaQcyfuPFFBC
 urgInhQqjrs+2e9BQa14yD5A4G9gYOn1+vL6yB/aJ2bYlvPxhw/u7XojNQ==
 =mZw/
 -----END PGP SIGNATURE-----

Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging

* meson: propagate qemu_ldflags to Rust link step
* target/i386: helper_sysret(): Check that RCX contains a canonical address when emulating an Intel CPU
* target/i386: tcg: remove FIXME
* scsi-disk: protect against guest sending truncated data for MODE SELECT commands
* scsi-disk: fix off by one in assertion

# -----BEGIN PGP SIGNATURE-----
#
# iQFIBAABCgAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmpgcwoUHHBib256aW5p
# QHJlZGhhdC5jb20ACgkQv/vSX3jHroPfhwf+PLJ73Xf71TyKsRp0q+aEBHuT0v+h
# KYSAzjqhKF3MvzTJXm/NBpnCQjxQ1FCypwcUvbDF/amOBjP/FQnFUORZMrFNkRIr
# LQqnuI4SSLkYBsx+/uCnZ2WsoELh0te/I/WqhjuimUhjQau93qLPByBaE0p3ifl6
# kWqeq7lgiLFSgJxOZPXfyFZPmYvfLQatO0LVArydkcNjIMhPi1sZ2ZEBrqbV/QnA
# pEpKkbeiS2t7x/kYCQ+X2scLiReWfVz1VHnufSI6L8+8/S4UE1Y3FaQcyfuPFFBC
# urgInhQqjrs+2e9BQa14yD5A4G9gYOn1+vL6yB/aJ2bYlvPxhw/u7XojNQ==
# =mZw/
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 22 Jul 2026 03:36:42 EDT
# gpg:                using RSA key F13338574B662389866C7682BFFBD25F78C7AE83
# gpg:                issuer "pbonzini@redhat.com"
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full]
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>" [full]
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4  E2F7 7E15 100C CD36 69B1
#      Subkey fingerprint: F133 3857 4B66 2389 866C  7682 BFFB D25F 78C7 AE83

* tag 'for-upstream' of https://gitlab.com/bonzini/qemu:
  scsi-disk: fix off by one in assertion
  scsi-disk: protect against guest sending truncated data for MODE SELECT commands
  target/i386: helper_sysret(): Check that RCX contains a canonical address when emulating an Intel CPU
  meson: propagate qemu_ldflags to Rust link step
  target/i386: tcg: remove FIXME

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2026-07-22 11:17:29 -04:00
commit c6bac4e201
4 changed files with 33 additions and 14 deletions

View file

@ -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;
@ -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;

View file

@ -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),

View file

@ -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)

View file

@ -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
{