]> 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 20:27:03 +0000 (23:27 +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 d18c1dbf2cb78cabb5130ffe332822b0ddf299c2..b2a2b671b0d61bc3acd600f19296ad20e68d35ef 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 c07b1b16ea171ad96e3c121da45c2d9a3319bc6d..891f7bac46210da340aeeb313db9c9da854f2ab1 100644 (file)
@@ -617,6 +617,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 b07cc9f9b12483568201a26833297d4ab919074c..ea7e42d06888174fe7aa2628e39ff4a460a72575 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: