mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-25 03:55:09 +08:00
x86/traps: Move control protection handler to separate file
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
This commit is contained in:
parent
18e66b695e
commit
2da5b91fe4
@ -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)
|
||||
|
76
arch/x86/kernel/cet.c
Normal file
76
arch/x86/kernel/cet.c
Normal file
@ -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);
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user