exec_elf32.c revision 1.121
1/* $NetBSD: exec_elf32.c,v 1.121 2007/03/05 04:59:19 dogcow Exp $ */ 2 3/*- 4 * Copyright (c) 1994, 2000, 2005 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#include <sys/cdefs.h> 67__KERNEL_RCSID(1, "$NetBSD: exec_elf32.c,v 1.121 2007/03/05 04:59:19 dogcow Exp $"); 68 69/* If not included by exec_elf64.c, ELFSIZE won't be defined. */ 70#ifndef ELFSIZE 71#define ELFSIZE 32 72#endif 73 74#ifdef _KERNEL_OPT 75#include "opt_pax.h" 76#endif /* _KERNEL_OPT */ 77 78#include <sys/param.h> 79#include <sys/proc.h> 80#include <sys/malloc.h> 81#include <sys/namei.h> 82#include <sys/vnode.h> 83#include <sys/exec.h> 84#include <sys/exec_elf.h> 85#include <sys/syscall.h> 86#include <sys/signalvar.h> 87#include <sys/mount.h> 88#include <sys/stat.h> 89#include <sys/kauth.h> 90 91#include <machine/cpu.h> 92#include <machine/reg.h> 93 94#if defined(PAX_MPROTECT) || defined(PAX_SEGVGUARD) 95#include <sys/pax.h> 96#endif /* PAX_MPROTECT || PAX_SEGVGUARD */ 97 98extern const struct emul emul_netbsd; 99 100#define elf_check_header ELFNAME(check_header) 101#define elf_copyargs ELFNAME(copyargs) 102#define elf_load_file ELFNAME(load_file) 103#define elf_load_psection ELFNAME(load_psection) 104#define exec_elf_makecmds ELFNAME2(exec,makecmds) 105#define netbsd_elf_signature ELFNAME2(netbsd,signature) 106#define netbsd_elf_probe ELFNAME2(netbsd,probe) 107 108int elf_load_file(struct lwp *, struct exec_package *, char *, 109 struct exec_vmcmd_set *, u_long *, struct elf_args *, Elf_Addr *); 110void elf_load_psection(struct exec_vmcmd_set *, struct vnode *, 111 const Elf_Phdr *, Elf_Addr *, u_long *, int *, int); 112 113int netbsd_elf_signature(struct lwp *, struct exec_package *, Elf_Ehdr *); 114int netbsd_elf_probe(struct lwp *, struct exec_package *, void *, char *, 115 vaddr_t *); 116 117/* round up and down to page boundaries. */ 118#define ELF_ROUND(a, b) (((a) + (b) - 1) & ~((b) - 1)) 119#define ELF_TRUNC(a, b) ((a) & ~((b) - 1)) 120 121#define MAXPHNUM 50 122 123/* 124 * Copy arguments onto the stack in the normal way, but add some 125 * extra information in case of dynamic binding. 126 */ 127int 128elf_copyargs(struct lwp *l, struct exec_package *pack, 129 struct ps_strings *arginfo, char **stackp, void *argp) 130{ 131 size_t len; 132 AuxInfo ai[ELF_AUX_ENTRIES], *a; 133 struct elf_args *ap; 134 int error; 135 136 if ((error = copyargs(l, pack, arginfo, stackp, argp)) != 0) 137 return error; 138 139 a = ai; 140 141 /* 142 * Push extra arguments on the stack needed by dynamically 143 * linked binaries 144 */ 145 if ((ap = (struct elf_args *)pack->ep_emul_arg)) { 146 struct vattr *vap = pack->ep_vap; 147 148 a->a_type = AT_PHDR; 149 a->a_v = ap->arg_phaddr; 150 a++; 151 152 a->a_type = AT_PHENT; 153 a->a_v = ap->arg_phentsize; 154 a++; 155 156 a->a_type = AT_PHNUM; 157 a->a_v = ap->arg_phnum; 158 a++; 159 160 a->a_type = AT_PAGESZ; 161 a->a_v = PAGE_SIZE; 162 a++; 163 164 a->a_type = AT_BASE; 165 a->a_v = ap->arg_interp; 166 a++; 167 168 a->a_type = AT_FLAGS; 169 a->a_v = 0; 170 a++; 171 172 a->a_type = AT_ENTRY; 173 a->a_v = ap->arg_entry; 174 a++; 175 176 a->a_type = AT_EUID; 177 if (vap->va_mode & S_ISUID) 178 a->a_v = vap->va_uid; 179 else 180 a->a_v = kauth_cred_geteuid(l->l_cred); 181 a++; 182 183 a->a_type = AT_RUID; 184 a->a_v = kauth_cred_getuid(l->l_cred); 185 a++; 186 187 a->a_type = AT_EGID; 188 if (vap->va_mode & S_ISGID) 189 a->a_v = vap->va_gid; 190 else 191 a->a_v = kauth_cred_getegid(l->l_cred); 192 a++; 193 194 a->a_type = AT_RGID; 195 a->a_v = kauth_cred_getgid(l->l_cred); 196 a++; 197 198 free(ap, M_TEMP); 199 pack->ep_emul_arg = NULL; 200 } 201 202 a->a_type = AT_NULL; 203 a->a_v = 0; 204 a++; 205 206 len = (a - ai) * sizeof(AuxInfo); 207 if ((error = copyout(ai, *stackp, len)) != 0) 208 return error; 209 *stackp += len; 210 211 return 0; 212} 213 214/* 215 * elf_check_header(): 216 * 217 * Check header for validity; return 0 of ok ENOEXEC if error 218 */ 219int 220elf_check_header(Elf_Ehdr *eh, int type) 221{ 222 223 if (memcmp(eh->e_ident, ELFMAG, SELFMAG) != 0 || 224 eh->e_ident[EI_CLASS] != ELFCLASS) 225 return ENOEXEC; 226 227 switch (eh->e_machine) { 228 229 ELFDEFNNAME(MACHDEP_ID_CASES) 230 231 default: 232 return ENOEXEC; 233 } 234 235 if (ELF_EHDR_FLAGS_OK(eh) == 0) 236 return ENOEXEC; 237 238 if (eh->e_type != type) 239 return ENOEXEC; 240 241 if (eh->e_shnum > 32768 || eh->e_phnum > 128) 242 return ENOEXEC; 243 244 return 0; 245} 246 247/* 248 * elf_load_psection(): 249 * 250 * Load a psection at the appropriate address 251 */ 252void 253elf_load_psection(struct exec_vmcmd_set *vcset, struct vnode *vp, 254 const Elf_Phdr *ph, Elf_Addr *addr, u_long *size, int *prot, int flags) 255{ 256 u_long msize, psize, rm, rf; 257 long diff, offset; 258 259 /* 260 * If the user specified an address, then we load there. 261 */ 262 if (*addr == ELFDEFNNAME(NO_ADDR)) 263 *addr = ph->p_vaddr; 264 265 if (ph->p_align > 1) { 266 /* 267 * Make sure we are virtually aligned as we are supposed to be. 268 */ 269 diff = ph->p_vaddr - ELF_TRUNC(ph->p_vaddr, ph->p_align); 270 KASSERT(*addr - diff == ELF_TRUNC(*addr, ph->p_align)); 271 /* 272 * But make sure to not map any pages before the start of the 273 * psection by limiting the difference to within a page. 274 */ 275 diff &= PAGE_MASK; 276 } else 277 diff = 0; 278 279 *prot |= (ph->p_flags & PF_R) ? VM_PROT_READ : 0; 280 *prot |= (ph->p_flags & PF_W) ? VM_PROT_WRITE : 0; 281 *prot |= (ph->p_flags & PF_X) ? VM_PROT_EXECUTE : 0; 282 283 /* 284 * Adjust everything so it all starts on a page boundary. 285 */ 286 *addr -= diff; 287 offset = ph->p_offset - diff; 288 *size = ph->p_filesz + diff; 289 msize = ph->p_memsz + diff; 290 291 if (ph->p_align >= PAGE_SIZE) { 292 if ((ph->p_flags & PF_W) != 0) { 293 /* 294 * Because the pagedvn pager can't handle zero fill 295 * of the last data page if it's not page aligned we 296 * map the last page readvn. 297 */ 298 psize = trunc_page(*size); 299 } else { 300 psize = round_page(*size); 301 } 302 } else { 303 psize = *size; 304 } 305 306 if (psize > 0) { 307 NEW_VMCMD2(vcset, ph->p_align < PAGE_SIZE ? 308 vmcmd_map_readvn : vmcmd_map_pagedvn, psize, *addr, vp, 309 offset, *prot, flags); 310 flags &= VMCMD_RELATIVE; 311 } 312 if (psize < *size) { 313 NEW_VMCMD2(vcset, vmcmd_map_readvn, *size - psize, 314 *addr + psize, vp, offset + psize, *prot, flags); 315 } 316 317 /* 318 * Check if we need to extend the size of the segment (does 319 * bss extend page the next page boundary)? 320 */ 321 rm = round_page(*addr + msize); 322 rf = round_page(*addr + *size); 323 324 if (rm != rf) { 325 NEW_VMCMD2(vcset, vmcmd_map_zero, rm - rf, rf, NULLVP, 326 0, *prot, flags & VMCMD_RELATIVE); 327 *size = msize; 328 } 329} 330 331/* 332 * elf_load_file(): 333 * 334 * Load a file (interpreter/library) pointed to by path 335 * [stolen from coff_load_shlib()]. Made slightly generic 336 * so it might be used externally. 337 */ 338int 339elf_load_file(struct lwp *l, struct exec_package *epp, char *path, 340 struct exec_vmcmd_set *vcset, u_long *entryoff, struct elf_args *ap, 341 Elf_Addr *last) 342{ 343 int error, i; 344 struct nameidata nd; 345 struct vnode *vp; 346 struct vattr attr; 347 Elf_Ehdr eh; 348 Elf_Phdr *ph = NULL; 349 const Elf_Phdr *ph0; 350 const Elf_Phdr *base_ph; 351 const Elf_Phdr *last_ph; 352 u_long phsize; 353 Elf_Addr addr = *last; 354 struct proc *p; 355 356 p = l->l_proc; 357 358 /* 359 * 1. open file 360 * 2. read filehdr 361 * 3. map text, data, and bss out of it using VM_* 362 */ 363 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, l); 364 if ((error = namei(&nd)) != 0) 365 return error; 366 vp = nd.ni_vp; 367 368 /* 369 * Similarly, if it's not marked as executable, or it's not a regular 370 * file, we don't allow it to be used. 371 */ 372 if (vp->v_type != VREG) { 373 error = EACCES; 374 goto badunlock; 375 } 376 if ((error = VOP_ACCESS(vp, VEXEC, l->l_cred, l)) != 0) 377 goto badunlock; 378 379 /* get attributes */ 380 if ((error = VOP_GETATTR(vp, &attr, l->l_cred, l)) != 0) 381 goto badunlock; 382 383 /* 384 * Check mount point. Though we're not trying to exec this binary, 385 * we will be executing code from it, so if the mount point 386 * disallows execution or set-id-ness, we punt or kill the set-id. 387 */ 388 if (vp->v_mount->mnt_flag & MNT_NOEXEC) { 389 error = EACCES; 390 goto badunlock; 391 } 392 if (vp->v_mount->mnt_flag & MNT_NOSUID) 393 epp->ep_vap->va_mode &= ~(S_ISUID | S_ISGID); 394 395#ifdef notyet /* XXX cgd 960926 */ 396 XXX cgd 960926: (maybe) VOP_OPEN it (and VOP_CLOSE in copyargs?) 397#endif 398 399 error = vn_marktext(vp); 400 if (error) 401 goto badunlock; 402 403 VOP_UNLOCK(vp, 0); 404 405 if ((error = exec_read_from(l, vp, 0, &eh, sizeof(eh))) != 0) 406 goto bad; 407 408 if ((error = elf_check_header(&eh, ET_DYN)) != 0) 409 goto bad; 410 411 if (eh.e_phnum > MAXPHNUM) 412 goto bad; 413 414 phsize = eh.e_phnum * sizeof(Elf_Phdr); 415 ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); 416 417 if ((error = exec_read_from(l, vp, eh.e_phoff, ph, phsize)) != 0) 418 goto bad; 419 420#ifdef ELF_INTERP_NON_RELOCATABLE 421 /* 422 * Evil hack: Only MIPS should be non-relocatable, and the 423 * psections should have a high address (typically 0x5ffe0000). 424 * If it's now relocatable, it should be linked at 0 and the 425 * psections should have zeros in the upper part of the address. 426 * Otherwise, force the load at the linked address. 427 */ 428 if (*last == ELF_LINK_ADDR && (ph->p_vaddr & 0xffff0000) == 0) 429 *last = ELFDEFNNAME(NO_ADDR); 430#endif 431 432 /* 433 * If no position to load the interpreter was set by a probe 434 * function, pick the same address that a non-fixed mmap(0, ..) 435 * would (i.e. something safely out of the way). 436 */ 437 if (*last == ELFDEFNNAME(NO_ADDR)) { 438 u_long limit = 0; 439 /* 440 * Find the start and ending addresses of the psections to 441 * be loaded. This will give us the size. 442 */ 443 for (i = 0, ph0 = ph, base_ph = NULL; i < eh.e_phnum; 444 i++, ph0++) { 445 if (ph0->p_type == PT_LOAD) { 446 u_long psize = ph0->p_vaddr + ph0->p_memsz; 447 if (base_ph == NULL) 448 base_ph = ph0; 449 if (psize > limit) 450 limit = psize; 451 } 452 } 453 454 if (base_ph == NULL) { 455 error = ENOEXEC; 456 goto bad; 457 } 458 459 /* 460 * Now compute the size and load address. 461 */ 462 addr = (*epp->ep_esch->es_emul->e_vm_default_addr)(p, 463 epp->ep_daddr, 464 round_page(limit) - trunc_page(base_ph->p_vaddr)); 465 } else 466 addr = *last; /* may be ELF_LINK_ADDR */ 467 468 /* 469 * Load all the necessary sections 470 */ 471 for (i = 0, ph0 = ph, base_ph = NULL, last_ph = NULL; 472 i < eh.e_phnum; i++, ph0++) { 473 switch (ph0->p_type) { 474 case PT_LOAD: { 475 u_long size; 476 int prot = 0; 477 int flags; 478 479 if (base_ph == NULL) { 480 /* 481 * First encountered psection is always the 482 * base psection. Make sure it's aligned 483 * properly (align down for topdown and align 484 * upwards for not topdown). 485 */ 486 base_ph = ph0; 487 flags = VMCMD_BASE; 488 if (addr == ELF_LINK_ADDR) 489 addr = ph0->p_vaddr; 490 if (p->p_vmspace->vm_map.flags & VM_MAP_TOPDOWN) 491 addr = ELF_TRUNC(addr, ph0->p_align); 492 else 493 addr = ELF_ROUND(addr, ph0->p_align); 494 } else { 495 u_long limit = round_page(last_ph->p_vaddr 496 + last_ph->p_memsz); 497 u_long base = trunc_page(ph0->p_vaddr); 498 499 /* 500 * If there is a gap in between the psections, 501 * map it as inaccessible so nothing else 502 * mmap'ed will be placed there. 503 */ 504 if (limit != base) { 505 NEW_VMCMD2(vcset, vmcmd_map_zero, 506 base - limit, 507 limit - base_ph->p_vaddr, NULLVP, 508 0, VM_PROT_NONE, VMCMD_RELATIVE); 509 } 510 511 addr = ph0->p_vaddr - base_ph->p_vaddr; 512 flags = VMCMD_RELATIVE; 513 } 514 last_ph = ph0; 515 elf_load_psection(vcset, vp, &ph[i], &addr, 516 &size, &prot, flags); 517 /* 518 * If entry is within this psection then this 519 * must contain the .text section. *entryoff is 520 * relative to the base psection. 521 */ 522 if (eh.e_entry >= ph0->p_vaddr && 523 eh.e_entry < (ph0->p_vaddr + size)) { 524 *entryoff = eh.e_entry - base_ph->p_vaddr; 525 } 526 addr += size; 527 break; 528 } 529 530 case PT_DYNAMIC: 531 case PT_PHDR: 532 break; 533 534 case PT_NOTE: 535 break; 536 537 default: 538 break; 539 } 540 } 541 542 free(ph, M_TEMP); 543 /* 544 * This value is ignored if TOPDOWN. 545 */ 546 *last = addr; 547 vrele(vp); 548 return 0; 549 550badunlock: 551 VOP_UNLOCK(vp, 0); 552 553bad: 554 if (ph != NULL) 555 free(ph, M_TEMP); 556#ifdef notyet /* XXX cgd 960926 */ 557 (maybe) VOP_CLOSE it 558#endif 559 vrele(vp); 560 return error; 561} 562 563/* 564 * exec_elf_makecmds(): Prepare an Elf binary's exec package 565 * 566 * First, set of the various offsets/lengths in the exec package. 567 * 568 * Then, mark the text image busy (so it can be demand paged) or error 569 * out if this is not possible. Finally, set up vmcmds for the 570 * text, data, bss, and stack segments. 571 */ 572int 573exec_elf_makecmds(struct lwp *l, struct exec_package *epp) 574{ 575 Elf_Ehdr *eh = epp->ep_hdr; 576 Elf_Phdr *ph, *pp; 577 Elf_Addr phdr = 0, pos = 0; 578 int error, i, nload; 579 char *interp = NULL; 580 u_long phsize; 581 struct proc *p; 582 583 if (epp->ep_hdrvalid < sizeof(Elf_Ehdr)) 584 return ENOEXEC; 585 586 /* 587 * XXX allow for executing shared objects. It seems silly 588 * but other ELF-based systems allow it as well. 589 */ 590 if (elf_check_header(eh, ET_EXEC) != 0 && 591 elf_check_header(eh, ET_DYN) != 0) 592 return ENOEXEC; 593 594 if (eh->e_phnum > MAXPHNUM) 595 return ENOEXEC; 596 597 error = vn_marktext(epp->ep_vp); 598 if (error) 599 return error; 600 601 /* 602 * Allocate space to hold all the program headers, and read them 603 * from the file 604 */ 605 p = l->l_proc; 606 phsize = eh->e_phnum * sizeof(Elf_Phdr); 607 ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); 608 609 if ((error = exec_read_from(l, epp->ep_vp, eh->e_phoff, ph, phsize)) != 610 0) 611 goto bad; 612 613 epp->ep_taddr = epp->ep_tsize = ELFDEFNNAME(NO_ADDR); 614 epp->ep_daddr = epp->ep_dsize = ELFDEFNNAME(NO_ADDR); 615 616 for (i = 0; i < eh->e_phnum; i++) { 617 pp = &ph[i]; 618 if (pp->p_type == PT_INTERP) { 619 if (pp->p_filesz >= MAXPATHLEN) 620 goto bad; 621 interp = PNBUF_GET(); 622 interp[0] = '\0'; 623 if ((error = exec_read_from(l, epp->ep_vp, 624 pp->p_offset, interp, pp->p_filesz)) != 0) 625 goto bad; 626 break; 627 } 628 } 629 630 /* 631 * On the same architecture, we may be emulating different systems. 632 * See which one will accept this executable. 633 * 634 * Probe functions would normally see if the interpreter (if any) 635 * exists. Emulation packages may possibly replace the interpreter in 636 * interp[] with a changed path (/emul/xxx/<path>). 637 */ 638 pos = ELFDEFNNAME(NO_ADDR); 639 if (epp->ep_esch->u.elf_probe_func) { 640 vaddr_t startp = (vaddr_t)pos; 641 642 error = (*epp->ep_esch->u.elf_probe_func)(l, epp, eh, interp, 643 &startp); 644 if (error) 645 goto bad; 646 pos = (Elf_Addr)startp; 647 } 648 649 /* 650 * Load all the necessary sections 651 */ 652 for (i = nload = 0; i < eh->e_phnum; i++) { 653 Elf_Addr addr = ELFDEFNNAME(NO_ADDR); 654 u_long size = 0; 655 int prot = 0; 656 657 pp = &ph[i]; 658 659 switch (ph[i].p_type) { 660 case PT_LOAD: 661 /* 662 * XXX 663 * Can handle only 2 sections: text and data 664 */ 665 if (nload++ == 2) 666 goto bad; 667 elf_load_psection(&epp->ep_vmcmds, epp->ep_vp, 668 &ph[i], &addr, &size, &prot, VMCMD_FIXED); 669 670 /* 671 * Decide whether it's text or data by looking 672 * at the entry point. 673 */ 674 if (eh->e_entry >= addr && 675 eh->e_entry < (addr + size)) { 676 epp->ep_taddr = addr; 677 epp->ep_tsize = size; 678 if (epp->ep_daddr == ELFDEFNNAME(NO_ADDR)) { 679 epp->ep_daddr = addr; 680 epp->ep_dsize = size; 681 } 682 } else { 683 epp->ep_daddr = addr; 684 epp->ep_dsize = size; 685 } 686 break; 687 688 case PT_SHLIB: 689 /* SCO has these sections. */ 690 case PT_INTERP: 691 /* Already did this one. */ 692 case PT_DYNAMIC: 693 break; 694 case PT_NOTE: 695#if defined(PAX_MPROTECT) || defined(PAX_SEGVGUARD) 696 pax_adjust(l, ph[i].p_flags); 697#endif /* PAX_MPROTECT || PAX_SEGVGUARD */ 698 break; 699 700 case PT_PHDR: 701 /* Note address of program headers (in text segment) */ 702 phdr = pp->p_vaddr; 703 break; 704 705 default: 706 /* 707 * Not fatal; we don't need to understand everything. 708 */ 709 break; 710 } 711 } 712 713 /* 714 * Check if we found a dynamically linked binary and arrange to load 715 * its interpreter 716 */ 717 if (interp) { 718 struct elf_args *ap; 719 int j = epp->ep_vmcmds.evs_used; 720 u_long interp_offset; 721 722 MALLOC(ap, struct elf_args *, sizeof(struct elf_args), 723 M_TEMP, M_WAITOK); 724 if ((error = elf_load_file(l, epp, interp, 725 &epp->ep_vmcmds, &interp_offset, ap, &pos)) != 0) { 726 FREE(ap, M_TEMP); 727 goto bad; 728 } 729 ap->arg_interp = epp->ep_vmcmds.evs_cmds[j].ev_addr; 730 epp->ep_entry = ap->arg_interp + interp_offset; 731 ap->arg_phaddr = phdr; 732 733 ap->arg_phentsize = eh->e_phentsize; 734 ap->arg_phnum = eh->e_phnum; 735 ap->arg_entry = eh->e_entry; 736 737 epp->ep_emul_arg = ap; 738 739 PNBUF_PUT(interp); 740 } else 741 epp->ep_entry = eh->e_entry; 742 743#ifdef ELF_MAP_PAGE_ZERO 744 /* Dell SVR4 maps page zero, yeuch! */ 745 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, PAGE_SIZE, 0, 746 epp->ep_vp, 0, VM_PROT_READ); 747#endif 748 free(ph, M_TEMP); 749 return (*epp->ep_esch->es_setup_stack)(l, epp); 750 751bad: 752 if (interp) 753 PNBUF_PUT(interp); 754 free(ph, M_TEMP); 755 kill_vmcmds(&epp->ep_vmcmds); 756 return ENOEXEC; 757} 758 759int 760netbsd_elf_signature(struct lwp *l, struct exec_package *epp, 761 Elf_Ehdr *eh) 762{ 763 size_t i; 764 Elf_Phdr *ph; 765 size_t phsize; 766 int error; 767 768 if (eh->e_phnum > MAXPHNUM) 769 return ENOEXEC; 770 771 phsize = eh->e_phnum * sizeof(Elf_Phdr); 772 ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); 773 error = exec_read_from(l, epp->ep_vp, eh->e_phoff, ph, phsize); 774 if (error) 775 goto out; 776 777 for (i = 0; i < eh->e_phnum; i++) { 778 Elf_Phdr *ephp = &ph[i]; 779 Elf_Nhdr *np; 780 781 if (ephp->p_type != PT_NOTE || 782 ephp->p_filesz > 1024 || 783 ephp->p_filesz < sizeof(Elf_Nhdr) + ELF_NOTE_NETBSD_NAMESZ) 784 continue; 785 786 np = (Elf_Nhdr *)malloc(ephp->p_filesz, M_TEMP, M_WAITOK); 787 error = exec_read_from(l, epp->ep_vp, ephp->p_offset, np, 788 ephp->p_filesz); 789 if (error) 790 goto next; 791 792 if (np->n_type != ELF_NOTE_TYPE_NETBSD_TAG || 793 np->n_namesz != ELF_NOTE_NETBSD_NAMESZ || 794 np->n_descsz != ELF_NOTE_NETBSD_DESCSZ || 795 memcmp((char *)np + 1, ELF_NOTE_NETBSD_NAME, 796 ELF_NOTE_NETBSD_NAMESZ)) 797 goto next; 798 799 error = 0; 800 free(np, M_TEMP); 801 goto out; 802 803 next: 804 free(np, M_TEMP); 805 continue; 806 } 807 808 error = ENOEXEC; 809out: 810 free(ph, M_TEMP); 811 return error; 812} 813 814int 815netbsd_elf_probe(struct lwp *l, struct exec_package *epp, void *eh, char *itp, 816 vaddr_t *pos) 817{ 818 int error; 819 820 if ((error = netbsd_elf_signature(l, epp, eh)) != 0) 821 return error; 822#ifdef ELF_INTERP_NON_RELOCATABLE 823 *pos = ELF_LINK_ADDR; 824#endif 825 return 0; 826} 827