[PATCH RFC v2 28/29] x86/pti: Disable PTI when ASI is on

Brendan Jackman
2025-01-10T18:49:17Z

Now that ASI has support for sandboxing userspace, although userspace
now has much more mapped than it would under KPTI, in theory none of
that data is important to protect.

Note that one particular impact of this is it makes locally defeating
KASLR easier. I don't think this is a great loss given [1] etc.

Why do we pass in an argument instead of just having
pti_check_boottime_disable() check boot_cpu_has(X86_FEATURE_ASI)? Just
for clarity: I wanted it to be at least _sort of_ visible that it would
break if you reordered asi_check_boottime_disable() afterwards.

[1]: https://gruss.cc/files/prefetch.pdf
and https://dl.acm.org/doi/pdf/10.1145/3623652.3623669

Signed-off-by: Brendan Jackman <jackmanb@google.com>
---
arch/x86/include/asm/pti.h | 6 ++++--
arch/x86/mm/init.c | 2 +-
arch/x86/mm/pti.c | 14 +++++++++++++-
3 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/arch/x86/include/asm/pti.h b/arch/x86/include/asm/pti.h
index ab167c96b9ab474b33d778453db0bb550f42b0ac..79b9ba927db9b76ac3cc72cdda6f8b5fc413d352 100644
--- a/arch/x86/include/asm/pti.h
+++ b/arch/x86/include/asm/pti.h
@@ -3,12 +3,14 @@
#define _ASM_X86_PTI_H
#ifndef __ASSEMBLY__

+#include <linux/types.h>
+
#ifdef CONFIG_MITIGATION_PAGE_TABLE_ISOLATION
extern void pti_init(void);
-extern void pti_check_boottime_disable(void);
+extern void pti_check_boottime_disable(bool asi_enabled);
extern void pti_finalize(void);
#else
-static inline void pti_check_boottime_disable(void) { }
+static inline void pti_check_boottime_disable(bool asi_enabled) { }
#endif

#endif /* __ASSEMBLY__ */
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index ded3a47f2a9c1f554824d4ad19f3b48bce271274..4ccf6d60705652805342abefc5e71cd00c563207 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -754,8 +754,8 @@ void __init init_mem_mapping(void)
{
unsigned long end;

- pti_check_boottime_disable();
asi_check_boottime_disable();
+ pti_check_boottime_disable(boot_cpu_has(X86_FEATURE_ASI));
probe_page_size_mask();
setup_pcid();

diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c
index 851ec8f1363a8b389ea4579cc68bf3300a4df27c..b7132080d3c9b6962a0252383190335e171bafa6 100644
--- a/arch/x86/mm/pti.c
+++ b/arch/x86/mm/pti.c
@@ -76,7 +76,7 @@ static enum pti_mode {
PTI_FORCE_ON
} pti_mode;

-void __init pti_check_boottime_disable(void)
+void __init pti_check_boottime_disable(bool asi_enabled)
{
if (hypervisor_is_type(X86_HYPER_XEN_PV)) {
pti_mode = PTI_FORCE_OFF;
@@ -91,6 +91,18 @@ void __init pti_check_boottime_disable(void)
return;
}

+ if (asi_enabled) {
+ /*
+ * Having both ASI and PTI enabled is not a totally ridiculous
+ * thing to do; if you want ASI but you are not confident in the
+ * sensitivity annotations then it provides useful
+ * defence-in-depth. But, the implementation doesn't support it.
+ */
+ if (pti_mode != PTI_FORCE_OFF)
+ pti_print_if_insecure("disabled by ASI");
+ return;
+ }
+
if (pti_mode == PTI_FORCE_ON)
pti_print_if_secure("force enabled on command line.");

--
2.47.1.613.gc27f4b7a9f-goog