1 /* $OpenBSD: exec_elf.c,v 1.148 2019/04/20 23:11:20 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 1996 Per Fogelstrom 5 * All rights reserved. 6 * 7 * Copyright (c) 1994 Christos Zoulas 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * 32 */ 33 34 /* 35 * Copyright (c) 2001 Wasabi Systems, Inc. 36 * All rights reserved. 37 * 38 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 39 * 40 * Redistribution and use in source and binary forms, with or without 41 * modification, are permitted provided that the following conditions 42 * are met: 43 * 1. Redistributions of source code must retain the above copyright 44 * notice, this list of conditions and the following disclaimer. 45 * 2. Redistributions in binary form must reproduce the above copyright 46 * notice, this list of conditions and the following disclaimer in the 47 * documentation and/or other materials provided with the distribution. 48 * 3. All advertising materials mentioning features or use of this software 49 * must display the following acknowledgement: 50 * This product includes software developed for the NetBSD Project by 51 * Wasabi Systems, Inc. 52 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 53 * or promote products derived from this software without specific prior 54 * written permission. 55 * 56 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 57 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 58 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 59 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 60 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 61 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 62 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 63 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 64 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 65 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 66 * POSSIBILITY OF SUCH DAMAGE. 67 */ 68 69 #include <sys/param.h> 70 #include <sys/systm.h> 71 #include <sys/kernel.h> 72 #include <sys/proc.h> 73 #include <sys/malloc.h> 74 #include <sys/pool.h> 75 #include <sys/mount.h> 76 #include <sys/namei.h> 77 #include <sys/vnode.h> 78 #include <sys/core.h> 79 #include <sys/syslog.h> 80 #include <sys/exec.h> 81 #include <sys/exec_elf.h> 82 #include <sys/fcntl.h> 83 #include <sys/ptrace.h> 84 #include <sys/syscall.h> 85 #include <sys/signalvar.h> 86 #include <sys/stat.h> 87 #include <sys/pledge.h> 88 89 #include <sys/mman.h> 90 91 #include <uvm/uvm_extern.h> 92 93 #include <machine/reg.h> 94 #include <machine/exec.h> 95 96 int elf_load_file(struct proc *, char *, struct exec_package *, 97 struct elf_args *); 98 int elf_check_header(Elf_Ehdr *); 99 int elf_read_from(struct proc *, struct vnode *, u_long, void *, int); 100 void elf_load_psection(struct exec_vmcmd_set *, struct vnode *, 101 Elf_Phdr *, Elf_Addr *, Elf_Addr *, int *, int); 102 int coredump_elf(struct proc *, void *); 103 void *elf_copyargs(struct exec_package *, struct ps_strings *, void *, 104 void *); 105 int exec_elf_fixup(struct proc *, struct exec_package *); 106 int elf_os_pt_note(struct proc *, struct exec_package *, Elf_Ehdr *, 107 char *, size_t, size_t); 108 109 extern char sigcode[], esigcode[], sigcoderet[]; 110 #ifdef SYSCALL_DEBUG 111 extern char *syscallnames[]; 112 #endif 113 114 /* round up and down to page boundaries. */ 115 #define ELF_ROUND(a, b) (((a) + (b) - 1) & ~((b) - 1)) 116 #define ELF_TRUNC(a, b) ((a) & ~((b) - 1)) 117 118 /* 119 * We limit the number of program headers to 32, this should 120 * be a reasonable limit for ELF, the most we have seen so far is 12 121 */ 122 #define ELF_MAX_VALID_PHDR 32 123 124 /* 125 * How many entries are in the AuxInfo array we pass to the process? 126 */ 127 #define ELF_AUX_ENTRIES 8 128 129 /* 130 * This is the OpenBSD ELF emul 131 */ 132 struct emul emul_elf = { 133 "native", 134 NULL, 135 SYS_syscall, 136 SYS_MAXSYSCALL, 137 sysent, 138 #ifdef SYSCALL_DEBUG 139 syscallnames, 140 #else 141 NULL, 142 #endif 143 (sizeof(AuxInfo) * ELF_AUX_ENTRIES / sizeof(char *)), 144 elf_copyargs, 145 setregs, 146 exec_elf_fixup, 147 coredump_elf, 148 sigcode, 149 esigcode, 150 sigcoderet 151 }; 152 153 /* 154 * Copy arguments onto the stack in the normal way, but add some 155 * space for extra information in case of dynamic binding. 156 */ 157 void * 158 elf_copyargs(struct exec_package *pack, struct ps_strings *arginfo, 159 void *stack, void *argp) 160 { 161 stack = copyargs(pack, arginfo, stack, argp); 162 if (!stack) 163 return (NULL); 164 165 /* 166 * Push space for extra arguments on the stack needed by 167 * dynamically linked binaries. 168 */ 169 if (pack->ep_emul_arg != NULL) { 170 pack->ep_emul_argp = stack; 171 stack = (char *)stack + ELF_AUX_ENTRIES * sizeof (AuxInfo); 172 } 173 return (stack); 174 } 175 176 /* 177 * Check header for validity; return 0 for ok, ENOEXEC if error 178 */ 179 int 180 elf_check_header(Elf_Ehdr *ehdr) 181 { 182 /* 183 * We need to check magic, class size, endianess, and version before 184 * we look at the rest of the Elf_Ehdr structure. These few elements 185 * are represented in a machine independent fashion. 186 */ 187 if (!IS_ELF(*ehdr) || 188 ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || 189 ehdr->e_ident[EI_DATA] != ELF_TARG_DATA || 190 ehdr->e_ident[EI_VERSION] != ELF_TARG_VER) 191 return (ENOEXEC); 192 193 /* Now check the machine dependent header */ 194 if (ehdr->e_machine != ELF_TARG_MACH || 195 ehdr->e_version != ELF_TARG_VER) 196 return (ENOEXEC); 197 198 /* Don't allow an insane amount of sections. */ 199 if (ehdr->e_phnum > ELF_MAX_VALID_PHDR) 200 return (ENOEXEC); 201 202 return (0); 203 } 204 205 /* 206 * Load a psection at the appropriate address 207 */ 208 void 209 elf_load_psection(struct exec_vmcmd_set *vcset, struct vnode *vp, 210 Elf_Phdr *ph, Elf_Addr *addr, Elf_Addr *size, int *prot, int flags) 211 { 212 u_long msize, lsize, psize, rm, rf; 213 long diff, offset, bdiff; 214 Elf_Addr base; 215 216 /* 217 * If the user specified an address, then we load there. 218 */ 219 if (*addr != ELF_NO_ADDR) { 220 if (ph->p_align > 1) { 221 *addr = ELF_TRUNC(*addr, ph->p_align); 222 diff = ph->p_vaddr - ELF_TRUNC(ph->p_vaddr, ph->p_align); 223 /* page align vaddr */ 224 base = *addr + trunc_page(ph->p_vaddr) 225 - ELF_TRUNC(ph->p_vaddr, ph->p_align); 226 } else { 227 diff = 0; 228 base = *addr + trunc_page(ph->p_vaddr) - ph->p_vaddr; 229 } 230 } else { 231 *addr = ph->p_vaddr; 232 if (ph->p_align > 1) 233 *addr = ELF_TRUNC(*addr, ph->p_align); 234 base = trunc_page(ph->p_vaddr); 235 diff = ph->p_vaddr - *addr; 236 } 237 bdiff = ph->p_vaddr - trunc_page(ph->p_vaddr); 238 239 /* 240 * Enforce W^X and map W|X segments without X permission 241 * initially. The dynamic linker will make these read-only 242 * and add back X permission after relocation processing. 243 * Static executables with W|X segments will probably crash. 244 */ 245 *prot |= (ph->p_flags & PF_R) ? PROT_READ : 0; 246 *prot |= (ph->p_flags & PF_W) ? PROT_WRITE : 0; 247 if ((ph->p_flags & PF_W) == 0) 248 *prot |= (ph->p_flags & PF_X) ? PROT_EXEC : 0; 249 250 msize = ph->p_memsz + diff; 251 offset = ph->p_offset - bdiff; 252 lsize = ph->p_filesz + bdiff; 253 psize = round_page(lsize); 254 255 /* 256 * Because the pagedvn pager can't handle zero fill of the last 257 * data page if it's not page aligned we map the last page readvn. 258 */ 259 if (ph->p_flags & PF_W) { 260 psize = trunc_page(lsize); 261 if (psize > 0) 262 NEW_VMCMD2(vcset, vmcmd_map_pagedvn, psize, base, vp, 263 offset, *prot, flags); 264 if (psize != lsize) { 265 NEW_VMCMD2(vcset, vmcmd_map_readvn, lsize - psize, 266 base + psize, vp, offset + psize, *prot, flags); 267 } 268 } else { 269 NEW_VMCMD2(vcset, vmcmd_map_pagedvn, psize, base, vp, offset, 270 *prot, flags); 271 } 272 273 /* 274 * Check if we need to extend the size of the segment 275 */ 276 rm = round_page(*addr + ph->p_memsz + diff); 277 rf = round_page(*addr + ph->p_filesz + diff); 278 279 if (rm != rf) { 280 NEW_VMCMD2(vcset, vmcmd_map_zero, rm - rf, rf, NULLVP, 0, 281 *prot, flags); 282 } 283 *size = msize; 284 } 285 286 /* 287 * Read from vnode into buffer at offset. 288 */ 289 int 290 elf_read_from(struct proc *p, struct vnode *vp, u_long off, void *buf, 291 int size) 292 { 293 int error; 294 size_t resid; 295 296 if ((error = vn_rdwr(UIO_READ, vp, buf, size, off, UIO_SYSSPACE, 297 0, p->p_ucred, &resid, p)) != 0) 298 return error; 299 /* 300 * See if we got all of it 301 */ 302 if (resid != 0) 303 return (ENOEXEC); 304 return (0); 305 } 306 307 /* 308 * Load a file (interpreter/library) pointed to by path [stolen from 309 * coff_load_shlib()]. Made slightly generic so it might be used externally. 310 */ 311 int 312 elf_load_file(struct proc *p, char *path, struct exec_package *epp, 313 struct elf_args *ap) 314 { 315 int error, i; 316 struct nameidata nd; 317 Elf_Ehdr eh; 318 Elf_Phdr *ph = NULL; 319 u_long phsize = 0; 320 Elf_Addr addr; 321 struct vnode *vp; 322 Elf_Phdr *base_ph = NULL; 323 struct interp_ld_sec { 324 Elf_Addr vaddr; 325 u_long memsz; 326 } loadmap[ELF_MAX_VALID_PHDR]; 327 int nload, idx = 0; 328 Elf_Addr pos; 329 int file_align; 330 int loop; 331 size_t randomizequota = ELF_RANDOMIZE_LIMIT; 332 333 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, p); 334 nd.ni_pledge = PLEDGE_RPATH; 335 nd.ni_unveil = UNVEIL_READ; 336 if ((error = namei(&nd)) != 0) { 337 return (error); 338 } 339 vp = nd.ni_vp; 340 if (vp->v_type != VREG) { 341 error = EACCES; 342 goto bad; 343 } 344 if ((error = VOP_GETATTR(vp, epp->ep_vap, p->p_ucred, p)) != 0) 345 goto bad; 346 if (vp->v_mount->mnt_flag & MNT_NOEXEC) { 347 error = EACCES; 348 goto bad; 349 } 350 if ((error = VOP_ACCESS(vp, VREAD, p->p_ucred, p)) != 0) 351 goto bad1; 352 if ((error = elf_read_from(p, nd.ni_vp, 0, &eh, sizeof(eh))) != 0) 353 goto bad1; 354 355 if (elf_check_header(&eh) || eh.e_type != ET_DYN) { 356 error = ENOEXEC; 357 goto bad1; 358 } 359 360 ph = mallocarray(eh.e_phnum, sizeof(Elf_Phdr), M_TEMP, M_WAITOK); 361 phsize = eh.e_phnum * sizeof(Elf_Phdr); 362 363 if ((error = elf_read_from(p, nd.ni_vp, eh.e_phoff, ph, phsize)) != 0) 364 goto bad1; 365 366 for (i = 0; i < eh.e_phnum; i++) { 367 if (ph[i].p_type == PT_LOAD) { 368 if (ph[i].p_filesz > ph[i].p_memsz || 369 ph[i].p_memsz == 0) { 370 error = EINVAL; 371 goto bad1; 372 } 373 loadmap[idx].vaddr = trunc_page(ph[i].p_vaddr); 374 loadmap[idx].memsz = round_page (ph[i].p_vaddr + 375 ph[i].p_memsz - loadmap[idx].vaddr); 376 file_align = ph[i].p_align; 377 idx++; 378 } 379 } 380 nload = idx; 381 382 /* 383 * Load the interpreter where a non-fixed mmap(NULL, ...) 384 * would (i.e. something safely out of the way). 385 */ 386 pos = uvm_map_hint(p->p_vmspace, PROT_EXEC, VM_MIN_ADDRESS, 387 VM_MAXUSER_ADDRESS); 388 pos = ELF_ROUND(pos, file_align); 389 390 loop = 0; 391 for (i = 0; i < nload;/**/) { 392 vaddr_t addr; 393 struct uvm_object *uobj; 394 off_t uoff; 395 size_t size; 396 397 #ifdef this_needs_fixing 398 if (i == 0) { 399 uobj = &vp->v_uvm.u_obj; 400 /* need to fix uoff */ 401 } else { 402 #endif 403 uobj = NULL; 404 uoff = 0; 405 #ifdef this_needs_fixing 406 } 407 #endif 408 409 addr = trunc_page(pos + loadmap[i].vaddr); 410 size = round_page(addr + loadmap[i].memsz) - addr; 411 412 /* CRAP - map_findspace does not avoid daddr+BRKSIZ */ 413 if ((addr + size > (vaddr_t)p->p_vmspace->vm_daddr) && 414 (addr < (vaddr_t)p->p_vmspace->vm_daddr + BRKSIZ)) 415 addr = round_page((vaddr_t)p->p_vmspace->vm_daddr + 416 BRKSIZ); 417 418 if (uvm_map_mquery(&p->p_vmspace->vm_map, &addr, size, 419 (i == 0 ? uoff : UVM_UNKNOWN_OFFSET), 0) != 0) { 420 if (loop == 0) { 421 loop = 1; 422 i = 0; 423 pos = 0; 424 continue; 425 } 426 error = ENOMEM; 427 goto bad1; 428 } 429 if (addr != pos + loadmap[i].vaddr) { 430 /* base changed. */ 431 pos = addr - trunc_page(loadmap[i].vaddr); 432 pos = ELF_ROUND(pos,file_align); 433 i = 0; 434 continue; 435 } 436 437 i++; 438 } 439 440 /* 441 * Load all the necessary sections 442 */ 443 for (i = 0; i < eh.e_phnum; i++) { 444 Elf_Addr size = 0; 445 int prot = 0; 446 int flags; 447 448 switch (ph[i].p_type) { 449 case PT_LOAD: 450 if (base_ph == NULL) { 451 flags = VMCMD_BASE; 452 addr = pos; 453 base_ph = &ph[i]; 454 } else { 455 flags = VMCMD_RELATIVE; 456 addr = ph[i].p_vaddr - base_ph->p_vaddr; 457 } 458 elf_load_psection(&epp->ep_vmcmds, nd.ni_vp, 459 &ph[i], &addr, &size, &prot, flags); 460 /* If entry is within this section it must be text */ 461 if (eh.e_entry >= ph[i].p_vaddr && 462 eh.e_entry < (ph[i].p_vaddr + size)) { 463 epp->ep_entry = addr + eh.e_entry - 464 ELF_TRUNC(ph[i].p_vaddr,ph[i].p_align); 465 if (flags == VMCMD_RELATIVE) 466 epp->ep_entry += pos; 467 ap->arg_interp = pos; 468 } 469 addr += size; 470 break; 471 472 case PT_DYNAMIC: 473 case PT_PHDR: 474 case PT_NOTE: 475 break; 476 477 case PT_OPENBSD_RANDOMIZE: 478 if (ph[i].p_memsz > randomizequota) { 479 error = ENOMEM; 480 goto bad1; 481 } 482 randomizequota -= ph[i].p_memsz; 483 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_randomize, 484 ph[i].p_memsz, ph[i].p_vaddr + pos, NULLVP, 0, 0); 485 break; 486 487 default: 488 break; 489 } 490 } 491 492 vn_marktext(nd.ni_vp); 493 494 bad1: 495 VOP_CLOSE(nd.ni_vp, FREAD, p->p_ucred, p); 496 bad: 497 free(ph, M_TEMP, phsize); 498 499 vput(nd.ni_vp); 500 return (error); 501 } 502 503 /* 504 * Prepare an Elf binary's exec package 505 * 506 * First, set of the various offsets/lengths in the exec package. 507 * 508 * Then, mark the text image busy (so it can be demand paged) or error out if 509 * this is not possible. Finally, set up vmcmds for the text, data, bss, and 510 * stack segments. 511 */ 512 int 513 exec_elf_makecmds(struct proc *p, struct exec_package *epp) 514 { 515 Elf_Ehdr *eh = epp->ep_hdr; 516 Elf_Phdr *ph, *pp, *base_ph = NULL; 517 Elf_Addr phdr = 0, exe_base = 0; 518 int error, i, has_phdr = 0; 519 char *interp = NULL; 520 u_long phsize; 521 size_t randomizequota = ELF_RANDOMIZE_LIMIT; 522 523 if (epp->ep_hdrvalid < sizeof(Elf_Ehdr)) 524 return (ENOEXEC); 525 526 if (elf_check_header(eh) || 527 (eh->e_type != ET_EXEC && eh->e_type != ET_DYN)) 528 return (ENOEXEC); 529 530 /* 531 * check if vnode is in open for writing, because we want to demand- 532 * page out of it. if it is, don't do it, for various reasons. 533 */ 534 if (epp->ep_vp->v_writecount != 0) { 535 #ifdef DIAGNOSTIC 536 if (epp->ep_vp->v_flag & VTEXT) 537 panic("exec: a VTEXT vnode has writecount != 0"); 538 #endif 539 return (ETXTBSY); 540 } 541 /* 542 * Allocate space to hold all the program headers, and read them 543 * from the file 544 */ 545 ph = mallocarray(eh->e_phnum, sizeof(Elf_Phdr), M_TEMP, M_WAITOK); 546 phsize = eh->e_phnum * sizeof(Elf_Phdr); 547 548 if ((error = elf_read_from(p, epp->ep_vp, eh->e_phoff, ph, 549 phsize)) != 0) 550 goto bad; 551 552 epp->ep_tsize = ELF_NO_ADDR; 553 epp->ep_dsize = ELF_NO_ADDR; 554 555 for (i = 0, pp = ph; i < eh->e_phnum; i++, pp++) { 556 if (pp->p_type == PT_INTERP && !interp) { 557 if (pp->p_filesz < 2 || pp->p_filesz > MAXPATHLEN) 558 goto bad; 559 interp = pool_get(&namei_pool, PR_WAITOK); 560 if ((error = elf_read_from(p, epp->ep_vp, 561 pp->p_offset, interp, pp->p_filesz)) != 0) { 562 goto bad; 563 } 564 if (interp[pp->p_filesz - 1] != '\0') 565 goto bad; 566 } else if (pp->p_type == PT_LOAD) { 567 if (pp->p_filesz > pp->p_memsz || 568 pp->p_memsz == 0) { 569 error = EINVAL; 570 goto bad; 571 } 572 if (base_ph == NULL) 573 base_ph = pp; 574 } else if (pp->p_type == PT_PHDR) { 575 has_phdr = 1; 576 } 577 } 578 579 if (eh->e_type == ET_DYN) { 580 /* need phdr and load sections for PIE */ 581 if (!has_phdr || base_ph == NULL) { 582 error = EINVAL; 583 goto bad; 584 } 585 /* randomize exe_base for PIE */ 586 exe_base = uvm_map_pie(base_ph->p_align); 587 } 588 589 /* 590 * OK, we want a slightly different twist of the 591 * standard emulation package for "real" elf. 592 */ 593 epp->ep_emul = &emul_elf; 594 595 /* 596 * Verify this is an OpenBSD executable. If it's marked that way 597 * via a PT_NOTE then also check for a PT_OPENBSD_WXNEEDED segment. 598 */ 599 if (eh->e_ident[EI_OSABI] != ELFOSABI_OPENBSD && (error = 600 elf_os_pt_note(p, epp, epp->ep_hdr, "OpenBSD", 8, 4)) != 0) { 601 goto bad; 602 } 603 604 /* 605 * Load all the necessary sections 606 */ 607 for (i = 0, pp = ph; i < eh->e_phnum; i++, pp++) { 608 Elf_Addr addr, size = 0; 609 int prot = 0; 610 int flags = 0; 611 612 switch (pp->p_type) { 613 case PT_LOAD: 614 if (exe_base != 0) { 615 if (pp == base_ph) { 616 flags = VMCMD_BASE; 617 addr = exe_base; 618 } else { 619 flags = VMCMD_RELATIVE; 620 addr = pp->p_vaddr - base_ph->p_vaddr; 621 } 622 } else 623 addr = ELF_NO_ADDR; 624 625 /* 626 * Calculates size of text and data segments 627 * by starting at first and going to end of last. 628 * 'rwx' sections are treated as data. 629 * this is correct for BSS_PLT, but may not be 630 * for DATA_PLT, is fine for TEXT_PLT. 631 */ 632 elf_load_psection(&epp->ep_vmcmds, epp->ep_vp, 633 pp, &addr, &size, &prot, flags); 634 635 /* 636 * Update exe_base in case alignment was off. 637 * For PIE, addr is relative to exe_base so 638 * adjust it (non PIE exe_base is 0 so no change). 639 */ 640 if (flags == VMCMD_BASE) 641 exe_base = addr; 642 else 643 addr += exe_base; 644 645 /* 646 * Decide whether it's text or data by looking 647 * at the protection of the section 648 */ 649 if (prot & PROT_WRITE) { 650 /* data section */ 651 if (epp->ep_dsize == ELF_NO_ADDR) { 652 epp->ep_daddr = addr; 653 epp->ep_dsize = size; 654 } else { 655 if (addr < epp->ep_daddr) { 656 epp->ep_dsize = 657 epp->ep_dsize + 658 epp->ep_daddr - 659 addr; 660 epp->ep_daddr = addr; 661 } else 662 epp->ep_dsize = addr+size - 663 epp->ep_daddr; 664 } 665 } else if (prot & PROT_EXEC) { 666 /* text section */ 667 if (epp->ep_tsize == ELF_NO_ADDR) { 668 epp->ep_taddr = addr; 669 epp->ep_tsize = size; 670 } else { 671 if (addr < epp->ep_taddr) { 672 epp->ep_tsize = 673 epp->ep_tsize + 674 epp->ep_taddr - 675 addr; 676 epp->ep_taddr = addr; 677 } else 678 epp->ep_tsize = addr+size - 679 epp->ep_taddr; 680 } 681 } 682 break; 683 684 case PT_SHLIB: 685 error = ENOEXEC; 686 goto bad; 687 688 case PT_INTERP: 689 /* Already did this one */ 690 case PT_DYNAMIC: 691 case PT_NOTE: 692 break; 693 694 case PT_PHDR: 695 /* Note address of program headers (in text segment) */ 696 phdr = pp->p_vaddr; 697 break; 698 699 case PT_OPENBSD_RANDOMIZE: 700 if (ph[i].p_memsz > randomizequota) { 701 error = ENOMEM; 702 goto bad; 703 } 704 randomizequota -= ph[i].p_memsz; 705 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_randomize, 706 ph[i].p_memsz, ph[i].p_vaddr + exe_base, NULLVP, 0, 0); 707 break; 708 709 default: 710 /* 711 * Not fatal, we don't need to understand everything 712 * :-) 713 */ 714 break; 715 } 716 } 717 718 phdr += exe_base; 719 720 /* 721 * Strangely some linux programs may have all load sections marked 722 * writeable, in this case, textsize is not -1, but rather 0; 723 */ 724 if (epp->ep_tsize == ELF_NO_ADDR) 725 epp->ep_tsize = 0; 726 /* 727 * Another possibility is that it has all load sections marked 728 * read-only. Fake a zero-sized data segment right after the 729 * text segment. 730 */ 731 if (epp->ep_dsize == ELF_NO_ADDR) { 732 epp->ep_daddr = round_page(epp->ep_taddr + epp->ep_tsize); 733 epp->ep_dsize = 0; 734 } 735 736 epp->ep_interp = interp; 737 epp->ep_entry = eh->e_entry + exe_base; 738 739 /* 740 * Check if we found a dynamically linked binary and arrange to load 741 * its interpreter when the exec file is released. 742 */ 743 if (interp || eh->e_type == ET_DYN) { 744 struct elf_args *ap; 745 746 ap = malloc(sizeof(*ap), M_TEMP, M_WAITOK); 747 748 ap->arg_phaddr = phdr; 749 ap->arg_phentsize = eh->e_phentsize; 750 ap->arg_phnum = eh->e_phnum; 751 ap->arg_entry = eh->e_entry + exe_base; 752 ap->arg_interp = exe_base; 753 754 epp->ep_emul_arg = ap; 755 epp->ep_emul_argsize = sizeof *ap; 756 } 757 758 free(ph, M_TEMP, phsize); 759 vn_marktext(epp->ep_vp); 760 return (exec_setup_stack(p, epp)); 761 762 bad: 763 if (interp) 764 pool_put(&namei_pool, interp); 765 free(ph, M_TEMP, phsize); 766 kill_vmcmds(&epp->ep_vmcmds); 767 if (error == 0) 768 return (ENOEXEC); 769 return (error); 770 } 771 772 /* 773 * Phase II of load. It is now safe to load the interpreter. Info collected 774 * when loading the program is available for setup of the interpreter. 775 */ 776 int 777 exec_elf_fixup(struct proc *p, struct exec_package *epp) 778 { 779 char *interp; 780 int error = 0; 781 struct elf_args *ap; 782 AuxInfo ai[ELF_AUX_ENTRIES], *a; 783 784 if (epp->ep_emul_arg == NULL) { 785 return (0); 786 } 787 788 interp = epp->ep_interp; 789 ap = epp->ep_emul_arg; 790 791 if (interp && 792 (error = elf_load_file(p, interp, epp, ap)) != 0) { 793 free(ap, M_TEMP, epp->ep_emul_argsize); 794 pool_put(&namei_pool, interp); 795 kill_vmcmds(&epp->ep_vmcmds); 796 return (error); 797 } 798 /* 799 * We have to do this ourselves... 800 */ 801 error = exec_process_vmcmds(p, epp); 802 803 /* 804 * Push extra arguments on the stack needed by dynamically 805 * linked binaries 806 */ 807 if (error == 0) { 808 memset(&ai, 0, sizeof ai); 809 a = ai; 810 811 a->au_id = AUX_phdr; 812 a->au_v = ap->arg_phaddr; 813 a++; 814 815 a->au_id = AUX_phent; 816 a->au_v = ap->arg_phentsize; 817 a++; 818 819 a->au_id = AUX_phnum; 820 a->au_v = ap->arg_phnum; 821 a++; 822 823 a->au_id = AUX_pagesz; 824 a->au_v = PAGE_SIZE; 825 a++; 826 827 a->au_id = AUX_base; 828 a->au_v = ap->arg_interp; 829 a++; 830 831 a->au_id = AUX_flags; 832 a->au_v = 0; 833 a++; 834 835 a->au_id = AUX_entry; 836 a->au_v = ap->arg_entry; 837 a++; 838 839 a->au_id = AUX_null; 840 a->au_v = 0; 841 a++; 842 843 error = copyout(ai, epp->ep_emul_argp, sizeof ai); 844 } 845 free(ap, M_TEMP, epp->ep_emul_argsize); 846 if (interp) 847 pool_put(&namei_pool, interp); 848 return (error); 849 } 850 851 int 852 elf_os_pt_note(struct proc *p, struct exec_package *epp, Elf_Ehdr *eh, 853 char *os_name, size_t name_size, size_t desc_size) 854 { 855 char pathbuf[MAXPATHLEN]; 856 Elf_Phdr *hph, *ph; 857 Elf_Note *np = NULL; 858 size_t phsize; 859 int error; 860 861 hph = mallocarray(eh->e_phnum, sizeof(Elf_Phdr), M_TEMP, M_WAITOK); 862 phsize = eh->e_phnum * sizeof(Elf_Phdr); 863 if ((error = elf_read_from(p, epp->ep_vp, eh->e_phoff, 864 hph, phsize)) != 0) 865 goto out1; 866 867 for (ph = hph; ph < &hph[eh->e_phnum]; ph++) { 868 if (ph->p_type == PT_OPENBSD_WXNEEDED) { 869 int wxallowed = (epp->ep_vp->v_mount && 870 (epp->ep_vp->v_mount->mnt_flag & MNT_WXALLOWED)); 871 872 if (!wxallowed) { 873 error = copyinstr(epp->ep_name, &pathbuf, 874 sizeof(pathbuf), NULL); 875 log(LOG_NOTICE, 876 "%s(%d): W^X binary outside wxallowed mountpoint\n", 877 error ? "" : pathbuf, p->p_p->ps_pid); 878 error = EACCES; 879 goto out1; 880 } 881 epp->ep_flags |= EXEC_WXNEEDED; 882 break; 883 } 884 } 885 886 for (ph = hph; ph < &hph[eh->e_phnum]; ph++) { 887 if (ph->p_type != PT_NOTE || 888 ph->p_filesz > 1024 || 889 ph->p_filesz < sizeof(Elf_Note) + name_size) 890 continue; 891 892 np = malloc(ph->p_filesz, M_TEMP, M_WAITOK); 893 if ((error = elf_read_from(p, epp->ep_vp, ph->p_offset, 894 np, ph->p_filesz)) != 0) 895 goto out2; 896 897 #if 0 898 if (np->type != ELF_NOTE_TYPE_OSVERSION) { 899 free(np, M_TEMP, ph->p_filesz); 900 np = NULL; 901 continue; 902 } 903 #endif 904 905 /* Check the name and description sizes. */ 906 if (np->namesz != name_size || 907 np->descsz != desc_size) 908 goto out3; 909 910 if (memcmp((np + 1), os_name, name_size)) 911 goto out3; 912 913 /* XXX: We could check for the specific emulation here */ 914 /* All checks succeeded. */ 915 error = 0; 916 goto out2; 917 } 918 919 out3: 920 error = ENOEXEC; 921 out2: 922 free(np, M_TEMP, ph->p_filesz); 923 out1: 924 free(hph, M_TEMP, phsize); 925 return error; 926 } 927 928 /* 929 * Start of routines related to dumping core 930 */ 931 932 #ifdef SMALL_KERNEL 933 int 934 coredump_elf(struct proc *p, void *cookie) 935 { 936 return EPERM; 937 } 938 #else /* !SMALL_KERNEL */ 939 940 struct writesegs_state { 941 off_t notestart; 942 off_t secstart; 943 off_t secoff; 944 struct proc *p; 945 void *iocookie; 946 Elf_Phdr *psections; 947 size_t psectionslen; 948 size_t notesize; 949 int npsections; 950 }; 951 952 uvm_coredump_setup_cb coredump_setup_elf; 953 uvm_coredump_walk_cb coredump_walk_elf; 954 955 int coredump_notes_elf(struct proc *, void *, size_t *); 956 int coredump_note_elf(struct proc *, void *, size_t *); 957 int coredump_writenote_elf(struct proc *, void *, Elf_Note *, 958 const char *, void *); 959 960 #define ELFROUNDSIZE sizeof(Elf_Word) 961 #define elfround(x) roundup((x), ELFROUNDSIZE) 962 963 int 964 coredump_elf(struct proc *p, void *cookie) 965 { 966 #ifdef DIAGNOSTIC 967 off_t offset; 968 #endif 969 struct writesegs_state ws; 970 size_t notesize; 971 int error, i; 972 973 ws.p = p; 974 ws.iocookie = cookie; 975 ws.psections = NULL; 976 977 /* 978 * Walk the map to get all the segment offsets and lengths, 979 * write out the ELF header. 980 */ 981 error = uvm_coredump_walkmap(p, coredump_setup_elf, 982 coredump_walk_elf, &ws); 983 if (error) 984 goto out; 985 986 error = coredump_write(cookie, UIO_SYSSPACE, ws.psections, 987 ws.psectionslen); 988 if (error) 989 goto out; 990 991 /* Write out the notes. */ 992 error = coredump_notes_elf(p, cookie, ¬esize); 993 if (error) 994 goto out; 995 996 #ifdef DIAGNOSTIC 997 if (notesize != ws.notesize) 998 panic("coredump: notesize changed: %zu != %zu", 999 ws.notesize, notesize); 1000 offset = ws.notestart + notesize; 1001 if (offset != ws.secstart) 1002 panic("coredump: offset %lld != secstart %lld", 1003 (long long) offset, (long long) ws.secstart); 1004 #endif 1005 1006 /* Pass 3: finally, write the sections themselves. */ 1007 for (i = 0; i < ws.npsections - 1; i++) { 1008 Elf_Phdr *pent = &ws.psections[i]; 1009 if (pent->p_filesz == 0) 1010 continue; 1011 1012 #ifdef DIAGNOSTIC 1013 if (offset != pent->p_offset) 1014 panic("coredump: offset %lld != p_offset[%d] %lld", 1015 (long long) offset, i, 1016 (long long) pent->p_filesz); 1017 #endif 1018 1019 error = coredump_write(cookie, UIO_USERSPACE, 1020 (void *)(vaddr_t)pent->p_vaddr, pent->p_filesz); 1021 if (error) 1022 goto out; 1023 1024 coredump_unmap(cookie, (vaddr_t)pent->p_vaddr, 1025 (vaddr_t)pent->p_vaddr + pent->p_filesz); 1026 1027 #ifdef DIAGNOSTIC 1028 offset += ws.psections[i].p_filesz; 1029 #endif 1030 } 1031 1032 out: 1033 free(ws.psections, M_TEMP, ws.psectionslen); 1034 return (error); 1035 } 1036 1037 1038 /* 1039 * Normally we lay out core files like this: 1040 * [ELF Header] [Program headers] [Notes] [data for PT_LOAD segments] 1041 * 1042 * However, if there's >= 65535 segments then it overflows the field 1043 * in the ELF header, so the standard specifies putting a magic 1044 * number there and saving the real count in the .sh_info field of 1045 * the first *section* header...which requires generating a section 1046 * header. To avoid confusing tools, we include an .shstrtab section 1047 * as well so all the indexes look valid. So in this case we lay 1048 * out the core file like this: 1049 * [ELF Header] [Section Headers] [.shstrtab] [Program headers] \ 1050 * [Notes] [data for PT_LOAD segments] 1051 * 1052 * The 'shstrtab' structure below is data for the second of the two 1053 * section headers, plus the .shstrtab itself, in one const buffer. 1054 */ 1055 static const struct { 1056 Elf_Shdr shdr; 1057 char shstrtab[sizeof(ELF_SHSTRTAB) + 1]; 1058 } shstrtab = { 1059 .shdr = { 1060 .sh_name = 1, /* offset in .shstrtab below */ 1061 .sh_type = SHT_STRTAB, 1062 .sh_offset = sizeof(Elf_Ehdr) + 2*sizeof(Elf_Shdr), 1063 .sh_size = sizeof(ELF_SHSTRTAB) + 1, 1064 .sh_addralign = 1, 1065 }, 1066 .shstrtab = "\0" ELF_SHSTRTAB, 1067 }; 1068 1069 int 1070 coredump_setup_elf(int segment_count, void *cookie) 1071 { 1072 Elf_Ehdr ehdr; 1073 struct writesegs_state *ws = cookie; 1074 Elf_Phdr *note; 1075 int error; 1076 1077 /* Get the count of segments, plus one for the PT_NOTE */ 1078 ws->npsections = segment_count + 1; 1079 1080 /* Get the size of the notes. */ 1081 error = coredump_notes_elf(ws->p, NULL, &ws->notesize); 1082 if (error) 1083 return error; 1084 1085 /* Setup the ELF header */ 1086 memset(&ehdr, 0, sizeof(ehdr)); 1087 memcpy(ehdr.e_ident, ELFMAG, SELFMAG); 1088 ehdr.e_ident[EI_CLASS] = ELF_TARG_CLASS; 1089 ehdr.e_ident[EI_DATA] = ELF_TARG_DATA; 1090 ehdr.e_ident[EI_VERSION] = EV_CURRENT; 1091 /* XXX Should be the OSABI/ABI version of the executable. */ 1092 ehdr.e_ident[EI_OSABI] = ELFOSABI_SYSV; 1093 ehdr.e_ident[EI_ABIVERSION] = 0; 1094 ehdr.e_type = ET_CORE; 1095 /* XXX This should be the e_machine of the executable. */ 1096 ehdr.e_machine = ELF_TARG_MACH; 1097 ehdr.e_version = EV_CURRENT; 1098 ehdr.e_entry = 0; 1099 ehdr.e_flags = 0; 1100 ehdr.e_ehsize = sizeof(ehdr); 1101 ehdr.e_phentsize = sizeof(Elf_Phdr); 1102 1103 if (ws->npsections < PN_XNUM) { 1104 ehdr.e_phoff = sizeof(ehdr); 1105 ehdr.e_shoff = 0; 1106 ehdr.e_phnum = ws->npsections; 1107 ehdr.e_shentsize = 0; 1108 ehdr.e_shnum = 0; 1109 ehdr.e_shstrndx = 0; 1110 } else { 1111 /* too many segments, use extension setup */ 1112 ehdr.e_shoff = sizeof(ehdr); 1113 ehdr.e_phnum = PN_XNUM; 1114 ehdr.e_shentsize = sizeof(Elf_Shdr); 1115 ehdr.e_shnum = 2; 1116 ehdr.e_shstrndx = 1; 1117 ehdr.e_phoff = shstrtab.shdr.sh_offset + shstrtab.shdr.sh_size; 1118 } 1119 1120 /* Write out the ELF header. */ 1121 error = coredump_write(ws->iocookie, UIO_SYSSPACE, &ehdr, sizeof(ehdr)); 1122 if (error) 1123 return error; 1124 1125 /* 1126 * If an section header is needed to store extension info, write 1127 * it out after the ELF header and before the program header. 1128 */ 1129 if (ehdr.e_shnum != 0) { 1130 Elf_Shdr shdr = { .sh_info = ws->npsections }; 1131 error = coredump_write(ws->iocookie, UIO_SYSSPACE, &shdr, 1132 sizeof shdr); 1133 if (error) 1134 return error; 1135 error = coredump_write(ws->iocookie, UIO_SYSSPACE, &shstrtab, 1136 sizeof(shstrtab.shdr) + sizeof(shstrtab.shstrtab)); 1137 if (error) 1138 return error; 1139 } 1140 1141 /* 1142 * Allocate the segment header array and setup to collect 1143 * the section sizes and offsets 1144 */ 1145 ws->psections = mallocarray(ws->npsections, sizeof(Elf_Phdr), 1146 M_TEMP, M_WAITOK|M_ZERO); 1147 ws->psectionslen = ws->npsections * sizeof(Elf_Phdr); 1148 1149 ws->notestart = ehdr.e_phoff + ws->psectionslen; 1150 ws->secstart = ws->notestart + ws->notesize; 1151 ws->secoff = ws->secstart; 1152 1153 /* Fill in the PT_NOTE segment header in the last slot */ 1154 note = &ws->psections[ws->npsections - 1]; 1155 note->p_type = PT_NOTE; 1156 note->p_offset = ws->notestart; 1157 note->p_vaddr = 0; 1158 note->p_paddr = 0; 1159 note->p_filesz = ws->notesize; 1160 note->p_memsz = 0; 1161 note->p_flags = PF_R; 1162 note->p_align = ELFROUNDSIZE; 1163 1164 return (0); 1165 } 1166 1167 int 1168 coredump_walk_elf(vaddr_t start, vaddr_t realend, vaddr_t end, vm_prot_t prot, 1169 int nsegment, void *cookie) 1170 { 1171 struct writesegs_state *ws = cookie; 1172 Elf_Phdr phdr; 1173 vsize_t size, realsize; 1174 1175 size = end - start; 1176 realsize = realend - start; 1177 1178 phdr.p_type = PT_LOAD; 1179 phdr.p_offset = ws->secoff; 1180 phdr.p_vaddr = start; 1181 phdr.p_paddr = 0; 1182 phdr.p_filesz = realsize; 1183 phdr.p_memsz = size; 1184 phdr.p_flags = 0; 1185 if (prot & PROT_READ) 1186 phdr.p_flags |= PF_R; 1187 if (prot & PROT_WRITE) 1188 phdr.p_flags |= PF_W; 1189 if (prot & PROT_EXEC) 1190 phdr.p_flags |= PF_X; 1191 phdr.p_align = PAGE_SIZE; 1192 1193 ws->secoff += phdr.p_filesz; 1194 ws->psections[nsegment] = phdr; 1195 1196 return (0); 1197 } 1198 1199 int 1200 coredump_notes_elf(struct proc *p, void *iocookie, size_t *sizep) 1201 { 1202 struct ps_strings pss; 1203 struct iovec iov; 1204 struct uio uio; 1205 struct elfcore_procinfo cpi; 1206 Elf_Note nhdr; 1207 struct process *pr = p->p_p; 1208 struct proc *q; 1209 size_t size, notesize; 1210 int error; 1211 1212 size = 0; 1213 1214 /* First, write an elfcore_procinfo. */ 1215 notesize = sizeof(nhdr) + elfround(sizeof("OpenBSD")) + 1216 elfround(sizeof(cpi)); 1217 if (iocookie) { 1218 memset(&cpi, 0, sizeof(cpi)); 1219 1220 cpi.cpi_version = ELFCORE_PROCINFO_VERSION; 1221 cpi.cpi_cpisize = sizeof(cpi); 1222 cpi.cpi_signo = p->p_sisig; 1223 cpi.cpi_sigcode = p->p_sicode; 1224 1225 cpi.cpi_sigpend = p->p_siglist; 1226 cpi.cpi_sigmask = p->p_sigmask; 1227 cpi.cpi_sigignore = pr->ps_sigacts->ps_sigignore; 1228 cpi.cpi_sigcatch = pr->ps_sigacts->ps_sigcatch; 1229 1230 cpi.cpi_pid = pr->ps_pid; 1231 cpi.cpi_ppid = pr->ps_pptr->ps_pid; 1232 cpi.cpi_pgrp = pr->ps_pgid; 1233 if (pr->ps_session->s_leader) 1234 cpi.cpi_sid = pr->ps_session->s_leader->ps_pid; 1235 else 1236 cpi.cpi_sid = 0; 1237 1238 cpi.cpi_ruid = p->p_ucred->cr_ruid; 1239 cpi.cpi_euid = p->p_ucred->cr_uid; 1240 cpi.cpi_svuid = p->p_ucred->cr_svuid; 1241 1242 cpi.cpi_rgid = p->p_ucred->cr_rgid; 1243 cpi.cpi_egid = p->p_ucred->cr_gid; 1244 cpi.cpi_svgid = p->p_ucred->cr_svgid; 1245 1246 (void)strlcpy(cpi.cpi_name, pr->ps_comm, sizeof(cpi.cpi_name)); 1247 1248 nhdr.namesz = sizeof("OpenBSD"); 1249 nhdr.descsz = sizeof(cpi); 1250 nhdr.type = NT_OPENBSD_PROCINFO; 1251 1252 error = coredump_writenote_elf(p, iocookie, &nhdr, 1253 "OpenBSD", &cpi); 1254 if (error) 1255 return (error); 1256 } 1257 size += notesize; 1258 1259 /* Second, write an NT_OPENBSD_AUXV note. */ 1260 notesize = sizeof(nhdr) + elfround(sizeof("OpenBSD")) + 1261 elfround(pr->ps_emul->e_arglen * sizeof(char *)); 1262 if (iocookie) { 1263 iov.iov_base = &pss; 1264 iov.iov_len = sizeof(pss); 1265 uio.uio_iov = &iov; 1266 uio.uio_iovcnt = 1; 1267 uio.uio_offset = (off_t)pr->ps_strings; 1268 uio.uio_resid = sizeof(pss); 1269 uio.uio_segflg = UIO_SYSSPACE; 1270 uio.uio_rw = UIO_READ; 1271 uio.uio_procp = NULL; 1272 1273 error = uvm_io(&p->p_vmspace->vm_map, &uio, 0); 1274 if (error) 1275 return (error); 1276 1277 if (pss.ps_envstr == NULL) 1278 return (EIO); 1279 1280 nhdr.namesz = sizeof("OpenBSD"); 1281 nhdr.descsz = pr->ps_emul->e_arglen * sizeof(char *); 1282 nhdr.type = NT_OPENBSD_AUXV; 1283 1284 error = coredump_write(iocookie, UIO_SYSSPACE, 1285 &nhdr, sizeof(nhdr)); 1286 if (error) 1287 return (error); 1288 1289 error = coredump_write(iocookie, UIO_SYSSPACE, 1290 "OpenBSD", elfround(nhdr.namesz)); 1291 if (error) 1292 return (error); 1293 1294 error = coredump_write(iocookie, UIO_USERSPACE, 1295 pss.ps_envstr + pss.ps_nenvstr + 1, nhdr.descsz); 1296 if (error) 1297 return (error); 1298 } 1299 size += notesize; 1300 1301 #ifdef PT_WCOOKIE 1302 notesize = sizeof(nhdr) + elfround(sizeof("OpenBSD")) + 1303 elfround(sizeof(register_t)); 1304 if (iocookie) { 1305 register_t wcookie; 1306 1307 nhdr.namesz = sizeof("OpenBSD"); 1308 nhdr.descsz = sizeof(register_t); 1309 nhdr.type = NT_OPENBSD_WCOOKIE; 1310 1311 wcookie = process_get_wcookie(p); 1312 error = coredump_writenote_elf(p, iocookie, &nhdr, 1313 "OpenBSD", &wcookie); 1314 if (error) 1315 return (error); 1316 } 1317 size += notesize; 1318 #endif 1319 1320 /* 1321 * Now write the register info for the thread that caused the 1322 * coredump. 1323 */ 1324 error = coredump_note_elf(p, iocookie, ¬esize); 1325 if (error) 1326 return (error); 1327 size += notesize; 1328 1329 /* 1330 * Now, for each thread, write the register info and any other 1331 * per-thread notes. Since we're dumping core, all the other 1332 * threads in the process have been stopped and the list can't 1333 * change. 1334 */ 1335 TAILQ_FOREACH(q, &pr->ps_threads, p_thr_link) { 1336 if (q == p) /* we've taken care of this thread */ 1337 continue; 1338 error = coredump_note_elf(q, iocookie, ¬esize); 1339 if (error) 1340 return (error); 1341 size += notesize; 1342 } 1343 1344 *sizep = size; 1345 return (0); 1346 } 1347 1348 int 1349 coredump_note_elf(struct proc *p, void *iocookie, size_t *sizep) 1350 { 1351 Elf_Note nhdr; 1352 int size, notesize, error; 1353 int namesize; 1354 char name[64+ELFROUNDSIZE]; 1355 struct reg intreg; 1356 #ifdef PT_GETFPREGS 1357 struct fpreg freg; 1358 #endif 1359 1360 size = 0; 1361 1362 snprintf(name, sizeof(name)-ELFROUNDSIZE, "%s@%d", 1363 "OpenBSD", p->p_tid + THREAD_PID_OFFSET); 1364 namesize = strlen(name) + 1; 1365 memset(name + namesize, 0, elfround(namesize) - namesize); 1366 1367 notesize = sizeof(nhdr) + elfround(namesize) + elfround(sizeof(intreg)); 1368 if (iocookie) { 1369 error = process_read_regs(p, &intreg); 1370 if (error) 1371 return (error); 1372 1373 nhdr.namesz = namesize; 1374 nhdr.descsz = sizeof(intreg); 1375 nhdr.type = NT_OPENBSD_REGS; 1376 1377 error = coredump_writenote_elf(p, iocookie, &nhdr, 1378 name, &intreg); 1379 if (error) 1380 return (error); 1381 1382 } 1383 size += notesize; 1384 1385 #ifdef PT_GETFPREGS 1386 notesize = sizeof(nhdr) + elfround(namesize) + elfround(sizeof(freg)); 1387 if (iocookie) { 1388 error = process_read_fpregs(p, &freg); 1389 if (error) 1390 return (error); 1391 1392 nhdr.namesz = namesize; 1393 nhdr.descsz = sizeof(freg); 1394 nhdr.type = NT_OPENBSD_FPREGS; 1395 1396 error = coredump_writenote_elf(p, iocookie, &nhdr, name, &freg); 1397 if (error) 1398 return (error); 1399 } 1400 size += notesize; 1401 #endif 1402 1403 *sizep = size; 1404 /* XXX Add hook for machdep per-LWP notes. */ 1405 return (0); 1406 } 1407 1408 int 1409 coredump_writenote_elf(struct proc *p, void *cookie, Elf_Note *nhdr, 1410 const char *name, void *data) 1411 { 1412 int error; 1413 1414 error = coredump_write(cookie, UIO_SYSSPACE, nhdr, sizeof(*nhdr)); 1415 if (error) 1416 return error; 1417 1418 error = coredump_write(cookie, UIO_SYSSPACE, name, 1419 elfround(nhdr->namesz)); 1420 if (error) 1421 return error; 1422 1423 return coredump_write(cookie, UIO_SYSSPACE, data, nhdr->descsz); 1424 } 1425 #endif /* !SMALL_KERNEL */ 1426