aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2014-07-31 11:36:08 +0100
committerMark Brown <broonie@kernel.org>2015-01-21 23:26:35 +0000
commit83f1bff42dfdbf3f4bc70a07f4304db54f89d27d (patch)
tree6ca9cefcde8dedbf2a73eec49d46598fa7bd817b
parent6eb8fed568d2d39d198391012c62c0bd5f36b8ac (diff)
arm64: don't call break hooks for BRK exceptions from EL0
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
-rw-r--r--arch/arm64/kernel/debug-monitors.c25
1 files changed, 11 insertions, 14 deletions
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
index fea84694fce4..e3b37ee9076a 100644
--- a/arch/arm64/kernel/debug-monitors.c
+++ b/arch/arm64/kernel/debug-monitors.c
@@ -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;
}