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)
committerHaibo Chen <haibo.chen@nxp.com>
Thu, 12 Apr 2018 10:46:27 +0000 (18:46 +0800)
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: Alex Shi <alex.shi@linaro.org>
Conflicts:
expand enable_da_f to 'msr daifclr, #(8 | 4 | 1)'
in arch/arm64/kernel/entry.S

arch/arm64/kernel/entry.S
arch/arm64/mm/fault.c

index 20a978b..f8768ab 100644 (file)
@@ -626,8 +626,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
+       msr     daifclr, #(8 | 4 | 1)
+#ifdef CONFIG_TRACE_IRQFLAGS
+       bl      trace_hardirqs_off
+#endif
        ct_user_exit
        mov     x0, x26
        mov     x1, x25
index c95b194..6120a14 100644 (file)
@@ -617,6 +617,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),
@@ -676,6 +682,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 {