From cf8dff8d9f92d75bbe16c391464b955fbb0d5720 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sat, 11 Oct 2025 09:13:29 +0200 Subject: [PATCH] i386/cpu: Prevent delivering SIPI during SMM in TCG mode [commit message by YiFei Zhu] A malicious kernel may control the instruction pointer in SMM in a multi-processor VM by sending a sequence of IPIs via APIC: CPU0 CPU1 IPI(CPU1, MODE_INIT) x86_cpu_exec_reset() apic_init_reset() s->wait_for_sipi = true IPI(CPU1, MODE_SMI) do_smm_enter() env->hflags |= HF_SMM_MASK; IPI(CPU1, MODE_STARTUP, vector) do_cpu_sipi() apic_sipi() /* s->wait_for_sipi check passes */ cpu_x86_load_seg_cache_sipi(vector) A different sequence, SMI INIT SIPI, is also buggy in TCG because INIT is not blocked or latched during SMM. However, it is not vulnerable to an instruction pointer control in the same way because x86_cpu_exec_reset clears env->hflags, exiting SMM. Fixes: a9bad65d2c1f ("target-i386: wake up processors that receive an SMI") Analyzed-by: YiFei Zhu Cc: qemu-stable@nongnu.org Signed-off-by: Paolo Bonzini (cherry picked from commit df32e5c568c9cf68c15a9bbd98d0c3aff19eab63) Signed-off-by: Michael Tokarev --- hw/intc/apic.c | 2 -- target/i386/helper.c | 4 ++++ target/i386/tcg/system/seg_helper.c | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/hw/intc/apic.c b/hw/intc/apic.c index bcb103560c7..143d08f1aa6 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -645,8 +645,6 @@ void apic_sipi(DeviceState *dev) { APICCommonState *s = APIC(dev); - cpu_reset_interrupt(CPU(s->cpu), CPU_INTERRUPT_SIPI); - if (!s->wait_for_sipi) return; cpu_x86_load_seg_cache_sipi(s->cpu, s->sipi_vector); diff --git a/target/i386/helper.c b/target/i386/helper.c index e0aaed3c4c4..693a95558f3 100644 --- a/target/i386/helper.c +++ b/target/i386/helper.c @@ -619,6 +619,10 @@ void do_cpu_init(X86CPU *cpu) void do_cpu_sipi(X86CPU *cpu) { + CPUX86State *env = &cpu->env; + if (env->hflags & HF_SMM_MASK) { + return; + } apic_sipi(cpu->apic_state); } diff --git a/target/i386/tcg/system/seg_helper.c b/target/i386/tcg/system/seg_helper.c index d4ea890c124..e7d76e41d23 100644 --- a/target/i386/tcg/system/seg_helper.c +++ b/target/i386/tcg/system/seg_helper.c @@ -182,6 +182,7 @@ bool x86_cpu_exec_interrupt(CPUState *cs, int interrupt_request) apic_poll_irq(cpu->apic_state); break; case CPU_INTERRUPT_SIPI: + cpu_reset_interrupt(cs, CPU_INTERRUPT_SIPI); do_cpu_sipi(cpu); break; case CPU_INTERRUPT_SMI: -- 2.47.3