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)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 16 Feb 2018 19:22:53 +0000 (20:22 +0100)
Commit 5dfc6ed27710 upstream.

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>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/arm64/kernel/entry.S
arch/arm64/mm/fault.c

index a035a981b5579a3f5691e5969a2311969b505306..ac7df45b296b88676a15b7aabfc7a386b8a2b314 100644 (file)
@@ -759,8 +759,10 @@ el0_sp_pc:
         * Stack or PC alignment exception handling
         */
        mrs     x26, far_el1
-       // enable interrupts before calling the main handler
-       enable_dbg_and_irq
+       enable_dbg
+#ifdef CONFIG_TRACE_IRQFLAGS
+       bl      trace_hardirqs_off
+#endif
        ct_user_exit
        mov     x0, x26
        mov     x1, x25
index 4985bd1175ef673373a9a8d2d9ce89281b437c18..58992467ebb9d34eebee83db65a6b05edc77b3b4 100644 (file)
@@ -778,6 +778,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),
@@ -837,6 +843,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 {