10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28 /*
29 * Copyright 2019 Joyent, Inc.
30 */
31
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/thread.h>
35 #include <sys/sysmacros.h>
36 #include <sys/signal.h>
37 #include <sys/cred.h>
38 #include <sys/user.h>
39 #include <sys/errno.h>
40 #include <sys/vnode.h>
41 #include <sys/mman.h>
42 #include <sys/kmem.h>
43 #include <sys/proc.h>
44 #include <sys/pathname.h>
45 #include <sys/policy.h>
46 #include <sys/cmn_err.h>
47 #include <sys/systm.h>
48 #include <sys/elf.h>
49 #include <sys/vmsystm.h>
77 extern int at_flags;
78 extern volatile size_t aslr_max_brk_skew;
79
80 #define ORIGIN_STR "ORIGIN"
81 #define ORIGIN_STR_SIZE 6
82
83 static int getelfhead(vnode_t *, cred_t *, Ehdr *, uint_t *, uint_t *,
84 uint_t *);
85 static int getelfphdr(vnode_t *, cred_t *, const Ehdr *, uint_t, caddr_t *,
86 size_t *);
87 static int getelfshdr(vnode_t *, cred_t *, const Ehdr *, uint_t, uint_t,
88 caddr_t *, size_t *, caddr_t *, size_t *);
89 static size_t elfsize(const Ehdr *, uint_t, const caddr_t, uintptr_t *);
90 static int mapelfexec(vnode_t *, Ehdr *, uint_t, caddr_t, Phdr **, Phdr **,
91 Phdr **, Phdr **, Phdr *, caddr_t *, caddr_t *, intptr_t *, uintptr_t *,
92 size_t, size_t *, size_t *);
93
94 #ifdef _ELF32_COMPAT
95 /* Link against the non-compat instances when compiling the 32-bit version. */
96 extern size_t elf_datasz_max;
97 extern void elf_ctx_resize_scratch(elf_core_ctx_t *, size_t);
98 extern uint_t elf_nphdr_max;
99 extern uint_t elf_nshdr_max;
100 extern size_t elf_shstrtab_max;
101 #else
102 size_t elf_datasz_max = 1 * 1024 * 1024;
103 uint_t elf_nphdr_max = 1000;
104 uint_t elf_nshdr_max = 10000;
105 size_t elf_shstrtab_max = 100 * 1024;
106 #endif
107
108
109
110 typedef enum {
111 STR_CTF,
112 STR_SYMTAB,
113 STR_DYNSYM,
114 STR_STRTAB,
115 STR_DYNSTR,
116 STR_SHSTRTAB,
117 STR_NUM
118 } shstrtype_t;
119
120 static const char *shstrtab_data[] = {
121 ".SUNW_ctf",
122 ".symtab",
2247 shstrtab_dump(&shstrtab, ctx->ecc_buf);
2248
2249 error = core_write(ctx->ecc_vp, UIO_SYSSPACE, ctx->ecc_doffset,
2250 ctx->ecc_buf, v[idx].sh_size, ctx->ecc_rlimit, ctx->ecc_credp);
2251 if (error == 0) {
2252 ctx->ecc_doffset += v[idx].sh_size;
2253 }
2254
2255 return (error);
2256 }
2257
2258 int
2259 elfcore(vnode_t *vp, proc_t *p, cred_t *credp, rlim64_t rlimit, int sig,
2260 core_content_t content)
2261 {
2262 u_offset_t poffset, soffset, doffset;
2263 int error;
2264 uint_t i, nphdrs, nshdrs;
2265 struct seg *seg;
2266 struct as *as = p->p_as;
2267 void *bigwad;
2268 size_t bigsize, phdrsz, shdrsz;
2269 Ehdr *ehdr;
2270 Phdr *phdr;
2271 Shdr shdr0;
2272 caddr_t brkbase, stkbase;
2273 size_t brksize, stksize;
2274 boolean_t overflowed = B_FALSE, retried = B_FALSE;
2275 klwp_t *lwp = ttolwp(curthread);
2276 elf_core_ctx_t ctx = {
2277 .ecc_vp = vp,
2278 .ecc_p = p,
2279 .ecc_credp = credp,
2280 .ecc_rlimit = rlimit,
2281 .ecc_content = content,
2282 .ecc_doffset = 0,
2283 .ecc_buf = NULL,
2284 .ecc_bufsz = 0
2285 };
2286
2287 top:
2559 }
2560
2561 if ((error = write_old_elfnotes(p, sig, vp, phdr[0].p_offset, rlimit,
2562 credp)) != 0) {
2563 goto done;
2564 }
2565 if ((error = write_elfnotes(p, sig, vp, phdr[1].p_offset, rlimit,
2566 credp, content)) != 0) {
2567 goto done;
2568 }
2569
2570 for (i = 2; i < nphdrs; i++) {
2571 prkillinfo_t killinfo;
2572 sigqueue_t *sq;
2573 int sig, j;
2574
2575 if (phdr[i].p_filesz == 0)
2576 continue;
2577
2578 /*
2579 * If dumping out this segment fails, rather than failing
2580 * the core dump entirely, we reset the size of the mapping
2581 * to zero to indicate that the data is absent from the core
2582 * file and or in the PF_SUNW_FAILURE flag to differentiate
2583 * this from mappings that were excluded due to the core file
2584 * content settings.
2585 */
2586 if ((error = core_seg(p, vp, phdr[i].p_offset,
2587 (caddr_t)(uintptr_t)phdr[i].p_vaddr, phdr[i].p_filesz,
2588 rlimit, credp)) == 0) {
2589 continue;
2590 }
2591
2592 if ((sig = lwp->lwp_cursig) == 0) {
2593 /*
2594 * We failed due to something other than a signal.
2595 * Since the space reserved for the segment is now
2596 * unused, we stash the errno in the first four
2597 * bytes. This undocumented interface will let us
2598 * understand the nature of the failure.
2599 */
2600 (void) core_write(vp, UIO_SYSSPACE, phdr[i].p_offset,
2601 &error, sizeof (error), rlimit, credp);
2602
2603 phdr[i].p_filesz = 0;
2604 phdr[i].p_flags |= PF_SUNW_FAILURE;
2605 if ((error = core_write(vp, UIO_SYSSPACE,
2606 poffset + sizeof (Phdr) * i, &phdr[i],
2607 sizeof (Phdr), rlimit, credp)) != 0)
2608 goto done;
2609
2610 continue;
2611 }
|
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28 /*
29 * Copyright 2019 Joyent, Inc.
30 * Copyright 2021 Oxide Computer Company
31 */
32
33 #include <sys/types.h>
34 #include <sys/param.h>
35 #include <sys/thread.h>
36 #include <sys/sysmacros.h>
37 #include <sys/signal.h>
38 #include <sys/cred.h>
39 #include <sys/user.h>
40 #include <sys/errno.h>
41 #include <sys/vnode.h>
42 #include <sys/mman.h>
43 #include <sys/kmem.h>
44 #include <sys/proc.h>
45 #include <sys/pathname.h>
46 #include <sys/policy.h>
47 #include <sys/cmn_err.h>
48 #include <sys/systm.h>
49 #include <sys/elf.h>
50 #include <sys/vmsystm.h>
78 extern int at_flags;
79 extern volatile size_t aslr_max_brk_skew;
80
81 #define ORIGIN_STR "ORIGIN"
82 #define ORIGIN_STR_SIZE 6
83
84 static int getelfhead(vnode_t *, cred_t *, Ehdr *, uint_t *, uint_t *,
85 uint_t *);
86 static int getelfphdr(vnode_t *, cred_t *, const Ehdr *, uint_t, caddr_t *,
87 size_t *);
88 static int getelfshdr(vnode_t *, cred_t *, const Ehdr *, uint_t, uint_t,
89 caddr_t *, size_t *, caddr_t *, size_t *);
90 static size_t elfsize(const Ehdr *, uint_t, const caddr_t, uintptr_t *);
91 static int mapelfexec(vnode_t *, Ehdr *, uint_t, caddr_t, Phdr **, Phdr **,
92 Phdr **, Phdr **, Phdr *, caddr_t *, caddr_t *, intptr_t *, uintptr_t *,
93 size_t, size_t *, size_t *);
94
95 #ifdef _ELF32_COMPAT
96 /* Link against the non-compat instances when compiling the 32-bit version. */
97 extern size_t elf_datasz_max;
98 extern size_t elf_zeropg_sz;
99 extern void elf_ctx_resize_scratch(elf_core_ctx_t *, size_t);
100 extern uint_t elf_nphdr_max;
101 extern uint_t elf_nshdr_max;
102 extern size_t elf_shstrtab_max;
103 #else
104 size_t elf_datasz_max = 1 * 1024 * 1024;
105 size_t elf_zeropg_sz = 4 * 1024;
106 uint_t elf_nphdr_max = 1000;
107 uint_t elf_nshdr_max = 10000;
108 size_t elf_shstrtab_max = 100 * 1024;
109 #endif
110
111
112
113 typedef enum {
114 STR_CTF,
115 STR_SYMTAB,
116 STR_DYNSYM,
117 STR_STRTAB,
118 STR_DYNSTR,
119 STR_SHSTRTAB,
120 STR_NUM
121 } shstrtype_t;
122
123 static const char *shstrtab_data[] = {
124 ".SUNW_ctf",
125 ".symtab",
2250 shstrtab_dump(&shstrtab, ctx->ecc_buf);
2251
2252 error = core_write(ctx->ecc_vp, UIO_SYSSPACE, ctx->ecc_doffset,
2253 ctx->ecc_buf, v[idx].sh_size, ctx->ecc_rlimit, ctx->ecc_credp);
2254 if (error == 0) {
2255 ctx->ecc_doffset += v[idx].sh_size;
2256 }
2257
2258 return (error);
2259 }
2260
2261 int
2262 elfcore(vnode_t *vp, proc_t *p, cred_t *credp, rlim64_t rlimit, int sig,
2263 core_content_t content)
2264 {
2265 u_offset_t poffset, soffset, doffset;
2266 int error;
2267 uint_t i, nphdrs, nshdrs;
2268 struct seg *seg;
2269 struct as *as = p->p_as;
2270 void *bigwad, *zeropg = NULL;
2271 size_t bigsize, phdrsz, shdrsz;
2272 Ehdr *ehdr;
2273 Phdr *phdr;
2274 Shdr shdr0;
2275 caddr_t brkbase, stkbase;
2276 size_t brksize, stksize;
2277 boolean_t overflowed = B_FALSE, retried = B_FALSE;
2278 klwp_t *lwp = ttolwp(curthread);
2279 elf_core_ctx_t ctx = {
2280 .ecc_vp = vp,
2281 .ecc_p = p,
2282 .ecc_credp = credp,
2283 .ecc_rlimit = rlimit,
2284 .ecc_content = content,
2285 .ecc_doffset = 0,
2286 .ecc_buf = NULL,
2287 .ecc_bufsz = 0
2288 };
2289
2290 top:
2562 }
2563
2564 if ((error = write_old_elfnotes(p, sig, vp, phdr[0].p_offset, rlimit,
2565 credp)) != 0) {
2566 goto done;
2567 }
2568 if ((error = write_elfnotes(p, sig, vp, phdr[1].p_offset, rlimit,
2569 credp, content)) != 0) {
2570 goto done;
2571 }
2572
2573 for (i = 2; i < nphdrs; i++) {
2574 prkillinfo_t killinfo;
2575 sigqueue_t *sq;
2576 int sig, j;
2577
2578 if (phdr[i].p_filesz == 0)
2579 continue;
2580
2581 /*
2582 * If we hit a region that was mapped PROT_NONE then we cannot
2583 * continue dumping this normally as the kernel would be unable
2584 * to read from the page and that would result in us failing to
2585 * dump the page. As such, any region mapped PROT_NONE, we dump
2586 * as a zero-filled page such that this is still represented in
2587 * the map.
2588 *
2589 * If dumping out this segment fails, rather than failing
2590 * the core dump entirely, we reset the size of the mapping
2591 * to zero to indicate that the data is absent from the core
2592 * file and or in the PF_SUNW_FAILURE flag to differentiate
2593 * this from mappings that were excluded due to the core file
2594 * content settings.
2595 */
2596 if ((phdr[i].p_flags & (PF_R | PF_W | PF_X)) == 0) {
2597 size_t towrite = phdr[i].p_filesz;
2598 size_t curoff = 0;
2599
2600 if (zeropg == NULL) {
2601 zeropg = kmem_zalloc(elf_zeropg_sz, KM_SLEEP);
2602 }
2603
2604 error = 0;
2605 while (towrite != 0) {
2606 size_t len = MIN(towrite, elf_zeropg_sz);
2607
2608 error = core_write(vp, UIO_SYSSPACE,
2609 phdr[i].p_offset + curoff, zeropg, len,
2610 rlimit, credp);
2611 if (error != 0)
2612 break;
2613
2614 towrite -= len;
2615 curoff += len;
2616 }
2617 } else {
2618 error = core_seg(p, vp, phdr[i].p_offset,
2619 (caddr_t)(uintptr_t)phdr[i].p_vaddr,
2620 phdr[i].p_filesz, rlimit, credp);
2621 }
2622 if (error == 0)
2623 continue;
2624
2625 if ((sig = lwp->lwp_cursig) == 0) {
2626 /*
2627 * We failed due to something other than a signal.
2628 * Since the space reserved for the segment is now
2629 * unused, we stash the errno in the first four
2630 * bytes. This undocumented interface will let us
2631 * understand the nature of the failure.
2632 */
2633 (void) core_write(vp, UIO_SYSSPACE, phdr[i].p_offset,
2634 &error, sizeof (error), rlimit, credp);
2635
2636 phdr[i].p_filesz = 0;
2637 phdr[i].p_flags |= PF_SUNW_FAILURE;
2638 if ((error = core_write(vp, UIO_SYSSPACE,
2639 poffset + sizeof (Phdr) * i, &phdr[i],
2640 sizeof (Phdr), rlimit, credp)) != 0)
2641 goto done;
2642
2643 continue;
2644 }
|