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