exec_elf32.c revision 1.50
1/* $NetBSD: exec_elf32.c,v 1.50 2000/06/26 14:38:54 mrg Exp $ */ 2 3/*- 4 * Copyright (c) 1994 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christos Zoulas. 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. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39/* 40 * Copyright (c) 1996 Christopher G. Demetriou 41 * All rights reserved. 42 * 43 * Redistribution and use in source and binary forms, with or without 44 * modification, are permitted provided that the following conditions 45 * are met: 46 * 1. Redistributions of source code must retain the above copyright 47 * notice, this list of conditions and the following disclaimer. 48 * 2. Redistributions in binary form must reproduce the above copyright 49 * notice, this list of conditions and the following disclaimer in the 50 * documentation and/or other materials provided with the distribution. 51 * 3. The name of the author may not be used to endorse or promote products 52 * derived from this software without specific prior written permission 53 * 54 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 55 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 56 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 57 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 58 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 59 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 60 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 61 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 62 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 63 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 64 */ 65 66/* If not included by exec_elf64.c, ELFSIZE won't be defined. */ 67#ifndef ELFSIZE 68#define ELFSIZE 32 69#endif 70 71#include "opt_compat_linux.h" 72#include "opt_compat_ibcs2.h" 73#include "opt_compat_svr4.h" 74#include "opt_compat_freebsd.h" 75#include "opt_compat_netbsd32.h" 76#include "opt_syscall_debug.h" 77 78#include <sys/param.h> 79#include <sys/systm.h> 80#include <sys/kernel.h> 81#include <sys/proc.h> 82#include <sys/malloc.h> 83#include <sys/namei.h> 84#include <sys/vnode.h> 85#include <sys/exec.h> 86#include <sys/exec_elf.h> 87#include <sys/fcntl.h> 88#include <sys/syscall.h> 89#include <sys/signalvar.h> 90#include <sys/mount.h> 91#include <sys/stat.h> 92 93#include <sys/mman.h> 94#include <vm/vm.h> 95 96#include <machine/cpu.h> 97#include <machine/reg.h> 98 99#ifdef COMPAT_NETBSD32 100#include <compat/netbsd32/netbsd32_exec.h> 101#endif 102 103#ifdef COMPAT_LINUX 104#include <compat/linux/common/linux_exec.h> 105#endif 106 107#ifdef COMPAT_SVR4 108#include <compat/svr4/svr4_exec.h> 109#endif 110 111#ifdef COMPAT_IBCS2 112#include <compat/ibcs2/ibcs2_exec.h> 113#endif 114 115#ifdef COMPAT_FREEBSD 116#include <compat/freebsd/freebsd_exec.h> 117#endif 118 119int ELFNAME(check_header) __P((Elf_Ehdr *, int)); 120int ELFNAME(load_file) __P((struct proc *, struct exec_package *, char *, 121 struct exec_vmcmd_set *, u_long *, struct elf_args *, Elf_Addr *)); 122void ELFNAME(load_psection) __P((struct exec_vmcmd_set *, struct vnode *, 123 Elf_Phdr *, Elf_Addr *, u_long *, int *)); 124 125int ELFNAME2(netbsd,signature) __P((struct proc *, struct exec_package *, 126 Elf_Ehdr *)); 127static int ELFNAME2(netbsd,probe) __P((struct proc *, struct exec_package *, 128 Elf_Ehdr *, char *, Elf_Addr *)); 129 130extern char sigcode[], esigcode[]; 131#ifdef SYSCALL_DEBUG 132extern char *syscallnames[]; 133#endif 134 135struct emul ELFNAMEEND(emul_netbsd) = { 136 "netbsd", 137 NULL, 138 sendsig, 139 SYS_syscall, 140 SYS_MAXSYSCALL, 141 sysent, 142#ifdef SYSCALL_DEBUG 143 syscallnames, 144#else 145 NULL, 146#endif 147 howmany(ELF_AUX_ENTRIES * sizeof(AuxInfo), sizeof (Elf_Addr)), 148 ELFNAME(copyargs), 149 setregs, 150 sigcode, 151 esigcode, 152}; 153 154int (*ELFNAME(probe_funcs)[]) __P((struct proc *, struct exec_package *, 155 Elf_Ehdr *, char *, Elf_Addr *)) = { 156#if defined(COMPAT_NETBSD32) && (ELFSIZE == 32) 157 /* This one should go first so it matches instead of netbsd */ 158 ELFNAME2(netbsd32,probe), 159#endif 160 ELFNAME2(netbsd,probe), 161#if defined(COMPAT_FREEBSD) && (ELFSIZE == 32) 162 ELFNAME2(freebsd,probe), /* XXX not 64-bit safe */ 163#endif 164#if defined(COMPAT_LINUX) 165 ELFNAME2(linux,probe), 166#endif 167#if defined(COMPAT_SVR4) && (ELFSIZE == 32) 168 ELFNAME2(svr4,probe), /* XXX not 64-bit safe */ 169#endif 170#if defined(COMPAT_IBCS2) && (ELFSIZE == 32) 171 ELFNAME2(ibcs2,probe), /* XXX not 64-bit safe */ 172#endif 173}; 174 175/* round up and down to page boundaries. */ 176#define ELF_ROUND(a, b) (((a) + (b) - 1) & ~((b) - 1)) 177#define ELF_TRUNC(a, b) ((a) & ~((b) - 1)) 178 179/* 180 * Copy arguments onto the stack in the normal way, but add some 181 * extra information in case of dynamic binding. 182 */ 183void * 184ELFNAME(copyargs)(pack, arginfo, stack, argp) 185 struct exec_package *pack; 186 struct ps_strings *arginfo; 187 void *stack; 188 void *argp; 189{ 190 size_t len; 191 AuxInfo ai[ELF_AUX_ENTRIES], *a; 192 struct elf_args *ap; 193 194 stack = copyargs(pack, arginfo, stack, argp); 195 if (!stack) 196 return NULL; 197 198 a = ai; 199 200 /* 201 * Push extra arguments on the stack needed by dynamically 202 * linked binaries 203 */ 204 if ((ap = (struct elf_args *)pack->ep_emul_arg)) { 205 206 a->a_type = AT_PHDR; 207 a->a_v = ap->arg_phaddr; 208 a++; 209 210 a->a_type = AT_PHENT; 211 a->a_v = ap->arg_phentsize; 212 a++; 213 214 a->a_type = AT_PHNUM; 215 a->a_v = ap->arg_phnum; 216 a++; 217 218 a->a_type = AT_PAGESZ; 219 a->a_v = NBPG; 220 a++; 221 222 a->a_type = AT_BASE; 223 a->a_v = ap->arg_interp; 224 a++; 225 226 a->a_type = AT_FLAGS; 227 a->a_v = 0; 228 a++; 229 230 a->a_type = AT_ENTRY; 231 a->a_v = ap->arg_entry; 232 a++; 233 234 free((char *)ap, M_TEMP); 235 pack->ep_emul_arg = NULL; 236 } 237 238 a->a_type = AT_NULL; 239 a->a_v = 0; 240 a++; 241 242 len = (a - ai) * sizeof(AuxInfo); 243 if (copyout(ai, stack, len)) 244 return NULL; 245 stack = (caddr_t)stack + len; 246 247 return stack; 248} 249 250/* 251 * elf_check_header(): 252 * 253 * Check header for validity; return 0 of ok ENOEXEC if error 254 */ 255int 256ELFNAME(check_header)(eh, type) 257 Elf_Ehdr *eh; 258 int type; 259{ 260 261 if (memcmp(eh->e_ident, ELFMAG, SELFMAG) != 0 || 262 eh->e_ident[EI_CLASS] != ELFCLASS) 263 264 switch (eh->e_machine) { 265 266 ELFDEFNNAME(MACHDEP_ID_CASES) 267 268 default: 269 return ENOEXEC; 270 } 271 272 if (eh->e_type != type) 273 return ENOEXEC; 274 275 return 0; 276} 277 278/* 279 * elf_load_psection(): 280 * 281 * Load a psection at the appropriate address 282 */ 283void 284ELFNAME(load_psection)(vcset, vp, ph, addr, size, prot) 285 struct exec_vmcmd_set *vcset; 286 struct vnode *vp; 287 Elf_Phdr *ph; 288 Elf_Addr *addr; 289 u_long *size; 290 int *prot; 291{ 292 u_long uaddr, msize, psize, rm, rf; 293 long diff, offset; 294 295 /* 296 * If the user specified an address, then we load there. 297 */ 298 if (*addr != ELFDEFNNAME(NO_ADDR)) { 299 if (ph->p_align > 1) { 300 *addr = ELF_ROUND(*addr, ph->p_align); 301 uaddr = ELF_TRUNC(ph->p_vaddr, ph->p_align); 302 } else 303 uaddr = ph->p_vaddr; 304 diff = ph->p_vaddr - uaddr; 305 } else { 306 *addr = uaddr = ph->p_vaddr; 307 if (ph->p_align > 1) 308 *addr = ELF_TRUNC(uaddr, ph->p_align); 309 diff = uaddr - *addr; 310 } 311 312 *prot |= (ph->p_flags & PF_R) ? VM_PROT_READ : 0; 313 *prot |= (ph->p_flags & PF_W) ? VM_PROT_WRITE : 0; 314 *prot |= (ph->p_flags & PF_X) ? VM_PROT_EXECUTE : 0; 315 316 offset = ph->p_offset - diff; 317 *size = ph->p_filesz + diff; 318 msize = ph->p_memsz + diff; 319 psize = round_page(*size); 320 321 if ((ph->p_flags & PF_W) != 0) { 322 /* 323 * Because the pagedvn pager can't handle zero fill of the last 324 * data page if it's not page aligned we map the last page 325 * readvn. 326 */ 327 psize = trunc_page(*size); 328 NEW_VMCMD(vcset, vmcmd_map_pagedvn, psize, *addr, vp, 329 offset, *prot); 330 if(psize != *size) 331 NEW_VMCMD(vcset, vmcmd_map_readvn, *size - psize, 332 *addr + psize, vp, offset + psize, *prot); 333 } else 334 NEW_VMCMD(vcset, vmcmd_map_pagedvn, psize, *addr, vp, 335 offset, *prot); 336 337 /* 338 * Check if we need to extend the size of the segment 339 */ 340 rm = round_page(*addr + msize); 341 rf = round_page(*addr + *size); 342 343 if (rm != rf) { 344 NEW_VMCMD(vcset, vmcmd_map_zero, rm - rf, rf, NULLVP, 345 0, *prot); 346 *size = msize; 347 } 348} 349 350/* 351 * elf_read_from(): 352 * 353 * Read from vnode into buffer at offset. 354 */ 355int 356ELFNAME(read_from)(p, vp, off, buf, size) 357 struct vnode *vp; 358 u_long off; 359 struct proc *p; 360 caddr_t buf; 361 int size; 362{ 363 int error; 364 size_t resid; 365 366 if ((error = vn_rdwr(UIO_READ, vp, buf, size, off, UIO_SYSSPACE, 367 0, p->p_ucred, &resid, p)) != 0) 368 return error; 369 /* 370 * See if we got all of it 371 */ 372 if (resid != 0) 373 return ENOEXEC; 374 return 0; 375} 376 377/* 378 * elf_load_file(): 379 * 380 * Load a file (interpreter/library) pointed to by path 381 * [stolen from coff_load_shlib()]. Made slightly generic 382 * so it might be used externally. 383 */ 384int 385ELFNAME(load_file)(p, epp, path, vcset, entry, ap, last) 386 struct proc *p; 387 struct exec_package *epp; 388 char *path; 389 struct exec_vmcmd_set *vcset; 390 u_long *entry; 391 struct elf_args *ap; 392 Elf_Addr *last; 393{ 394 int error, i; 395 struct nameidata nd; 396 struct vnode *vp; 397 struct vattr attr; 398 Elf_Ehdr eh; 399 Elf_Phdr *ph = NULL; 400 u_long phsize; 401 char *bp = NULL; 402 Elf_Addr addr = *last; 403 404 bp = path; 405 /* 406 * 1. open file 407 * 2. read filehdr 408 * 3. map text, data, and bss out of it using VM_* 409 */ 410 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, p); 411 if ((error = namei(&nd)) != 0) 412 return error; 413 vp = nd.ni_vp; 414 415 /* 416 * Similarly, if it's not marked as executable, or it's not a regular 417 * file, we don't allow it to be used. 418 */ 419 if (vp->v_type != VREG) { 420 error = EACCES; 421 goto badunlock; 422 } 423 if ((error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p)) != 0) 424 goto badunlock; 425 426 /* get attributes */ 427 if ((error = VOP_GETATTR(vp, &attr, p->p_ucred, p)) != 0) 428 goto badunlock; 429 430 /* 431 * Check mount point. Though we're not trying to exec this binary, 432 * we will be executing code from it, so if the mount point 433 * disallows execution or set-id-ness, we punt or kill the set-id. 434 */ 435 if (vp->v_mount->mnt_flag & MNT_NOEXEC) { 436 error = EACCES; 437 goto badunlock; 438 } 439 if (vp->v_mount->mnt_flag & MNT_NOSUID) 440 epp->ep_vap->va_mode &= ~(S_ISUID | S_ISGID); 441 442#ifdef notyet /* XXX cgd 960926 */ 443 XXX cgd 960926: (maybe) VOP_OPEN it (and VOP_CLOSE in copyargs?) 444#endif 445 VOP_UNLOCK(vp, 0); 446 447 if ((error = ELFNAME(read_from)(p, vp, 0, (caddr_t) &eh, 448 sizeof(eh))) != 0) 449 goto bad; 450 451 if ((error = ELFNAME(check_header)(&eh, ET_DYN)) != 0) 452 goto bad; 453 454 phsize = eh.e_phnum * sizeof(Elf_Phdr); 455 ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); 456 457 if ((error = ELFNAME(read_from)(p, vp, eh.e_phoff, 458 (caddr_t) ph, phsize)) != 0) 459 goto bad; 460 461 /* 462 * Load all the necessary sections 463 */ 464 for (i = 0; i < eh.e_phnum; i++) { 465 u_long size = 0; 466 int prot = 0; 467 468 switch (ph[i].p_type) { 469 case PT_LOAD: 470 ELFNAME(load_psection)(vcset, vp, &ph[i], &addr, 471 &size, &prot); 472 /* If entry is within this section it must be text */ 473 if (eh.e_entry >= ph[i].p_vaddr && 474 eh.e_entry < (ph[i].p_vaddr + size)) { 475 /* XXX */ 476 *entry = addr + eh.e_entry; 477#ifdef mips 478 *entry -= ph[i].p_vaddr; 479#endif 480 ap->arg_interp = addr; 481 } 482 addr += size; 483 break; 484 485 case PT_DYNAMIC: 486 case PT_PHDR: 487 case PT_NOTE: 488 break; 489 490 default: 491 break; 492 } 493 } 494 495 free((char *)ph, M_TEMP); 496 *last = addr; 497 vrele(vp); 498 return 0; 499 500badunlock: 501 VOP_UNLOCK(vp, 0); 502 503bad: 504 if (ph != NULL) 505 free((char *)ph, M_TEMP); 506#ifdef notyet /* XXX cgd 960926 */ 507 (maybe) VOP_CLOSE it 508#endif 509 vrele(vp); 510 return error; 511} 512 513/* 514 * exec_elf_makecmds(): Prepare an Elf binary's exec package 515 * 516 * First, set of the various offsets/lengths in the exec package. 517 * 518 * Then, mark the text image busy (so it can be demand paged) or error 519 * out if this is not possible. Finally, set up vmcmds for the 520 * text, data, bss, and stack segments. 521 */ 522int 523ELFNAME2(exec,makecmds)(p, epp) 524 struct proc *p; 525 struct exec_package *epp; 526{ 527 Elf_Ehdr *eh = epp->ep_hdr; 528 Elf_Phdr *ph, *pp; 529 Elf_Addr phdr = 0, pos = 0; 530 int error, i, n, nload; 531 char interp[MAXPATHLEN]; 532 u_long phsize; 533 534 if (epp->ep_hdrvalid < sizeof(Elf_Ehdr)) 535 return ENOEXEC; 536 537 /* 538 * XXX allow for executing shared objects. It seems silly 539 * but other ELF-based systems allow it as well. 540 */ 541 if (ELFNAME(check_header)(eh, ET_EXEC) != 0 && 542 ELFNAME(check_header)(eh, ET_DYN) != 0) 543 return ENOEXEC; 544 545 /* 546 * check if vnode is in open for writing, because we want to 547 * demand-page out of it. if it is, don't do it, for various 548 * reasons 549 */ 550 if (epp->ep_vp->v_writecount != 0) { 551#ifdef DIAGNOSTIC 552 if (epp->ep_vp->v_flag & VTEXT) 553 panic("exec: a VTEXT vnode has writecount != 0\n"); 554#endif 555 return ETXTBSY; 556 } 557 /* 558 * Allocate space to hold all the program headers, and read them 559 * from the file 560 */ 561 phsize = eh->e_phnum * sizeof(Elf_Phdr); 562 ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); 563 564 if ((error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_phoff, 565 (caddr_t) ph, phsize)) != 0) 566 goto bad; 567 568 epp->ep_taddr = epp->ep_tsize = ELFDEFNNAME(NO_ADDR); 569 epp->ep_daddr = epp->ep_dsize = ELFDEFNNAME(NO_ADDR); 570 571 interp[0] = '\0'; 572 573 for (i = 0; i < eh->e_phnum; i++) { 574 pp = &ph[i]; 575 if (pp->p_type == PT_INTERP) { 576 if (pp->p_filesz >= sizeof(interp)) 577 goto bad; 578 if ((error = ELFNAME(read_from)(p, epp->ep_vp, 579 pp->p_offset, (caddr_t) interp, 580 pp->p_filesz)) != 0) 581 goto bad; 582 break; 583 } 584 } 585 586 /* 587 * Setup things for native emulation. 588 */ 589 epp->ep_emul = &ELFNAMEEND(emul_netbsd); 590 pos = ELFDEFNNAME(NO_ADDR); 591 592 /* 593 * On the same architecture, we may be emulating different systems. 594 * See which one will accept this executable. This currently only 595 * applies to SVR4, and IBCS2 on the i386 and Linux on the i386 596 * and the Alpha. 597 * 598 * Probe functions would normally see if the interpreter (if any) 599 * exists. Emulation packages may possibly replace the interpreter in 600 * interp[] with a changed path (/emul/xxx/<path>), and also 601 * set the ep_emul field in the exec package structure. 602 */ 603 n = sizeof(ELFNAME(probe_funcs)) / sizeof(ELFNAME(probe_funcs)[0]); 604 if (n != 0) { 605 error = ENOEXEC; 606 for (i = 0; i < n && error; i++) 607 error = ELFNAME(probe_funcs)[i](p, epp, eh, 608 interp, &pos); 609#ifdef notyet 610 /* 611 * We should really use a signature in our native binaries 612 * and have our own probe function for matching binaries, 613 * before trying the emulations. For now, if the emulation 614 * probes failed we default to native. 615 */ 616 if (error) 617 goto bad; 618#endif 619 } 620 621 /* 622 * Load all the necessary sections 623 */ 624 for (i = nload = 0; i < eh->e_phnum; i++) { 625 Elf_Addr addr = ELFDEFNNAME(NO_ADDR); 626 u_long size = 0; 627 int prot = 0; 628 629 pp = &ph[i]; 630 631 switch (ph[i].p_type) { 632 case PT_LOAD: 633 /* 634 * XXX 635 * Can handle only 2 sections: text and data 636 */ 637 if (nload++ == 2) 638 goto bad; 639 ELFNAME(load_psection)(&epp->ep_vmcmds, epp->ep_vp, 640 &ph[i], &addr, &size, &prot); 641 642 /* 643 * Decide whether it's text or data by looking 644 * at the entry point. 645 */ 646 if (eh->e_entry >= addr && 647 eh->e_entry < (addr + size)) { 648 epp->ep_taddr = addr; 649 epp->ep_tsize = size; 650 if (epp->ep_daddr == ELFDEFNNAME(NO_ADDR)) { 651 epp->ep_daddr = addr; 652 epp->ep_dsize = size; 653 } 654 } else { 655 epp->ep_daddr = addr; 656 epp->ep_dsize = size; 657 } 658 break; 659 660 case PT_SHLIB: 661#ifndef COMPAT_IBCS2 /* SCO has these sections */ 662 error = ENOEXEC; 663 goto bad; 664#endif 665 666 case PT_INTERP: 667 /* Already did this one */ 668 case PT_DYNAMIC: 669 case PT_NOTE: 670 break; 671 672 case PT_PHDR: 673 /* Note address of program headers (in text segment) */ 674 phdr = pp->p_vaddr; 675 break; 676 677 default: 678 /* 679 * Not fatal; we don't need to understand everything. 680 */ 681 break; 682 } 683 } 684 685 /* this breaks on, e.g., OpenBSD-compatible mips shared binaries. */ 686#ifndef ELF_INTERP_NON_RELOCATABLE 687 /* 688 * If no position to load the interpreter was set by a probe 689 * function, pick the same address that a non-fixed mmap(0, ..) 690 * would (i.e. something safely out of the way). 691 */ 692 if (pos == ELFDEFNNAME(NO_ADDR)) 693 pos = round_page(epp->ep_daddr + MAXDSIZ); 694#endif /* !ELF_INTERP_NON_RELOCATABLE */ 695 696 /* 697 * Check if we found a dynamically linked binary and arrange to load 698 * it's interpreter 699 */ 700 if (interp[0]) { 701 struct elf_args *ap; 702 703 ap = (struct elf_args *)malloc(sizeof(struct elf_args), 704 M_TEMP, M_WAITOK); 705 if ((error = ELFNAME(load_file)(p, epp, interp, 706 &epp->ep_vmcmds, &epp->ep_entry, ap, &pos)) != 0) { 707 free((char *)ap, M_TEMP); 708 goto bad; 709 } 710 pos += phsize; 711 ap->arg_phaddr = phdr; 712 713 ap->arg_phentsize = eh->e_phentsize; 714 ap->arg_phnum = eh->e_phnum; 715 ap->arg_entry = eh->e_entry; 716 717 epp->ep_emul_arg = ap; 718 } else 719 epp->ep_entry = eh->e_entry; 720 721#ifdef ELF_MAP_PAGE_ZERO 722 /* Dell SVR4 maps page zero, yeuch! */ 723 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, NBPG, 0, epp->ep_vp, 0, 724 VM_PROT_READ); 725#endif 726 free((char *)ph, M_TEMP); 727 vn_marktext(epp->ep_vp); 728 return exec_elf_setup_stack(p, epp); 729 730bad: 731 free((char *)ph, M_TEMP); 732 kill_vmcmds(&epp->ep_vmcmds); 733 return ENOEXEC; 734} 735 736int 737ELFNAME2(netbsd,signature)(p, epp, eh) 738 struct proc *p; 739 struct exec_package *epp; 740 Elf_Ehdr *eh; 741{ 742 Elf_Phdr *hph, *ph; 743 Elf_Nhdr *np = NULL; 744 size_t phsize; 745 int error; 746 747 phsize = eh->e_phnum * sizeof(Elf_Phdr); 748 hph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); 749 if ((error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_phoff, 750 (caddr_t)hph, phsize)) != 0) 751 goto out1; 752 753 for (ph = hph; ph < &hph[eh->e_phnum]; ph++) { 754 if (ph->p_type != PT_NOTE || 755 ph->p_filesz < sizeof(Elf_Nhdr) + ELF_NOTE_NETBSD_NAMESZ) 756 continue; 757 758 np = (Elf_Nhdr *)malloc(ph->p_filesz, M_TEMP, M_WAITOK); 759 if ((error = ELFNAME(read_from)(p, epp->ep_vp, ph->p_offset, 760 (caddr_t)np, ph->p_filesz)) != 0) 761 goto out2; 762 763 if (np->n_type != ELF_NOTE_TYPE_OSVERSION) { 764 free(np, M_TEMP); 765 np = NULL; 766 continue; 767 } 768 769 /* Check the name and description sizes. */ 770 if (np->n_namesz != ELF_NOTE_NETBSD_NAMESZ || 771 np->n_descsz != ELF_NOTE_NETBSD_DESCSZ) 772 goto out3; 773 774 /* Is the name "NetBSD\0\0"? */ 775 if (memcmp((np + 1), ELF_NOTE_NETBSD_NAME, 776 ELF_NOTE_NETBSD_NAMESZ)) 777 goto out3; 778 779 /* XXX: We could check for the specific emulation here */ 780 /* All checks succeeded. */ 781 error = 0; 782 goto out2; 783 } 784 785out3: 786 error = ENOEXEC; 787out2: 788 if (np) 789 free(np, M_TEMP); 790out1: 791 free(hph, M_TEMP); 792 return error; 793} 794 795static int 796ELFNAME2(netbsd,probe)(p, epp, eh, itp, pos) 797 struct proc *p; 798 struct exec_package *epp; 799 Elf_Ehdr *eh; 800 char *itp; 801 Elf_Addr *pos; 802{ 803 int error; 804 805 if ((error = ELFNAME2(netbsd,signature)(p, epp, eh)) != 0) 806 return error; 807 epp->ep_emul = &ELFNAMEEND(emul_netbsd); 808 *pos = ELFDEFNNAME(NO_ADDR); 809 return 0; 810} 811