lkml.org 
[lkml]   [2021]   [Feb]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v21 06/26] x86/cet: Add control-protection fault handler
    Date
    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; or an indirect JMP instruction, without the NOTRACK
    prefix, arrives at a non-ENDBR opcode.

    The control-protection fault handler works in a similar way as the general
    protection fault handler. It provides the si_code SEGV_CPERR to the signal
    handler.

    Signed-off-by: Yu-cheng Yu <yu-cheng.yu@intel.com>
    Reviewed-by: Kees Cook <keescook@chromium.org>
    Cc: Michael Kerrisk <mtk.manpages@gmail.com>
    ---
    arch/x86/include/asm/idtentry.h | 4 ++
    arch/x86/kernel/idt.c | 4 ++
    arch/x86/kernel/signal_compat.c | 2 +-
    arch/x86/kernel/traps.c | 63 ++++++++++++++++++++++++++++++
    include/uapi/asm-generic/siginfo.h | 3 +-
    5 files changed, 74 insertions(+), 2 deletions(-)

    diff --git a/arch/x86/include/asm/idtentry.h b/arch/x86/include/asm/idtentry.h
    index f656aabd1545..ff4b3bf634da 100644
    --- a/arch/x86/include/asm/idtentry.h
    +++ b/arch/x86/include/asm/idtentry.h
    @@ -574,6 +574,10 @@ DECLARE_IDTENTRY_ERRORCODE(X86_TRAP_SS, exc_stack_segment);
    DECLARE_IDTENTRY_ERRORCODE(X86_TRAP_GP, exc_general_protection);
    DECLARE_IDTENTRY_ERRORCODE(X86_TRAP_AC, exc_alignment_check);

    +#ifdef CONFIG_X86_CET
    +DECLARE_IDTENTRY_ERRORCODE(X86_TRAP_CP, exc_control_protection);
    +#endif
    +
    /* Raw exception entries which need extra work */
    DECLARE_IDTENTRY_RAW(X86_TRAP_UD, exc_invalid_op);
    DECLARE_IDTENTRY_RAW(X86_TRAP_BP, exc_int3);
    diff --git a/arch/x86/kernel/idt.c b/arch/x86/kernel/idt.c
    index ee1a283f8e96..e8166d9bbb10 100644
    --- a/arch/x86/kernel/idt.c
    +++ b/arch/x86/kernel/idt.c
    @@ -105,6 +105,10 @@ static const __initconst struct idt_data def_idts[] = {
    #elif defined(CONFIG_X86_32)
    SYSG(IA32_SYSCALL_VECTOR, entry_INT80_32),
    #endif
    +
    +#ifdef CONFIG_X86_CET
    + INTG(X86_TRAP_CP, asm_exc_control_protection),
    +#endif
    };

    /*
    diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
    index a5330ff498f0..dd92490b1e7f 100644
    --- a/arch/x86/kernel/signal_compat.c
    +++ b/arch/x86/kernel/signal_compat.c
    @@ -27,7 +27,7 @@ static inline void signal_compat_build_tests(void)
    */
    BUILD_BUG_ON(NSIGILL != 11);
    BUILD_BUG_ON(NSIGFPE != 15);
    - BUILD_BUG_ON(NSIGSEGV != 9);
    + BUILD_BUG_ON(NSIGSEGV != 10);
    BUILD_BUG_ON(NSIGBUS != 5);
    BUILD_BUG_ON(NSIGTRAP != 5);
    BUILD_BUG_ON(NSIGCHLD != 6);
    diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
    index 7f5aec758f0e..8c7fa91a57c9 100644
    --- a/arch/x86/kernel/traps.c
    +++ b/arch/x86/kernel/traps.c
    @@ -39,6 +39,7 @@
    #include <linux/io.h>
    #include <linux/hardirq.h>
    #include <linux/atomic.h>
    +#include <linux/nospec.h>

    #include <asm/stacktrace.h>
    #include <asm/processor.h>
    @@ -606,6 +607,68 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
    cond_local_irq_disable(regs);
    }

    +#ifdef CONFIG_X86_CET
    +static const char * const control_protection_err[] = {
    + "unknown",
    + "near-ret",
    + "far-ret/iret",
    + "endbranch",
    + "rstorssp",
    + "setssbsy",
    + "unknown",
    +};
    +
    +/*
    + * When a control protection exception occurs, send a signal to the responsible
    + * application. Currently, control protection is only enabled for user mode.
    + * This exception should not come from kernel mode.
    + */
    +DEFINE_IDTENTRY_ERRORCODE(exc_control_protection)
    +{
    + static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL,
    + DEFAULT_RATELIMIT_BURST);
    + struct task_struct *tsk;
    +
    + if (!user_mode(regs)) {
    + pr_emerg("PANIC: unexpected kernel control protection fault\n");
    + die("kernel control protection fault", regs, error_code);
    + panic("Machine halted.");
    + }
    +
    + cond_local_irq_enable(regs);
    +
    + if (!boot_cpu_has(X86_FEATURE_CET))
    + WARN_ONCE(1, "Control protection fault with CET support disabled\n");
    +
    + tsk = current;
    + 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(&rs)) {
    + unsigned long ssp;
    + int err;
    +
    + err = array_index_nospec(error_code, ARRAY_SIZE(control_protection_err));
    +
    + rdmsrl(MSR_IA32_PL3_SSP, ssp);
    + pr_emerg("%s[%d] control protection ip:%lx sp:%lx ssp:%lx error:%lx(%s)",
    + tsk->comm, task_pid_nr(tsk),
    + regs->ip, regs->sp, ssp, error_code,
    + control_protection_err[err]);
    + print_vma_addr(KERN_CONT " in ", regs->ip);
    + pr_cont("\n");
    + }
    +
    + force_sig_fault(SIGSEGV, SEGV_CPERR,
    + (void __user *)uprobe_get_trap_addr(regs));
    + cond_local_irq_disable(regs);
    +}
    +#endif
    +
    static bool do_int3(struct pt_regs *regs)
    {
    int res;
    diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
    index d2597000407a..1c2ea91284a0 100644
    --- a/include/uapi/asm-generic/siginfo.h
    +++ b/include/uapi/asm-generic/siginfo.h
    @@ -231,7 +231,8 @@ typedef struct siginfo {
    #define SEGV_ADIPERR 7 /* Precise MCD exception */
    #define SEGV_MTEAERR 8 /* Asynchronous ARM MTE error */
    #define SEGV_MTESERR 9 /* Synchronous ARM MTE exception */
    -#define NSIGSEGV 9
    +#define SEGV_CPERR 10 /* Control protection fault */
    +#define NSIGSEGV 10

    /*
    * SIGBUS si_codes
    --
    2.21.0
    \
     
     \ /
      Last update: 2021-02-17 23:34    [W:4.096 / U:0.032 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site