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