Skip to content

Commit

Permalink
x86/traps: Move control protection handler to separate file
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Dave Hansen <[email protected]>
Reviewed-by: Borislav Petkov (AMD) <[email protected]>
Reviewed-by: Kees Cook <[email protected]>
Acked-by: Mike Rapoport (IBM) <[email protected]>
Tested-by: Pengfei Xu <[email protected]>
Tested-by: John Allen <[email protected]>
Tested-by: Kees Cook <[email protected]>
Link: https://lore.kernel.org/all/20230613001108.3040476-8-rick.p.edgecombe%40intel.com
  • Loading branch information
rpedgeco committed Jul 11, 2023
1 parent 18e66b6 commit 2da5b91
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 75 deletions.
2 changes: 2 additions & 0 deletions arch/x86/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
76 changes: 76 additions & 0 deletions arch/x86/kernel/cet.c
Original file line number Diff line number Diff line change
@@ -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);
75 changes: 0 additions & 75 deletions arch/x86/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 2da5b91

Please sign in to comment.