Re: [PATCH v5 07/39] x86: Add user control-protection fault handler

Borislav Petkov
2023-02-03T19:09:28Z

On Thu, Jan 19, 2023 at 01:22:45PM -0800, Rick Edgecombe wrote:
> Subject: Re: [PATCH v5 07/39] x86: Add user control-protection fault handler

Subject: x86/shstk: Add...

> From: Yu-cheng Yu <yu-cheng.yu@intel.com>
>
> A control-protection fault is triggered when a control-flow transfer
> attempt violates Shadow Stack or Indirect Branch Tracking constraints.
> For example, the return address for a RET instruction differs from the copy
> on the shadow stack.

...

> diff --git a/arch/x86/kernel/cet.c b/arch/x86/kernel/cet.c
> new file mode 100644
> index 000000000000..33d7d119be26
> --- /dev/null
> +++ b/arch/x86/kernel/cet.c
> @@ -0,0 +1,152 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <linux/ptrace.h>
> +#include <asm/bugs.h>
> +#include <asm/traps.h>
> +
> +enum cp_error_code {
> + CP_EC = (1 << 15) - 1,

That looks like a mask, so

CP_EC_MASK

I guess.

> +
> + CP_RET = 1,
> + CP_IRET = 2,
> + CP_ENDBR = 3,
> + CP_RSTRORSSP = 4,
> + CP_SETSSBSY = 5,
> +
> + CP_ENCL = 1 << 15,
> +};

...

> +static void do_user_cp_fault(struct pt_regs *regs, unsigned long error_code)
> +{
> + struct task_struct *tsk;
> + unsigned long ssp;
> +
> + /*
> + * An exception was just taken from userspace. Since interrupts are disabled
> + * here, no scheduling should have messed with the registers yet and they
> + * will be whatever is live in userspace. So read the SSP before enabling
> + * interrupts so locking the fpregs to do it later is not required.
> + */
> + rdmsrl(MSR_IA32_PL3_SSP, ssp);
> +
> + cond_local_irq_enable(regs);
> +
> + tsk = current;

Hmm, should you read current before you enable interrupts? Not that it
changes from under us...

> + tsk->thread.error_code = error_code;
> + tsk->thread.trap_nr = X86_TRAP_CP;
> +
> + /* Ratelimit to prevent log spamming. */
> + if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
> + __ratelimit(&cpf_rate)) {
> + pr_emerg("%s[%d] control protection ip:%lx sp:%lx ssp:%lx error:%lx(%s)%s",
> + tsk->comm, task_pid_nr(tsk),
> + regs->ip, regs->sp, ssp, error_code,
> + cp_err_string(error_code),
> + error_code & CP_ENCL ? " in enclave" : "");
> + print_vma_addr(KERN_CONT " in ", regs->ip);
> + pr_cont("\n");
> + }
> +
> + force_sig_fault(SIGSEGV, SEGV_CPERR, (void __user *)0);
> + cond_local_irq_disable(regs);
> +}

--
Regards/Gruss,
Boris.