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