@@ -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.
@@ -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
new file mode 100644
@@ -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 */
@@ -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
new file mode 100644
@@ -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,
+};
@@ -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: */
new file mode 100644
@@ -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 */
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@kernel.org/ 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@google.com> --- 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(-)