aac1e9a2f0
Approved by: bapt (implicit) MFH: 2017Q4 Sponsored by: Citrix Systems R&D
51 lines
2 KiB
Diff
51 lines
2 KiB
Diff
From: Andrew Cooper <andrew.cooper3@citrix.com>
|
|
Subject: x86/cpu: fix IST handling during PCPU bringup
|
|
|
|
Clear IST references in newly allocated IDTs. Nothing good will come of
|
|
having them set before the TSS is suitably constructed (although the chances
|
|
of the CPU surviving such an IST interrupt/exception is extremely slim).
|
|
|
|
Uniformly set the IST references after the TSS is in place. This fixes an
|
|
issue on AMD hardware, where onlining a PCPU while PCPU0 is in HVM context
|
|
will cause IST_NONE to be copied into the new IDT, making that PCPU vulnerable
|
|
to privilege escalation from PV guests until it subsequently schedules an HVM
|
|
guest.
|
|
|
|
This is XSA-244.
|
|
|
|
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
|
Reviewed-by: Jan Beulich <jbeulich@suse.com>
|
|
|
|
--- a/xen/arch/x86/cpu/common.c
|
|
+++ b/xen/arch/x86/cpu/common.c
|
|
@@ -617,6 +617,7 @@ void __init early_cpu_init(void)
|
|
* - Sets up TSS with stack pointers, including ISTs
|
|
* - Inserts TSS selector into regular and compat GDTs
|
|
* - Loads GDT, IDT, TR then null LDT
|
|
+ * - Sets up IST references in the IDT
|
|
*/
|
|
void load_system_tables(void)
|
|
{
|
|
@@ -663,6 +664,10 @@ void load_system_tables(void)
|
|
asm volatile ("lidt %0" : : "m" (idtr) );
|
|
asm volatile ("ltr %w0" : : "rm" (TSS_ENTRY << 3) );
|
|
asm volatile ("lldt %w0" : : "rm" (0) );
|
|
+
|
|
+ set_ist(&idt_tables[cpu][TRAP_double_fault], IST_DF);
|
|
+ set_ist(&idt_tables[cpu][TRAP_nmi], IST_NMI);
|
|
+ set_ist(&idt_tables[cpu][TRAP_machine_check], IST_MCE);
|
|
}
|
|
|
|
/*
|
|
--- a/xen/arch/x86/smpboot.c
|
|
+++ b/xen/arch/x86/smpboot.c
|
|
@@ -715,6 +715,9 @@ static int cpu_smpboot_alloc(unsigned in
|
|
if ( idt_tables[cpu] == NULL )
|
|
goto oom;
|
|
memcpy(idt_tables[cpu], idt_table, IDT_ENTRIES * sizeof(idt_entry_t));
|
|
+ set_ist(&idt_tables[cpu][TRAP_double_fault], IST_NONE);
|
|
+ set_ist(&idt_tables[cpu][TRAP_nmi], IST_NONE);
|
|
+ set_ist(&idt_tables[cpu][TRAP_machine_check], IST_NONE);
|
|
|
|
for ( stub_page = 0, i = cpu & ~(STUBS_PER_PAGE - 1);
|
|
i < nr_cpu_ids && i <= (cpu | (STUBS_PER_PAGE - 1)); ++i )
|