Skip to content

Commit 2da5b91

Browse files
committed
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
1 parent 18e66b6 commit 2da5b91

3 files changed

Lines changed: 78 additions & 75 deletions

File tree

arch/x86/kernel/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ obj-$(CONFIG_CFI_CLANG) += cfi.o
145145

146146
obj-$(CONFIG_CALL_THUNKS) += callthunks.o
147147

148+
obj-$(CONFIG_X86_CET) += cet.o
149+
148150
###
149151
# 64 bit specific files
150152
ifeq ($(CONFIG_X86_64),y)

arch/x86/kernel/cet.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <linux/ptrace.h>
4+
#include <asm/bugs.h>
5+
#include <asm/traps.h>
6+
7+
static __ro_after_init bool ibt_fatal = true;
8+
9+
extern void ibt_selftest_ip(void); /* code label defined in asm below */
10+
11+
enum cp_error_code {
12+
CP_EC = (1 << 15) - 1,
13+
14+
CP_RET = 1,
15+
CP_IRET = 2,
16+
CP_ENDBR = 3,
17+
CP_RSTRORSSP = 4,
18+
CP_SETSSBSY = 5,
19+
20+
CP_ENCL = 1 << 15,
21+
};
22+
23+
DEFINE_IDTENTRY_ERRORCODE(exc_control_protection)
24+
{
25+
if (!cpu_feature_enabled(X86_FEATURE_IBT)) {
26+
pr_err("Unexpected #CP\n");
27+
BUG();
28+
}
29+
30+
if (WARN_ON_ONCE(user_mode(regs) || (error_code & CP_EC) != CP_ENDBR))
31+
return;
32+
33+
if (unlikely(regs->ip == (unsigned long)&ibt_selftest_ip)) {
34+
regs->ax = 0;
35+
return;
36+
}
37+
38+
pr_err("Missing ENDBR: %pS\n", (void *)instruction_pointer(regs));
39+
if (!ibt_fatal) {
40+
printk(KERN_DEFAULT CUT_HERE);
41+
__warn(__FILE__, __LINE__, (void *)regs->ip, TAINT_WARN, regs, NULL);
42+
return;
43+
}
44+
BUG();
45+
}
46+
47+
/* Must be noinline to ensure uniqueness of ibt_selftest_ip. */
48+
noinline bool ibt_selftest(void)
49+
{
50+
unsigned long ret;
51+
52+
asm (" lea ibt_selftest_ip(%%rip), %%rax\n\t"
53+
ANNOTATE_RETPOLINE_SAFE
54+
" jmp *%%rax\n\t"
55+
"ibt_selftest_ip:\n\t"
56+
UNWIND_HINT_FUNC
57+
ANNOTATE_NOENDBR
58+
" nop\n\t"
59+
60+
: "=a" (ret) : : "memory");
61+
62+
return !ret;
63+
}
64+
65+
static int __init ibt_setup(char *str)
66+
{
67+
if (!strcmp(str, "off"))
68+
setup_clear_cpu_cap(X86_FEATURE_IBT);
69+
70+
if (!strcmp(str, "warn"))
71+
ibt_fatal = false;
72+
73+
return 1;
74+
}
75+
76+
__setup("ibt=", ibt_setup);

arch/x86/kernel/traps.c

Lines changed: 0 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -213,81 +213,6 @@ DEFINE_IDTENTRY(exc_overflow)
213213
do_error_trap(regs, 0, "overflow", X86_TRAP_OF, SIGSEGV, 0, NULL);
214214
}
215215

216-
#ifdef CONFIG_X86_KERNEL_IBT
217-
218-
static __ro_after_init bool ibt_fatal = true;
219-
220-
extern void ibt_selftest_ip(void); /* code label defined in asm below */
221-
222-
enum cp_error_code {
223-
CP_EC = (1 << 15) - 1,
224-
225-
CP_RET = 1,
226-
CP_IRET = 2,
227-
CP_ENDBR = 3,
228-
CP_RSTRORSSP = 4,
229-
CP_SETSSBSY = 5,
230-
231-
CP_ENCL = 1 << 15,
232-
};
233-
234-
DEFINE_IDTENTRY_ERRORCODE(exc_control_protection)
235-
{
236-
if (!cpu_feature_enabled(X86_FEATURE_IBT)) {
237-
pr_err("Unexpected #CP\n");
238-
BUG();
239-
}
240-
241-
if (WARN_ON_ONCE(user_mode(regs) || (error_code & CP_EC) != CP_ENDBR))
242-
return;
243-
244-
if (unlikely(regs->ip == (unsigned long)&ibt_selftest_ip)) {
245-
regs->ax = 0;
246-
return;
247-
}
248-
249-
pr_err("Missing ENDBR: %pS\n", (void *)instruction_pointer(regs));
250-
if (!ibt_fatal) {
251-
printk(KERN_DEFAULT CUT_HERE);
252-
__warn(__FILE__, __LINE__, (void *)regs->ip, TAINT_WARN, regs, NULL);
253-
return;
254-
}
255-
BUG();
256-
}
257-
258-
/* Must be noinline to ensure uniqueness of ibt_selftest_ip. */
259-
noinline bool ibt_selftest(void)
260-
{
261-
unsigned long ret;
262-
263-
asm (" lea ibt_selftest_ip(%%rip), %%rax\n\t"
264-
ANNOTATE_RETPOLINE_SAFE
265-
" jmp *%%rax\n\t"
266-
"ibt_selftest_ip:\n\t"
267-
UNWIND_HINT_FUNC
268-
ANNOTATE_NOENDBR
269-
" nop\n\t"
270-
271-
: "=a" (ret) : : "memory");
272-
273-
return !ret;
274-
}
275-
276-
static int __init ibt_setup(char *str)
277-
{
278-
if (!strcmp(str, "off"))
279-
setup_clear_cpu_cap(X86_FEATURE_IBT);
280-
281-
if (!strcmp(str, "warn"))
282-
ibt_fatal = false;
283-
284-
return 1;
285-
}
286-
287-
__setup("ibt=", ibt_setup);
288-
289-
#endif /* CONFIG_X86_KERNEL_IBT */
290-
291216
#ifdef CONFIG_X86_F00F_BUG
292217
void handle_invalid_op(struct pt_regs *regs)
293218
#else

0 commit comments

Comments
 (0)