mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
arm64: debug: Don't propagate UNKNOWN FAR into si_code for debug signals
commit b9a4b9d084 upstream.
FAR_EL1 is UNKNOWN for all debug exceptions other than those caused by
taking a hardware watchpoint. Unfortunately, if a debug handler returns
a non-zero value, then we will propagate the UNKNOWN FAR value to
userspace via the si_addr field of the SIGTRAP siginfo_t.
Instead, let's set si_addr to take on the PC of the faulting instruction,
which we have available in the current pt_regs.
Cc: <stable@vger.kernel.org>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
@@ -787,11 +787,12 @@ void __init hook_debug_fault_code(int nr,
|
||||
debug_fault_info[nr].name = name;
|
||||
}
|
||||
|
||||
asmlinkage int __exception do_debug_exception(unsigned long addr,
|
||||
asmlinkage int __exception do_debug_exception(unsigned long addr_if_watchpoint,
|
||||
unsigned int esr,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
const struct fault_info *inf = debug_fault_info + DBG_ESR_EVT(esr);
|
||||
unsigned long pc = instruction_pointer(regs);
|
||||
struct siginfo info;
|
||||
int rv;
|
||||
|
||||
@@ -802,19 +803,19 @@ 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)
|
||||
if (user_mode(regs) && pc > TASK_SIZE)
|
||||
arm64_apply_bp_hardening();
|
||||
|
||||
if (!inf->fn(addr, esr, regs)) {
|
||||
if (!inf->fn(addr_if_watchpoint, esr, regs)) {
|
||||
rv = 1;
|
||||
} else {
|
||||
pr_alert("Unhandled debug exception: %s (0x%08x) at 0x%016lx\n",
|
||||
inf->name, esr, addr);
|
||||
inf->name, esr, pc);
|
||||
|
||||
info.si_signo = inf->sig;
|
||||
info.si_errno = 0;
|
||||
info.si_code = inf->code;
|
||||
info.si_addr = (void __user *)addr;
|
||||
info.si_addr = (void __user *)pc;
|
||||
arm64_notify_die("", regs, &info, 0);
|
||||
rv = 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user