This commit serves to provide a minimal framework to present an ASI integration into the page allocator, without getting distracted by irrelevant details. There's no need to review this actively, just refer back to it as-needed when reading the later patches. In a real [PATCH] series this should be several separate commits. Aside from missing the actual core address-space switching and security logic, this is missing runtime-disablement of ASI. If you enable it in Kconfig, ASI's mm logic gets run unconditionally. That isn't what we want in the real implementation (certainly not in the initial version, anyway). - Add CONFIG_MITIGATION_ADDRESS_SPACE_ISOLATION. Attempt to follow the proposal by Mike Rapoport here: https://lore.kernel.org/linux-mm/Z8K2B3WJoICVbDj3@xxxxxxxxxx/ In this RFC, there's only a small amount of x86-specific logic, perhaps it's possible to implement this logic without any arch/ dependency. But, this is absolutely not true of the full ASI implementation. So that's already reflected in the Kconfig stuff here. - Introduce struct asi, which is an "ASI domain", i.e. an address space. For now this is nothing but a wrapper for a PGD. - Introduce the "global nonsensitive" ASI domain. This contains all the mappings that do not need to be protected from any attacker. Maintaining these mappings is the subject of this RFC. Signed-off-by: Brendan Jackman <jackmanb@xxxxxxxxxx> --- arch/Kconfig | 14 ++++++++++++++ arch/x86/Kconfig | 1 + arch/x86/include/asm/asi.h | 28 ++++++++++++++++++++++++++++ arch/x86/mm/Makefile | 1 + arch/x86/mm/asi.c | 8 ++++++++ arch/x86/mm/init.c | 3 ++- include/linux/asi.h | 18 ++++++++++++++++++ 7 files changed, 72 insertions(+), 1 deletion(-) diff --git a/arch/Kconfig b/arch/Kconfig index b8a4ff36558228240080a5677f702d37f4f8d547..871ad0987c8740205ceec675a6b7304c644f28e1 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -17,6 +17,20 @@ config CPU_MITIGATIONS def_bool y endif +config ARCH_HAS_MITIGATION_ADDRESS_SPACE_ISOLATION + bool + +config MITIGATION_ADDRESS_SPACE_ISOLATION + bool "Allow code to run with a reduced kernel address space" + default n + depends on ARCH_HAS_MITIGATION_ADDRESS_SPACE_ISOLATION && !PARAVIRT + help + This feature provides the ability to run some kernel code + with a reduced kernel address space. This can be used to + mitigate some speculative execution attacks. + + !PARAVIRT dependency is a temporary hack while ASI has custom + pagetable manipulation code. # # Selected by architectures that need custom DMA operations for e.g. legacy # IOMMUs not handled by dma-iommu. Drivers must never select this symbol. diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 0e27ebd7e36a9e3d69ad3e77c8db5dcf11ae3016..19ceecf5978bbe62e0742072c192c8ee952082dc 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -36,6 +36,7 @@ config X86_64 select ARCH_HAS_ELFCORE_COMPAT select ZONE_DMA32 select EXECMEM if DYNAMIC_FTRACE + select ARCH_HAS_MITIGATION_ADDRESS_SPACE_ISOLATION config FORCE_DYNAMIC_FTRACE def_bool y diff --git a/arch/x86/include/asm/asi.h b/arch/x86/include/asm/asi.h new file mode 100644 index 0000000000000000000000000000000000000000..b8f604df6a36508acbc10710f821d5f95e8cdceb --- /dev/null +++ b/arch/x86/include/asm/asi.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_X86_ASI_H +#define _ASM_X86_ASI_H + +#include <asm/pgtable_types.h> + +#ifdef CONFIG_MITIGATION_ADDRESS_SPACE_ISOLATION + +extern struct asi __asi_global_nonsensitive; +#define ASI_GLOBAL_NONSENSITIVE (&__asi_global_nonsensitive) + +/* + * An ASI domain (struct asi) represents a restricted address space. The + * unrestricted address space (and user address space under PTI) are not + * represented as a domain. + */ +struct asi { + pgd_t *pgd; +}; + +static __always_inline pgd_t *asi_pgd(struct asi *asi) +{ + return asi ? asi->pgd : NULL; +} + +#endif /* CONFIG_MITIGATION_ADDRESS_SPACE_ISOLATION */ + +#endif /* _ASM_X86_ASI_H */ diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile index 690fbf48e8538b62a176ce838820e363575b7897..89ade7363798cc20d5e5643526eba7378174baa0 100644 --- a/arch/x86/mm/Makefile +++ b/arch/x86/mm/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_ACPI_NUMA) += srat.o obj-$(CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS) += pkeys.o obj-$(CONFIG_RANDOMIZE_MEMORY) += kaslr.o obj-$(CONFIG_MITIGATION_PAGE_TABLE_ISOLATION) += pti.o +obj-$(CONFIG_MITIGATION_ADDRESS_SPACE_ISOLATION) += asi.o obj-$(CONFIG_X86_MEM_ENCRYPT) += mem_encrypt.o obj-$(CONFIG_AMD_MEM_ENCRYPT) += mem_encrypt_amd.o diff --git a/arch/x86/mm/asi.c b/arch/x86/mm/asi.c new file mode 100644 index 0000000000000000000000000000000000000000..e5a981a7b3192655cd981633514fbf945b92c9b6 --- /dev/null +++ b/arch/x86/mm/asi.c @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <asm/asi.h> + +static __aligned(PAGE_SIZE) pgd_t asi_global_nonsensitive_pgd[PTRS_PER_PGD]; + +struct asi __asi_global_nonsensitive = { + .pgd = asi_global_nonsensitive_pgd, +}; diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 62aa4d66a032d59191e79d34fc0cdaa4f32f88db..44d3dc574881dd23bb48f9af3f6191be309405ef 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -250,7 +250,8 @@ static void __init probe_page_size_mask(void) /* By the default is everything supported: */ __default_kernel_pte_mask = __supported_pte_mask; /* Except when with PTI where the kernel is mostly non-Global: */ - if (cpu_feature_enabled(X86_FEATURE_PTI)) + if (cpu_feature_enabled(X86_FEATURE_PTI) || + IS_ENABLED(CONFIG_MITIGATION_ADDRESS_SPACE_ISOLATION)) __default_kernel_pte_mask &= ~_PAGE_GLOBAL; /* Enable 1 GB linear kernel mappings if available: */ diff --git a/include/linux/asi.h b/include/linux/asi.h new file mode 100644 index 0000000000000000000000000000000000000000..2d3049d5fe423e139dcce8f3d68cdffcc0ec0bfe --- /dev/null +++ b/include/linux/asi.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _INCLUDE_ASI_H +#define _INCLUDE_ASI_H + +#include <asm/pgtable_types.h> + +#ifdef CONFIG_MITIGATION_ADDRESS_SPACE_ISOLATION +#include <asm/asi.h> +#else + +#define ASI_GLOBAL_NONSENSITIVE NULL + +struct asi {}; + +static inline pgd_t *asi_pgd(struct asi *asi) { return NULL; } + +#endif /* CONFIG_MITIGATION_ADDRESS_SPACE_ISOLATION */ +#endif /* _INCLUDE_ASI_H */ -- 2.49.0.rc1.451.g8f38331e32-goog