diff options
author | Ben Hutchings <ben@decadent.org.uk> | 2020-03-15 20:36:09 +0000 |
---|---|---|
committer | Ben Hutchings <ben@decadent.org.uk> | 2020-03-15 20:36:09 +0000 |
commit | 9e461bc0d8d58574c8df60ca6ca3dafa90f22309 (patch) | |
tree | ccea9e1d6edbe5541ab0eaf30f17356aff294bcc /queue-3.16 | |
parent | b84ce9d4df142ac3ce783f644d347b984e3cb455 (diff) | |
download | linux-stable-queue-9e461bc0d8d58574c8df60ca6ca3dafa90f22309.tar.gz |
Add PTI/EFI stable-specific fix
Diffstat (limited to 'queue-3.16')
-rw-r--r-- | queue-3.16/series | 1 | ||||
-rw-r--r-- | queue-3.16/x86-pti-efi-broken-conversion-from-efi-to-kernel-page-table.patch | 118 |
2 files changed, 119 insertions, 0 deletions
diff --git a/queue-3.16/series b/queue-3.16/series index 33bdfe06..4cbd9ac4 100644 --- a/queue-3.16/series +++ b/queue-3.16/series @@ -52,3 +52,4 @@ dm-do-not-override-error-code-returned-from-dm_get_device.patch dm-flakey-return-einval-on-interval-bounds-error-in-flakey_ctr.patch dm-flakey-fix-reads-to-be-issued-if-drop_writes-configured.patch dm-flakey-check-for-null-arg_name-in-parse_features.patch +x86-pti-efi-broken-conversion-from-efi-to-kernel-page-table.patch diff --git a/queue-3.16/x86-pti-efi-broken-conversion-from-efi-to-kernel-page-table.patch b/queue-3.16/x86-pti-efi-broken-conversion-from-efi-to-kernel-page-table.patch new file mode 100644 index 00000000..dd1d4182 --- /dev/null +++ b/queue-3.16/x86-pti-efi-broken-conversion-from-efi-to-kernel-page-table.patch @@ -0,0 +1,118 @@ +From: Pavel Tatashin <pasha.tatashin@oracle.com> +Date: Fri, 12 Jan 2018 15:00:02 -0500 +Subject: x86/pti/efi: broken conversion from efi to kernel page table + +In entry_64.S we have code like this: + + /* Unconditionally use kernel CR3 for do_nmi() */ + /* %rax is saved above, so OK to clobber here */ + ALTERNATIVE "jmp 2f", "movq %cr3, %rax", X86_FEATURE_KAISER + /* If PCID enabled, NOFLUSH now and NOFLUSH on return */ + ALTERNATIVE "", "bts $63, %rax", X86_FEATURE_PCID + pushq %rax + /* mask off "user" bit of pgd address and 12 PCID bits: */ + andq $(~(X86_CR3_PCID_ASID_MASK | KAISER_SHADOW_PGD_OFFSET)), %rax + movq %rax, %cr3 +2: + + /* paranoidentry do_nmi, 0; without TRACE_IRQS_OFF */ + call do_nmi + +With this instruction: + andq $(~(X86_CR3_PCID_ASID_MASK | KAISER_SHADOW_PGD_OFFSET)), %rax + +We unconditionally switch from whatever our CR3 was to kernel page table. +But, in arch/x86/platform/efi/efi_64.c We temporarily set a different page +table, that does not have the kernel page table with 0x1000 offset from it. + +Look in efi_thunk() and efi_thunk_set_virtual_address_map(). + +So, while CR3 points to the other page table, we get an NMI interrupt, +and clear 0x1000 from CR3, resulting in a bogus CR3 if the 0x1000 bit was +set. + +The efi page table comes from realmode/rm/trampoline_64.S: + +arch/x86/realmode/rm/trampoline_64.S + +141 .bss +142 .balign PAGE_SIZE +143 GLOBAL(trampoline_pgd) .space PAGE_SIZE + +Notice: alignment is PAGE_SIZE, so after applying KAISER_SHADOW_PGD_OFFSET +which equal to PAGE_SIZE, we can get a different page table. + +But, even if we fix alignment, here the trampoline binary is later copied +into dynamically allocated memory in reserve_real_mode(), so we need to +fix that place as well. + +Fixes: f9a1666f97b3 ("KAISER: Kernel Address Isolation") +Signed-off-by: Pavel Tatashin <pasha.tatashin@oracle.com> +Reviewed-by: Steven Sistare <steven.sistare@oracle.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +[bwh: Adjust the Fixes field for 3.16] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/x86/include/asm/kaiser.h | 10 ++++++++++ + arch/x86/realmode/init.c | 4 +++- + arch/x86/realmode/rm/trampoline_64.S | 3 ++- + 3 files changed, 15 insertions(+), 2 deletions(-) + +--- a/arch/x86/include/asm/kaiser.h ++++ b/arch/x86/include/asm/kaiser.h +@@ -19,6 +19,16 @@ + + #define KAISER_SHADOW_PGD_OFFSET 0x1000 + ++#ifdef CONFIG_PAGE_TABLE_ISOLATION ++/* ++ * A page table address must have this alignment to stay the same when ++ * KAISER_SHADOW_PGD_OFFSET mask is applied ++ */ ++#define KAISER_KERNEL_PGD_ALIGNMENT (KAISER_SHADOW_PGD_OFFSET << 1) ++#else ++#define KAISER_KERNEL_PGD_ALIGNMENT PAGE_SIZE ++#endif ++ + #ifdef __ASSEMBLY__ + #ifdef CONFIG_PAGE_TABLE_ISOLATION + +--- a/arch/x86/realmode/init.c ++++ b/arch/x86/realmode/init.c +@@ -4,6 +4,7 @@ + #include <asm/cacheflush.h> + #include <asm/pgtable.h> + #include <asm/realmode.h> ++#include <asm/kaiser.h> + + struct real_mode_header *real_mode_header; + u32 *trampoline_cr4_features; +@@ -15,7 +16,8 @@ void __init reserve_real_mode(void) + size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob); + + /* Has to be under 1M so we can execute real-mode AP code. */ +- mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE); ++ mem = memblock_find_in_range(0, 1 << 20, size, ++ KAISER_KERNEL_PGD_ALIGNMENT); + if (!mem) + panic("Cannot allocate trampoline\n"); + +--- a/arch/x86/realmode/rm/trampoline_64.S ++++ b/arch/x86/realmode/rm/trampoline_64.S +@@ -30,6 +30,7 @@ + #include <asm/msr.h> + #include <asm/segment.h> + #include <asm/processor-flags.h> ++#include <asm/kaiser.h> + #include "realmode.h" + + .text +@@ -139,7 +140,7 @@ tr_gdt: + tr_gdt_end: + + .bss +- .balign PAGE_SIZE ++ .balign KAISER_KERNEL_PGD_ALIGNMENT + GLOBAL(trampoline_pgd) .space PAGE_SIZE + + .balign 8 |