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