This sysctl supports a value from -1 to 1 which will let the administrator
decide whether or not to adjust the PTI behaviour per process.

Signed-off-by: Willy Tarreau <[email protected]>
Cc: Andy Lutomirski <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: Brian Gerst <[email protected]>
Cc: Dave Hansen <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Josh Poimboeuf <[email protected]>
Cc: "H. Peter Anvin" <[email protected]>
Cc: Kees Cook <[email protected]>
---
 arch/x86/include/asm/pti.h |  5 +++++
 arch/x86/mm/pti.c          | 19 +++++++++++++++++++
 kernel/sysctl.c            | 12 ++++++++++++
 3 files changed, 36 insertions(+)

diff --git a/arch/x86/include/asm/pti.h b/arch/x86/include/asm/pti.h
index 0b5ef05..cc8e0d0e 100644
--- a/arch/x86/include/asm/pti.h
+++ b/arch/x86/include/asm/pti.h
@@ -6,6 +6,11 @@
 #ifdef CONFIG_PAGE_TABLE_ISOLATION
 extern void pti_init(void);
 extern void pti_check_boottime_disable(void);
+# ifdef CONFIG_PER_PROCESS_PTI
+extern int pti_adjust;
+int pti_adjust_sysctl_handler(struct ctl_table *table, int write,
+                             void __user *buffer, size_t *lenp, loff_t *ppos);
+# endif
 #else
 static inline void pti_check_boottime_disable(void) { }
 #endif
diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c
index 43d4a4a..8166686f 100644
--- a/arch/x86/mm/pti.c
+++ b/arch/x86/mm/pti.c
@@ -54,6 +54,10 @@
 #define __GFP_NOTRACK  0
 #endif
 
+# ifdef CONFIG_PER_PROCESS_PTI
+int pti_adjust;
+#endif
+
 static void __init pti_print_if_insecure(const char *reason)
 {
        if (boot_cpu_has_bug(X86_BUG_CPU_MELTDOWN))
@@ -371,6 +375,21 @@ static void __init pti_clone_entry_text(void)
                       _PAGE_RW | _PAGE_GLOBAL);
 }
 
+#ifdef CONFIG_PER_PROCESS_PTI
+/*
+ * sysctl handler for pti_adjust which decides whether or not to accept a
+ * change to the value. 0 and 1 may be interchanged, but -1 is definitive.
+ */
+int pti_adjust_sysctl_handler(struct ctl_table *table, int write,
+                             void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       if (write && (!capable(CAP_SYS_RAWIO) || pti_adjust == -1))
+               return -EPERM;
+
+       return proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+}
+#endif
+
 /*
  * Initialize kernel page table isolation
  */
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 557d467..a37a5e1 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -34,6 +34,7 @@
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/pti.h>
 #include <linux/kobject.h>
 #include <linux/net.h>
 #include <linux/sysrq.h>
@@ -1572,6 +1573,17 @@ static int sysrq_sysctl_handler(struct ctl_table *table, 
int write,
                .proc_handler   = numa_zonelist_order_handler,
        },
 #endif
+#ifdef CONFIG_PER_PROCESS_PTI
+       {
+               .procname       = "pti_adjust",
+               .data           = &pti_adjust,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = pti_adjust_sysctl_handler,
+               .extra1         = &neg_one,
+               .extra2         = &one,
+       },
+#endif
 #if (defined(CONFIG_X86_32) && !defined(CONFIG_UML))|| \
    (defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL))
        {
-- 
1.7.12.1

Reply via email to