x86/traps: Move control protection handler to separate file
authorRick Edgecombe <rick.p.edgecombe@intel.com>
Tue, 13 Jun 2023 00:10:33 +0000 (17:10 -0700)
committerRick Edgecombe <rick.p.edgecombe@intel.com>
Tue, 11 Jul 2023 21:12:18 +0000 (14:12 -0700)
Today the control protection handler is defined in traps.c and used only
for the kernel IBT feature. To reduce ifdeffery, move it to it's own file.
In future patches, functionality will be added to make this handler also
handle user shadow stack faults. So name the file cet.c.

No functional change.

Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Kees Cook <keescook@chromium.org>
Acked-by: Mike Rapoport (IBM) <rppt@kernel.org>
Tested-by: Pengfei Xu <pengfei.xu@intel.com>
Tested-by: John Allen <john.allen@amd.com>
Tested-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/all/20230613001108.3040476-8-rick.p.edgecombe%40intel.com
arch/x86/kernel/Makefile
arch/x86/kernel/cet.c [new file with mode: 0644]
arch/x86/kernel/traps.c

index 4070a01c11b72af04f429dee966c495275a7dfb6..abee0564b75064b30d6d59971a6133b8a2f9c106 100644 (file)
@@ -145,6 +145,8 @@ obj-$(CONFIG_CFI_CLANG)                     += cfi.o
 
 obj-$(CONFIG_CALL_THUNKS)              += callthunks.o
 
+obj-$(CONFIG_X86_CET)                  += cet.o
+
 ###
 # 64 bit specific files
 ifeq ($(CONFIG_X86_64),y)
diff --git a/arch/x86/kernel/cet.c b/arch/x86/kernel/cet.c
new file mode 100644 (file)
index 0000000..7ad22b7
--- /dev/null
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/ptrace.h>
+#include <asm/bugs.h>
+#include <asm/traps.h>
+
+static __ro_after_init bool ibt_fatal = true;
+
+extern void ibt_selftest_ip(void); /* code label defined in asm below */
+
+enum cp_error_code {
+       CP_EC        = (1 << 15) - 1,
+
+       CP_RET       = 1,
+       CP_IRET      = 2,
+       CP_ENDBR     = 3,
+       CP_RSTRORSSP = 4,
+       CP_SETSSBSY  = 5,
+
+       CP_ENCL      = 1 << 15,
+};
+
+DEFINE_IDTENTRY_ERRORCODE(exc_control_protection)
+{
+       if (!cpu_feature_enabled(X86_FEATURE_IBT)) {
+               pr_err("Unexpected #CP\n");
+               BUG();
+       }
+
+       if (WARN_ON_ONCE(user_mode(regs) || (error_code & CP_EC) != CP_ENDBR))
+               return;
+
+       if (unlikely(regs->ip == (unsigned long)&ibt_selftest_ip)) {
+               regs->ax = 0;
+               return;
+       }
+
+       pr_err("Missing ENDBR: %pS\n", (void *)instruction_pointer(regs));
+       if (!ibt_fatal) {
+               printk(KERN_DEFAULT CUT_HERE);
+               __warn(__FILE__, __LINE__, (void *)regs->ip, TAINT_WARN, regs, NULL);
+               return;
+       }
+       BUG();
+}
+
+/* Must be noinline to ensure uniqueness of ibt_selftest_ip. */
+noinline bool ibt_selftest(void)
+{
+       unsigned long ret;
+
+       asm ("  lea ibt_selftest_ip(%%rip), %%rax\n\t"
+            ANNOTATE_RETPOLINE_SAFE
+            "  jmp *%%rax\n\t"
+            "ibt_selftest_ip:\n\t"
+            UNWIND_HINT_FUNC
+            ANNOTATE_NOENDBR
+            "  nop\n\t"
+
+            : "=a" (ret) : : "memory");
+
+       return !ret;
+}
+
+static int __init ibt_setup(char *str)
+{
+       if (!strcmp(str, "off"))
+               setup_clear_cpu_cap(X86_FEATURE_IBT);
+
+       if (!strcmp(str, "warn"))
+               ibt_fatal = false;
+
+       return 1;
+}
+
+__setup("ibt=", ibt_setup);
index 58b1f208eff5186aae3b08825f1d0581b47ba275..6f666dfa97de2024e7bf2badfd32e1bfb2efab4b 100644 (file)
@@ -213,81 +213,6 @@ DEFINE_IDTENTRY(exc_overflow)
        do_error_trap(regs, 0, "overflow", X86_TRAP_OF, SIGSEGV, 0, NULL);
 }
 
-#ifdef CONFIG_X86_KERNEL_IBT
-
-static __ro_after_init bool ibt_fatal = true;
-
-extern void ibt_selftest_ip(void); /* code label defined in asm below */
-
-enum cp_error_code {
-       CP_EC        = (1 << 15) - 1,
-
-       CP_RET       = 1,
-       CP_IRET      = 2,
-       CP_ENDBR     = 3,
-       CP_RSTRORSSP = 4,
-       CP_SETSSBSY  = 5,
-
-       CP_ENCL      = 1 << 15,
-};
-
-DEFINE_IDTENTRY_ERRORCODE(exc_control_protection)
-{
-       if (!cpu_feature_enabled(X86_FEATURE_IBT)) {
-               pr_err("Unexpected #CP\n");
-               BUG();
-       }
-
-       if (WARN_ON_ONCE(user_mode(regs) || (error_code & CP_EC) != CP_ENDBR))
-               return;
-
-       if (unlikely(regs->ip == (unsigned long)&ibt_selftest_ip)) {
-               regs->ax = 0;
-               return;
-       }
-
-       pr_err("Missing ENDBR: %pS\n", (void *)instruction_pointer(regs));
-       if (!ibt_fatal) {
-               printk(KERN_DEFAULT CUT_HERE);
-               __warn(__FILE__, __LINE__, (void *)regs->ip, TAINT_WARN, regs, NULL);
-               return;
-       }
-       BUG();
-}
-
-/* Must be noinline to ensure uniqueness of ibt_selftest_ip. */
-noinline bool ibt_selftest(void)
-{
-       unsigned long ret;
-
-       asm ("  lea ibt_selftest_ip(%%rip), %%rax\n\t"
-            ANNOTATE_RETPOLINE_SAFE
-            "  jmp *%%rax\n\t"
-            "ibt_selftest_ip:\n\t"
-            UNWIND_HINT_FUNC
-            ANNOTATE_NOENDBR
-            "  nop\n\t"
-
-            : "=a" (ret) : : "memory");
-
-       return !ret;
-}
-
-static int __init ibt_setup(char *str)
-{
-       if (!strcmp(str, "off"))
-               setup_clear_cpu_cap(X86_FEATURE_IBT);
-
-       if (!strcmp(str, "warn"))
-               ibt_fatal = false;
-
-       return 1;
-}
-
-__setup("ibt=", ibt_setup);
-
-#endif /* CONFIG_X86_KERNEL_IBT */
-
 #ifdef CONFIG_X86_F00F_BUG
 void handle_invalid_op(struct pt_regs *regs)
 #else