1 // SPDX-License-Identifier: GPL-2.0
3 #include <linux/ptrace.h>
19 static const char cp_err
[][10] = {
28 static const char *cp_err_string(unsigned long error_code
)
30 unsigned int cpec
= error_code
& CP_EC
;
32 if (cpec
>= ARRAY_SIZE(cp_err
))
37 static void do_unexpected_cp(struct pt_regs
*regs
, unsigned long error_code
)
39 WARN_ONCE(1, "Unexpected %s #CP, error_code: %s\n",
40 user_mode(regs
) ? "user mode" : "kernel mode",
41 cp_err_string(error_code
));
44 static DEFINE_RATELIMIT_STATE(cpf_rate
, DEFAULT_RATELIMIT_INTERVAL
,
45 DEFAULT_RATELIMIT_BURST
);
47 static void do_user_cp_fault(struct pt_regs
*regs
, unsigned long error_code
)
49 struct task_struct
*tsk
;
53 * An exception was just taken from userspace. Since interrupts are disabled
54 * here, no scheduling should have messed with the registers yet and they
55 * will be whatever is live in userspace. So read the SSP before enabling
56 * interrupts so locking the fpregs to do it later is not required.
58 rdmsrl(MSR_IA32_PL3_SSP
, ssp
);
60 cond_local_irq_enable(regs
);
63 tsk
->thread
.error_code
= error_code
;
64 tsk
->thread
.trap_nr
= X86_TRAP_CP
;
66 /* Ratelimit to prevent log spamming. */
67 if (show_unhandled_signals
&& unhandled_signal(tsk
, SIGSEGV
) &&
68 __ratelimit(&cpf_rate
)) {
69 pr_emerg("%s[%d] control protection ip:%lx sp:%lx ssp:%lx error:%lx(%s)%s",
70 tsk
->comm
, task_pid_nr(tsk
),
71 regs
->ip
, regs
->sp
, ssp
, error_code
,
72 cp_err_string(error_code
),
73 error_code
& CP_ENCL
? " in enclave" : "");
74 print_vma_addr(KERN_CONT
" in ", regs
->ip
);
78 force_sig_fault(SIGSEGV
, SEGV_CPERR
, (void __user
*)0);
79 cond_local_irq_disable(regs
);
82 static __ro_after_init
bool ibt_fatal
= true;
84 /* code label defined in asm below */
85 extern void ibt_selftest_ip(void);
87 static void do_kernel_cp_fault(struct pt_regs
*regs
, unsigned long error_code
)
89 if ((error_code
& CP_EC
) != CP_ENDBR
) {
90 do_unexpected_cp(regs
, error_code
);
94 if (unlikely(regs
->ip
== (unsigned long)&ibt_selftest_ip
)) {
99 pr_err("Missing ENDBR: %pS\n", (void *)instruction_pointer(regs
));
101 printk(KERN_DEFAULT CUT_HERE
);
102 __warn(__FILE__
, __LINE__
, (void *)regs
->ip
, TAINT_WARN
, regs
, NULL
);
108 /* Must be noinline to ensure uniqueness of ibt_selftest_ip. */
109 noinline
bool ibt_selftest(void)
113 asm (" lea ibt_selftest_ip(%%rip), %%rax\n\t"
114 ANNOTATE_RETPOLINE_SAFE
116 "ibt_selftest_ip:\n\t"
121 : "=a" (ret
) : : "memory");
126 static int __init
ibt_setup(char *str
)
128 if (!strcmp(str
, "off"))
129 setup_clear_cpu_cap(X86_FEATURE_IBT
);
131 if (!strcmp(str
, "warn"))
137 __setup("ibt=", ibt_setup
);
139 DEFINE_IDTENTRY_ERRORCODE(exc_control_protection
)
141 if (user_mode(regs
)) {
142 if (cpu_feature_enabled(X86_FEATURE_USER_SHSTK
))
143 do_user_cp_fault(regs
, error_code
);
145 do_unexpected_cp(regs
, error_code
);
147 if (cpu_feature_enabled(X86_FEATURE_IBT
))
148 do_kernel_cp_fault(regs
, error_code
);
150 do_unexpected_cp(regs
, error_code
);