]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
i386/cpu: Prevent delivering SIPI during SMM in TCG mode
authorPaolo Bonzini <pbonzini@redhat.com>
Sat, 11 Oct 2025 07:13:29 +0000 (09:13 +0200)
committerMichael Tokarev <mjt@tls.msk.ru>
Wed, 15 Oct 2025 04:31:18 +0000 (07:31 +0300)
[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 <zhuyifei@google.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit df32e5c568c9cf68c15a9bbd98d0c3aff19eab63)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
hw/intc/apic.c
target/i386/helper.c
target/i386/tcg/system/seg_helper.c

index bcb103560c726d6207325305f833b6457bf954a8..143d08f1aa62ca672fbe46e0ac56aed47e7d087a 100644 (file)
@@ -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);
index e0aaed3c4c4e0ff8dbe0d4fee10bd95e091e5736..693a95558f329980b9d41ff8217194c166e43e93 100644 (file)
@@ -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);
 }
 
index d4ea890c12440c56e11a739de6a0b289d62f666b..e7d76e41d23ff788073f9524168133ceb410ee7d 100644 (file)
@@ -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: