mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] KVM: x86: Inject #UD for AMD-compatible SYSEXIT in long mode
@ 2026-10-21  2:11 Hao Zhang
  0 siblings, 0 replies; only message in thread
From: Hao Zhang @ 2026-10-21  2:11 UTC (permalink / raw)
  To: Sean Christopherson; +Cc: Paolo Bonzini, kvm, linux-kernel

From: Hao Zhang <zhanghao1@kylinos.cn>

AMD specifies that SYSEXIT raises #UD in both 64-bit and compatibility
modes.  On AMD hosts, KVM intercepts the hardware #UD, but SYSEXIT is
marked EmulateOnUD and em_sysexit() applies Intel semantics without
checking the guest CPU vendor.

For an AMD-compatible guest at CPL0, this can incorrectly complete
the transition to CPL3 or inject #GP, depending on the SYSENTER_CS
value and other operands.  At nonzero CPL, the generic Priv check
injects #GP instead of the required #UD.

Inject #UD for AMD-compatible vCPUs when EFER.LMA is set, before
checking CPL or SYSENTER_CS and before modifying architectural state.

Move the CPL check into em_sysexit() and remove the opcode's Priv
flag so that the generic privilege check does not take precedence
over AMD's long-mode #UD.  Retain the existing #GP behavior for real
mode, virtual-8086 mode, and nonzero CPL outside the AMD long-mode
case.

See the SYSEXIT instruction description in AMD APM Volume 3.

Fixes: 4668f0507870 ("KVM: x86 emulator: Add sysexit emulation")
Signed-off-by: Hao Zhang <zhanghao1@kylinos.cn>
---
 arch/x86/kvm/emulate.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index c1b21282187f..2154a2f2fd92 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -2457,12 +2457,18 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
 	const struct x86_emulate_ops *ops = ctxt->ops;
 	struct desc_struct cs, ss;
 	u64 msr_data, rcx, rdx;
+	u64 efer = 0;
 	int usermode;
 	u16 cs_sel = 0, ss_sel = 0;
 
-	/* inject #GP if in real mode or Virtual 8086 mode */
+	/* AMD rejects SYSEXIT in both IA-32e submodes, even at CPL3. */
+	ops->get_msr(ctxt, MSR_EFER, &efer);
+	if ((efer & EFER_LMA) && !ops->guest_cpuid_is_intel_compatible(ctxt))
+		return emulate_ud(ctxt);
+
+	/* Check CPL here so that AMD's long-mode #UD takes precedence. */
 	if (ctxt->mode == X86EMUL_MODE_REAL ||
-	    ctxt->mode == X86EMUL_MODE_VM86)
+	    ctxt->mode == X86EMUL_MODE_VM86 || ops->cpl(ctxt))
 		return emulate_gp(ctxt, 0);
 
 	setup_syscalls_segments(&cs, &ss);
@@ -4390,7 +4396,7 @@ static const struct opcode twobyte_table[256] = {
 	II(ImplicitOps | Priv, em_rdmsr, rdmsr),
 	IIP(ImplicitOps, em_rdpmc, rdpmc, check_rdpmc),
 	I(ImplicitOps | EmulateOnUD | IsBranch | ShadowStack, em_sysenter),
-	I(ImplicitOps | Priv | EmulateOnUD | IsBranch | ShadowStack, em_sysexit),
+	I(ImplicitOps | EmulateOnUD | IsBranch | ShadowStack, em_sysexit),
 	N, N,
 	N, N, N, N, N, N, N, N,
 	/* 0x40 - 0x4F */

base-commit: 6c377d19d4a5116d9bec5203aa3c6c11523e7898
-- 
2.15.0


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-10-21  2:11 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-21  2:11 [PATCH] KVM: x86: Inject #UD for AMD-compatible SYSEXIT in long mode Hao Zhang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®