arm64: entry: Apply BP hardening for high-priority synchronous exceptions
authorWill Deacon <will.deacon@arm.com>
Fri, 2 Feb 2018 17:31:39 +0000 (17:31 +0000)
committerCatalin Marinas <catalin.marinas@arm.com>
Tue, 6 Feb 2018 22:53:44 +0000 (22:53 +0000)
Software-step and PC alignment fault exceptions have higher priority than
instruction abort exceptions, so apply the BP hardening hooks there too
if the user PC appears to reside in kernel space.

Reported-by: Dan Hettena <dhettena@nvidia.com>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
arch/arm64/kernel/entry.S
arch/arm64/mm/fault.c

index 4dd1b5a46642c911018a11380ee81eba875af69d..af22793103afdbf49cd2d8fc71fdbe819290c518 100644 (file)
@@ -767,7 +767,10 @@ el0_sp_pc:
         * Stack or PC alignment exception handling
         */
        mrs     x26, far_el1
-       enable_daif
+       enable_da_f
+#ifdef CONFIG_TRACE_IRQFLAGS
+       bl      trace_hardirqs_off
+#endif
        ct_user_exit
        mov     x0, x26
        mov     x1, x25
index af530eb9f2ed14138219969f8bea75e8c26f022d..43b28a782ed4672565392fbd5c66dded86104890 100644 (file)
@@ -732,6 +732,12 @@ asmlinkage void __exception do_sp_pc_abort(unsigned long addr,
        struct siginfo info;
        struct task_struct *tsk = current;
 
+       if (user_mode(regs)) {
+               if (instruction_pointer(regs) > TASK_SIZE)
+                       arm64_apply_bp_hardening();
+               local_irq_enable();
+       }
+
        if (show_unhandled_signals && unhandled_signal(tsk, SIGBUS))
                pr_info_ratelimited("%s[%d]: %s exception: pc=%p sp=%p\n",
                                    tsk->comm, task_pid_nr(tsk),
@@ -791,6 +797,9 @@ asmlinkage int __exception do_debug_exception(unsigned long addr,
        if (interrupts_enabled(regs))
                trace_hardirqs_off();
 
+       if (user_mode(regs) && instruction_pointer(regs) > TASK_SIZE)
+               arm64_apply_bp_hardening();
+
        if (!inf->fn(addr, esr, regs)) {
                rv = 1;
        } else {