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