x86: Secure Memory Encryption (SME) fixes 2017-07-26
Subsystems (3)
v2 cover x86: Secure Memory Encryption (SME) fixes 2017-07-26
This patch series addresses some issues found during further testing of Secure Memory Encryption (SME).
The following fixes are included in this update series:
- Fix a cache-related memory corruption when kexec is invoked in successive instances
- Remove the encryption mask from the protection properties returned by arch_apei_get_mem_attribute() when SME is active
---
This patch series is based off of the master branch of tip:
https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git master
Commit 8333bcad393c ("Merge branch 'x86/asm'")
Changes since v1:
- Patch #1:
- Only issue wbinvd if SME is active
- Patch #2:
- Create a no encryption version of the PAGE_KERNEL protection type and use that in arch_apei_get_mem_attribute()
- General comment and patch description clean up
Tom Lendacky (2):
x86/mm, kexec: Fix memory corruption with SME on successive kexecs acpi, x86: Remove encryption mask from ACPI page protection type
arch/x86/include/asm/acpi.h | 11 ++++++----- arch/x86/include/asm/kexec.h | 3 ++- arch/x86/include/asm/pgtable_types.h | 1 + arch/x86/kernel/machine_kexec_64.c | 3 ++- arch/x86/kernel/relocate_kernel_64.S | 14 ++++++++++++++ 5 files changed, 25 insertions(+), 7 deletions(-)
Signature · 1 line
1.9.1
PATCH v2 1/2 x86/mm, kexec: Fix memory corruption with SME on successive kexecs
After issuing successive kexecs it was found that the SHA hash failed verification when booting the kexec'd kernel. When SME is enabled, the change from using pages that were marked encrypted to now being marked as not encrypted (through new identify mapped page tables) results in memory corruption if there are any cache entries for the previously encrypted pages. This is because separate cache entries can exist for the same physical location but tagged both with and without the encryption bit.
To prevent this, issue a wbinvd if SME is active before copying the pages from the source location to the destination location to clear any possible cache entry conflicts.
--- arch/x86/include/asm/kexec.h | 3 ++- arch/x86/kernel/machine_kexec_64.c | 3 ++- arch/x86/kernel/relocate_kernel_64.S | 14 ++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-)
arch/x86/include/asm/kexec.h +2 -1
@@ -147,7 +147,8 @@ static inline void crash_setup_regs(struct pt_regs *newregs, relocate_kernel(unsigned long indirection_page, unsigned long page_list, unsigned long start_address, - unsigned int preserve_context); + unsigned int preserve_context, + unsigned int sme_active);#endif #define ARCH_HAS_KIMAGE_ARCH
arch/x86/kernel/machine_kexec_64.c +2 -1
@@ -335,7 +335,8 @@ void machine_kexec(struct kimage *image) image->start =relocate_kernel ((unsigned long )image->head, (unsigned long )page_list, image->start, - image->preserve_context); + image->preserve_context, +sme_active ());#ifdef CONFIG_KEXEC_JUMP if (image->preserve_context)
arch/x86/kernel/relocate_kernel_64.S +14 -0
@@ -47,6 +47,7 @@ relocate_kernel: * %rsi page_list * %rdx start address * %rcx preserve_context + * %r8 sme_active */ /* Save the CPU context, used for jumping back */
@@ -71,6 +72,9 @@ relocate_kernel: pushq $0 popfq + /* Save SME active flag */ + movq %r8, %r12 + /* * get physical address of control page now * this is impossible after page table switch
@@ -132,6 +136,16 @@ identity_mapped: /* Flush the TLB (needed?) */ movq %r9, %cr3 + /* + * If SME is active, there could be old encrypted cache line + * entries that will conflict with the now unencrypted memory + * used by kexec. Flush the caches before copying the kernel. + */ + testq %r12, %r12 + jz 1f + wbinvd +1: + movq %rcx, %r11 call swap_pages
Signature · 7 lines
1.9.1 _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
tip-bot for Tom Lendacky
merge bot[tip:x86/mm] x86/mm, kexec: Fix memory corruption with SME on successive kexecs
x86/mm, kexec: Fix memory corruption with SME on successive kexecs
Commit-ID: 4e237903f95db585b976e7311de2bfdaaf0f6e31 Gitweb: http://git.kernel.org/tip/4e237903f95db585b976e7311de2bfdaaf0f6e31 Author: Tom Lendacky <[email protected]> AuthorDate: Fri, 28 Jul 2017 11:01:16 -0500 Committer: Ingo Molnar <[email protected]> CommitDate: Sun, 30 Jul 2017 12:09:12 +0200
x86/mm, kexec: Fix memory corruption with SME on successive kexecs
After issuing successive kexecs it was found that the SHA hash failed verification when booting the kexec'd kernel. When SME is enabled, the change from using pages that were marked encrypted to now being marked as not encrypted (through new identify mapped page tables) results in memory corruption if there are any cache entries for the previously encrypted pages. This is because separate cache entries can exist for the same physical location but tagged both with and without the encryption bit.
To prevent this, issue a wbinvd if SME is active before copying the pages from the source location to the destination location to clear any possible cache entry conflicts.
--- arch/x86/include/asm/kexec.h | 3 ++- arch/x86/kernel/machine_kexec_64.c | 3 ++- arch/x86/kernel/relocate_kernel_64.S | 14 ++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-)
arch/x86/include/asm/kexec.h +2 -1
@@ -147,7 +147,8 @@ unsigned long relocate_kernel(unsigned long indirection_page, unsigned long page_list, unsigned long start_address, - unsigned int preserve_context); + unsigned int preserve_context, + unsigned int sme_active);#endif #define ARCH_HAS_KIMAGE_ARCH
arch/x86/kernel/machine_kexec_64.c +2 -1
@@ -335,7 +335,8 @@ void machine_kexec(struct kimage *image) image->start =relocate_kernel ((unsigned long )image->head, (unsigned long )page_list, image->start, - image->preserve_context); + image->preserve_context, +sme_active ());#ifdef CONFIG_KEXEC_JUMP if (image->preserve_context)
arch/x86/kernel/relocate_kernel_64.S +14 -0
@@ -47,6 +47,7 @@ relocate_kernel: * %rsi page_list * %rdx start address * %rcx preserve_context + * %r8 sme_active */ /* Save the CPU context, used for jumping back */
@@ -71,6 +72,9 @@ relocate_kernel: pushq $0 popfq + /* Save SME active flag */ + movq %r8, %r12 + /* * get physical address of control page now * this is impossible after page table switch
@@ -132,6 +136,16 @@ identity_mapped: /* Flush the TLB (needed?) */ movq %r9, %cr3 + /* + * If SME is active, there could be old encrypted cache line + * entries that will conflict with the now unencrypted memory + * used by kexec. Flush the caches before copying the kernel. + */ + testq %r12, %r12 + jz 1f + wbinvd +1: + movq %rcx, %r11 call swap_pages
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
PATCH v2 2/2 acpi, x86: Remove encryption mask from ACPI page protection type
In reply to Tom LendackyThe function arch_apei_get_mem_attributes() is used to set the page protection type for ACPI physical addresses. When SME is active, the associated protection type cannot have the encryption mask set since the ACPI tables live in un-encrypted memory. Create a new protection type, PAGE_KERNEL_NOENC, that is a no encryption version of PAGE_KERNEL, and return that from arch_apei_get_mem_attributes().
--- arch/x86/include/asm/acpi.h | 11 ++++++----- arch/x86/include/asm/pgtable_types.h | 1 + 2 files changed, 7 insertions(+), 5 deletions(-)
arch/x86/include/asm/acpi.h +6 -5
@@ -160,12 +160,13 @@ static inline pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr)* you call efi_mem_attributes() during boot and at runtime, * you could theoretically see different attributes. * -* Since we are yet to see any x86 platforms that require -* anything other than PAGE_KERNEL (some arm64 platforms -* require the equivalent of PAGE_KERNEL_NOCACHE), return that -* until we know differently. +* We are yet to see any x86 platforms that require anything +* other than PAGE_KERNEL (some arm64 platforms require the +* equivalent of PAGE_KERNEL_NOCACHE). Additionally, if SME +* is active, the ACPI information will not be encrypted, +* so return PAGE_KERNEL_NOENC until we know differently. */ - return PAGE_KERNEL; + return PAGE_KERNEL_NOENC; }#endif
arch/x86/include/asm/pgtable_types.h +1 -0
@@ -211,6 +211,7 @@ enum page_cache_mode {#define __PAGE_KERNEL_NOENC_WP (__PAGE_KERNEL_WP)#define PAGE_KERNEL __pgprot(__PAGE_KERNEL | _PAGE_ENC) +#define PAGE_KERNEL_NOENC __pgprot(__PAGE_KERNEL)#define PAGE_KERNEL_RO __pgprot(__PAGE_KERNEL_RO | _PAGE_ENC)#define PAGE_KERNEL_EXEC __pgprot(__PAGE_KERNEL_EXEC | _PAGE_ENC)#define PAGE_KERNEL_EXEC_NOENC __pgprot(__PAGE_KERNEL_EXEC)
Signature · 1 line
1.9.1
tip-bot for Tom Lendacky
merge bot[tip:x86/mm] acpi, x86/mm: Remove encryption mask from ACPI page protection type
acpi, x86/mm: Remove encryption mask from ACPI page protection type
Commit-ID: 57bd1905b228f2a14d7506b0302f69f425131e57 Gitweb: http://git.kernel.org/tip/57bd1905b228f2a14d7506b0302f69f425131e57 Author: Tom Lendacky <[email protected]> AuthorDate: Fri, 28 Jul 2017 11:01:17 -0500 Committer: Ingo Molnar <[email protected]> CommitDate: Sun, 30 Jul 2017 12:09:12 +0200
acpi, x86/mm: Remove encryption mask from ACPI page protection type
The arch_apei_get_mem_attributes() function is used to set the page protection type for ACPI physical addresses. When SME is active, the associated protection type cannot have the encryption mask set since the ACPI tables live in un-encrypted memory - the kernel will see corrupted data.
To fix this, create a new protection type, PAGE_KERNEL_NOENC, that is a 'no encryption' version of PAGE_KERNEL, and return that from arch_apei_get_mem_attributes().
--- arch/x86/include/asm/acpi.h | 11 ++++++----- arch/x86/include/asm/pgtable_types.h | 1 + 2 files changed, 7 insertions(+), 5 deletions(-)
arch/x86/include/asm/acpi.h +6 -5
@@ -160,12 +160,13 @@ static inline pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr)* you call efi_mem_attributes() during boot and at runtime, * you could theoretically see different attributes. * -* Since we are yet to see any x86 platforms that require -* anything other than PAGE_KERNEL (some arm64 platforms -* require the equivalent of PAGE_KERNEL_NOCACHE), return that -* until we know differently. +* We are yet to see any x86 platforms that require anything +* other than PAGE_KERNEL (some ARM64 platforms require the +* equivalent of PAGE_KERNEL_NOCACHE). Additionally, if SME +* is active, the ACPI information will not be encrypted, +* so return PAGE_KERNEL_NOENC until we know differently. */ - return PAGE_KERNEL; + return PAGE_KERNEL_NOENC; }#endif
arch/x86/include/asm/pgtable_types.h +1 -0
@@ -211,6 +211,7 @@ enum page_cache_mode {#define __PAGE_KERNEL_NOENC_WP (__PAGE_KERNEL_WP)#define PAGE_KERNEL __pgprot(__PAGE_KERNEL | _PAGE_ENC) +#define PAGE_KERNEL_NOENC __pgprot(__PAGE_KERNEL)#define PAGE_KERNEL_RO __pgprot(__PAGE_KERNEL_RO | _PAGE_ENC)#define PAGE_KERNEL_EXEC __pgprot(__PAGE_KERNEL_EXEC | _PAGE_ENC)#define PAGE_KERNEL_EXEC_NOENC __pgprot(__PAGE_KERNEL_EXEC)