Merge tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64...
[linux-2.6-block.git] / arch / arm64 / mm / fault.c
index ce441d29e7f6ed797b74228ff6284a6224baef9b..f76bb2c3c9434dc29c572d4103f9eb10b42dc278 100644 (file)
@@ -240,7 +240,7 @@ static inline bool is_permission_fault(unsigned int esr, struct pt_regs *regs,
        if (fsc_type == ESR_ELx_FSC_PERM)
                return true;
 
-       if (addr < USER_DS && system_uses_ttbr0_pan())
+       if (addr < TASK_SIZE && system_uses_ttbr0_pan())
                return fsc_type == ESR_ELx_FSC_FAULT &&
                        (regs->pstate & PSR_PAN_BIT);
 
@@ -414,7 +414,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
                mm_flags |= FAULT_FLAG_WRITE;
        }
 
-       if (addr < USER_DS && is_permission_fault(esr, regs, addr)) {
+       if (addr < TASK_SIZE && is_permission_fault(esr, regs, addr)) {
                /* regs->orig_addr_limit may be 0 if we entered from EL0 */
                if (regs->orig_addr_limit == KERNEL_DS)
                        die("Accessing user space memory with fs=KERNEL_DS", regs, esr);
@@ -707,6 +707,12 @@ asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr,
        arm64_notify_die("", regs, &info, esr);
 }
 
+asmlinkage void __exception do_el0_irq_bp_hardening(void)
+{
+       /* PC has already been checked in entry.S */
+       arm64_apply_bp_hardening();
+}
+
 asmlinkage void __exception do_el0_ia_bp_hardening(unsigned long addr,
                                                   unsigned int esr,
                                                   struct pt_regs *regs)
@@ -731,6 +737,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),
@@ -790,6 +802,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 {