From 13f0bae737815c2bc645da585a42c3d9a6f218f2 Mon Sep 17 00:00:00 2001 From: kettenis Date: Fri, 13 Jan 2023 23:02:43 +0000 Subject: [PATCH] Since the signal trampoline is now execute-only we no longer write it into core dumps. As a result backtraces through signal handlers no longer work in gdb and other debuggers. Fix this by keeping a read-only mapping of the signal trampoline in the kernel and writing it into the core dump at the virtual address where it is mapped in the process. ok deraadt@, tb@ --- sys/kern/exec_elf.c | 19 ++++++++++++++++--- sys/kern/kern_exec.c | 10 ++++++++-- sys/uvm/uvm_unix.c | 5 +++-- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/sys/kern/exec_elf.c b/sys/kern/exec_elf.c index 9dc99d3efa4..779b729b240 100644 --- a/sys/kern/exec_elf.c +++ b/sys/kern/exec_elf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: exec_elf.c,v 1.178 2022/12/21 07:16:03 deraadt Exp $ */ +/* $OpenBSD: exec_elf.c,v 1.179 2023/01/13 23:02:43 kettenis Exp $ */ /* * Copyright (c) 1996 Per Fogelstrom @@ -982,6 +982,9 @@ int coredump_note_elf(struct proc *, void *, size_t *); int coredump_writenote_elf(struct proc *, void *, Elf_Note *, const char *, void *); +extern vaddr_t sigcode_va; +extern vsize_t sigcode_sz; + int coredump_elf(struct proc *p, void *cookie) { @@ -1038,8 +1041,18 @@ coredump_elf(struct proc *p, void *cookie) (long long) pent->p_filesz); #endif - error = coredump_write(cookie, UIO_USERSPACE, - (void *)(vaddr_t)pent->p_vaddr, pent->p_filesz); + /* + * Since the sigcode is mapped execute-only, we can't + * read it. So use the kernel mapping for it instead. + */ + if (pent->p_vaddr == p->p_p->ps_sigcode && + pent->p_filesz == sigcode_sz) { + error = coredump_write(cookie, UIO_SYSSPACE, + (void *)sigcode_va, sigcode_sz); + } else { + error = coredump_write(cookie, UIO_USERSPACE, + (void *)(vaddr_t)pent->p_vaddr, pent->p_filesz); + } if (error) goto out; diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 0d470bf9292..6a7188c3264 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_exec.c,v 1.242 2023/01/07 05:24:58 guenther Exp $ */ +/* $OpenBSD: kern_exec.c,v 1.243 2023/01/13 23:02:43 kettenis Exp $ */ /* $NetBSD: kern_exec.c,v 1.75 1996/02/09 18:59:28 christos Exp $ */ /*- @@ -66,6 +66,8 @@ #include struct uvm_object *sigobject; /* shared sigcode object */ +vaddr_t sigcode_va; +vsize_t sigcode_sz; struct uvm_object *timekeep_object; struct timekeep *timekeep; @@ -855,7 +857,11 @@ exec_sigcode_map(struct process *pr) left -= chunk; } memcpy((caddr_t)va, sigcode, sz); - uvm_unmap(kernel_map, va, va + round_page(sz)); + + (void) uvm_map_protect(kernel_map, va, round_page(sz), + PROT_READ, 0, FALSE, FALSE); + sigcode_va = va; + sigcode_sz = round_page(sz); } pr->ps_sigcode = 0; /* no hint */ diff --git a/sys/uvm/uvm_unix.c b/sys/uvm/uvm_unix.c index 82617cb0595..3ec0b00a0fb 100644 --- a/sys/uvm/uvm_unix.c +++ b/sys/uvm/uvm_unix.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_unix.c,v 1.71 2020/10/21 21:24:57 deraadt Exp $ */ +/* $OpenBSD: uvm_unix.c,v 1.72 2023/01/13 23:02:44 kettenis Exp $ */ /* $NetBSD: uvm_unix.c,v 1.18 2000/09/13 15:00:25 thorpej Exp $ */ /* @@ -234,7 +234,8 @@ uvm_should_coredump(struct proc *p, struct vm_map_entry *entry) * uvm_map_extract(UVM_EXTRACT_FIXPROT) * on each such page would suck. */ - if ((entry->protection & PROT_READ) == 0) + if (!(entry->protection & PROT_READ) && + entry->start != p->p_p->ps_sigcode) return 0; /* Skip ranges excluded from coredumps. */ -- 2.20.1