Since the signal trampoline is now execute-only we no longer write it
authorkettenis <kettenis@openbsd.org>
Fri, 13 Jan 2023 23:02:43 +0000 (23:02 +0000)
committerkettenis <kettenis@openbsd.org>
Fri, 13 Jan 2023 23:02:43 +0000 (23:02 +0000)
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
sys/kern/kern_exec.c
sys/uvm/uvm_unix.c

index 9dc99d3..779b729 100644 (file)
@@ -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;
 
index 0d470bf..6a7188c 100644 (file)
@@ -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 <sys/timetc.h>
 
 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 */
index 82617cb..3ec0b00 100644 (file)
@@ -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. */