arm64: don't call break hooks for BRK exceptions from EL0
authorWill Deacon <will.deacon@arm.com>
Thu, 31 Jul 2014 10:36:08 +0000 (11:36 +0100)
committerMark Brown <broonie@kernel.org>
Wed, 21 Jan 2015 23:26:35 +0000 (23:26 +0000)
Our break hooks are used to handle brk exceptions from kgdb (and potentially
kprobes if that code ever resurfaces), so don't bother calling them if
the BRK exception comes from userspace.

This prevents userspace from trapping to a kdb shell on systems where
kgdb is enabled and active.

Cc: <stable@vger.kernel.org>
Reported-by: Omar Sandoval <osandov@osandov.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
(cherry picked from commit c878e0cff5c5e56b216951cbe75f7a3dd500a736)
Signed-off-by: Mark Brown <broonie@kernel.org>
Conflicts:
arch/arm64/kernel/debug-monitors.c

arch/arm64/kernel/debug-monitors.c

index fea84694fce40d8782f800240af0bf544485597b..e3b37ee9076af9c5d05cb0e0c626347358ffc85a 100644 (file)
@@ -303,23 +303,20 @@ static int brk_handler(unsigned long addr, unsigned int esr,
 {
        siginfo_t info;
 
-       if (call_break_hook(regs, esr) == DBG_HOOK_HANDLED)
-               return 0;
-
-       pr_warn("unexpected brk exception at %lx, esr=0x%x\n",
-                       (long)instruction_pointer(regs), esr);
+       if (user_mode(regs)) {
+               info = (siginfo_t) {
+                       .si_signo = SIGTRAP,
+                       .si_errno = 0,
+                       .si_code  = TRAP_BRKPT,
+                       .si_addr  = (void __user *)instruction_pointer(regs),
+               };
 
-       if (!user_mode(regs))
+               force_sig_info(SIGTRAP, &info, current);
+       } else if (call_break_hook(regs, esr) != DBG_HOOK_HANDLED) {
+               pr_warning("Unexpected kernel BRK exception at EL1\n");
                return -EFAULT;
+       }
 
-       info = (siginfo_t) {
-               .si_signo = SIGTRAP,
-               .si_errno = 0,
-               .si_code  = TRAP_BRKPT,
-               .si_addr  = (void __user *)instruction_pointer(regs),
-       };
-
-       force_sig_info(SIGTRAP, &info, current);
        return 0;
 }