[PATCH] arm64: symbolize user-space stack on SIGSEGV
From: Peter Collingbourne <hidden>
Date: 2021-08-17 22:00:59
Subsystem:
arm64 port (aarch64 architecture), the rest · Maintainers:
Catalin Marinas, Will Deacon, Linus Torvalds
On arm64, dump the userspace stack to the console when a SIGSEGV occurs. Print filename+offset to allow symbolization. This is a patch that I frequently need to apply locally in order to debug segfaults that occur in environments where attaching a debugger is infeasible. Although I don't expect this patch to be applied to the mainline kernel, I am posting it in case anyone else would find it useful (and because I almost lost track of it recently, and I don't want to have to write it again). Signed-off-by: Peter Collingbourne <redacted> --- arch/arm64/mm/fault.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 349c488765ca..8db82788e80b 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c@@ -526,6 +526,38 @@ static bool is_write_abort(unsigned int esr) return (esr & ESR_ELx_WNR) && !(esr & ESR_ELx_CM); } +static void symbolize_addr(const char *prefix, unsigned long addr) +{ + struct vm_area_struct *vma = find_vma(current->mm, addr); + if (vma && vma->vm_file) { + char buf[1024]; + char *c = d_path(&vma->vm_file->f_path, buf, 1024); + printk(KERN_ERR "%s = 0x%lx (%s + 0x%lx)\n", prefix, addr, c, + addr - vma->vm_start + vma->vm_pgoff * PAGE_SIZE); + } else { + printk(KERN_ERR "%s = 0x%lx", prefix, addr); + } +} + +static void symbolize_stack(void) +{ + int i; + unsigned long frame = current_pt_regs()->regs[29]; + + symbolize_addr("pc", current_pt_regs()->pc); + symbolize_addr("lr", current_pt_regs()->regs[30]); + + for (i = 0; i != 64; ++i) { + unsigned long ret_addr; + unsafe_get_user(ret_addr, (unsigned long __user *)(frame + 8), + end); + symbolize_addr("ret_addr", ptrauth_clear_pac(ret_addr)); + + unsafe_get_user(frame, (unsigned long __user *)frame, end); + } +end:; +} + static int __kprobes do_page_fault(unsigned long far, unsigned int esr, struct pt_regs *regs) {
@@ -671,6 +703,7 @@ static int __kprobes do_page_fault(unsigned long far, unsigned int esr, * Something tried to access memory that isn't in our memory * map. */ + symbolize_stack(); arm64_force_sig_fault(SIGSEGV, fault == VM_FAULT_BADACCESS ? SEGV_ACCERR : SEGV_MAPERR, far, inf->name);
--
2.33.0.rc1.237.g0d66db33f3-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel