[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <2f1617ff-1665-1814-9c0b-5188d0794ac2@citrix.com>
Date: Wed, 9 Mar 2022 13:56:51 +0000
From: Andrew Cooper <Andrew.Cooper3@...rix.com>
To: Peter Zijlstra <peterz@...radead.org>,
"x86@...nel.org" <x86@...nel.org>,
"joao@...rdrivepizza.com" <joao@...rdrivepizza.com>,
"hjl.tools@...il.com" <hjl.tools@...il.com>,
"jpoimboe@...hat.com" <jpoimboe@...hat.com>
CC: "linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
"ndesaulniers@...gle.com" <ndesaulniers@...gle.com>,
"keescook@...omium.org" <keescook@...omium.org>,
"samitolvanen@...gle.com" <samitolvanen@...gle.com>,
"mark.rutland@....com" <mark.rutland@....com>,
"alyssa.milburn@...el.com" <alyssa.milburn@...el.com>,
"mbenes@...e.cz" <mbenes@...e.cz>,
"rostedt@...dmis.org" <rostedt@...dmis.org>,
"mhiramat@...nel.org" <mhiramat@...nel.org>,
"alexei.starovoitov@...il.com" <alexei.starovoitov@...il.com>
Subject: Re: [PATCH v4 24/45] x86/ibt: Add IBT feature, MSR and #CP handling
On 08/03/2022 15:30, Peter Zijlstra wrote:
> --- a/arch/x86/kernel/cpu/common.c
> +++ b/arch/x86/kernel/cpu/common.c
> @@ -592,6 +594,24 @@ static __init int setup_disable_pku(char
> __setup("nopku", setup_disable_pku);
> #endif /* CONFIG_X86_64 */
>
> +static __always_inline void setup_cet(struct cpuinfo_x86 *c)
> +{
> + u64 msr = CET_ENDBR_EN;
> +
> + if (!HAS_KERNEL_IBT ||
> + !cpu_feature_enabled(X86_FEATURE_IBT))
> + return;
> +
> + wrmsrl(MSR_IA32_S_CET, msr);
> + cr4_set_bits(X86_CR4_CET);
> +
> + if (!ibt_selftest()) {
> + pr_err("IBT selftest: Failed!\n");
> + setup_clear_cpu_cap(X86_FEATURE_IBT);
This path wants to clear CR4.CET or MSR_S_CET, or both.
> + return;
> + }
> +}
> +
> /*
> * Some CPU features depend on higher CPUID levels, which may not always
> * be available due to CPUID level capping or broken virtualization
> --- a/arch/x86/kernel/traps.c
> +++ b/arch/x86/kernel/traps.c
> @@ -210,6 +210,80 @@ 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;
> +
> +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;
Is this wise? #CP is a fault, so this will livelock.
user_mode() wants to turn into an oops. Kernel probably wants to fold
into the Unexpected #CP path, but definitely print the error code.
~Andrew
> +
> + 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();
> +}
> +
> +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
>
>
Powered by blists - more mailing lists