exec_elf32.c revision 1.58
1/* $NetBSD: exec_elf32.c,v 1.58 2000/11/21 00:37:56 jdolecek 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_ibcs2.h" /* XXX quirk for PT_SHLIB section */ 72 73#include <sys/param.h> 74#include <sys/proc.h> 75#include <sys/malloc.h> 76#include <sys/namei.h> 77#include <sys/vnode.h> 78#include <sys/exec.h> 79#include <sys/exec_elf.h> 80#include <sys/syscall.h> 81#include <sys/signalvar.h> 82#include <sys/mount.h> 83#include <sys/stat.h> 84 85#include <machine/cpu.h> 86#include <machine/reg.h> 87 88extern const struct emul emul_netbsd; 89 90int ELFNAME(check_header)(Elf_Ehdr *, int); 91int ELFNAME(load_file)(struct proc *, struct exec_package *, char *, 92 struct exec_vmcmd_set *, u_long *, struct elf_args *, Elf_Addr *); 93void ELFNAME(load_psection)(struct exec_vmcmd_set *, struct vnode *, 94 const Elf_Phdr *, Elf_Addr *, u_long *, int *, int); 95 96static int ELFNAME2(netbsd,signature)(struct proc *, struct exec_package *, 97 Elf_Ehdr *); 98int ELFNAME2(netbsd,probe)(struct proc *, struct exec_package *, 99 void *, char *, vaddr_t *); 100 101/* round up and down to page boundaries. */ 102#define ELF_ROUND(a, b) (((a) + (b) - 1) & ~((b) - 1)) 103#define ELF_TRUNC(a, b) ((a) & ~((b) - 1)) 104 105/* 106 * Copy arguments onto the stack in the normal way, but add some 107 * extra information in case of dynamic binding. 108 */ 109void * 110ELFNAME(copyargs)(struct exec_package *pack, struct ps_strings *arginfo, 111 void *stack, void *argp) 112{ 113 size_t len; 114 AuxInfo ai[ELF_AUX_ENTRIES], *a; 115 struct elf_args *ap; 116 117 stack = copyargs(pack, arginfo, stack, argp); 118 if (!stack) 119 return NULL; 120 121 a = ai; 122 123 /* 124 * Push extra arguments on the stack needed by dynamically 125 * linked binaries 126 */ 127 if ((ap = (struct elf_args *)pack->ep_emul_arg)) { 128 129 a->a_type = AT_PHDR; 130 a->a_v = ap->arg_phaddr; 131 a++; 132 133 a->a_type = AT_PHENT; 134 a->a_v = ap->arg_phentsize; 135 a++; 136 137 a->a_type = AT_PHNUM; 138 a->a_v = ap->arg_phnum; 139 a++; 140 141 a->a_type = AT_PAGESZ; 142 a->a_v = PAGE_SIZE; 143 a++; 144 145 a->a_type = AT_BASE; 146 a->a_v = ap->arg_interp; 147 a++; 148 149 a->a_type = AT_FLAGS; 150 a->a_v = 0; 151 a++; 152 153 a->a_type = AT_ENTRY; 154 a->a_v = ap->arg_entry; 155 a++; 156 157 free((char *)ap, M_TEMP); 158 pack->ep_emul_arg = NULL; 159 } 160 161 a->a_type = AT_NULL; 162 a->a_v = 0; 163 a++; 164 165 len = (a - ai) * sizeof(AuxInfo); 166 if (copyout(ai, stack, len)) 167 return NULL; 168 stack = (caddr_t)stack + len; 169 170 return stack; 171} 172 173/* 174 * elf_check_header(): 175 * 176 * Check header for validity; return 0 of ok ENOEXEC if error 177 */ 178int 179ELFNAME(check_header)(Elf_Ehdr *eh, int type) 180{ 181 182 if (memcmp(eh->e_ident, ELFMAG, SELFMAG) != 0 || 183 eh->e_ident[EI_CLASS] != ELFCLASS) 184 return ENOEXEC; 185 186 switch (eh->e_machine) { 187 188 ELFDEFNNAME(MACHDEP_ID_CASES) 189 190 default: 191 return ENOEXEC; 192 } 193 194 if (eh->e_type != type) 195 return ENOEXEC; 196 197 return 0; 198} 199 200/* 201 * elf_load_psection(): 202 * 203 * Load a psection at the appropriate address 204 */ 205void 206ELFNAME(load_psection)(struct exec_vmcmd_set *vcset, struct vnode *vp, 207 const Elf_Phdr *ph, Elf_Addr *addr, u_long *size, int *prot, int flags) 208{ 209 u_long uaddr, msize, psize, rm, rf; 210 long diff, offset; 211 212 /* 213 * If the user specified an address, then we load there. 214 */ 215 if (*addr != ELFDEFNNAME(NO_ADDR)) { 216 if (ph->p_align > 1) { 217 *addr = ELF_TRUNC(*addr, ph->p_align); 218 uaddr = ELF_TRUNC(ph->p_vaddr, ph->p_align); 219 } else 220 uaddr = ph->p_vaddr; 221 diff = ph->p_vaddr - uaddr; 222 } else { 223 *addr = uaddr = ph->p_vaddr; 224 if (ph->p_align > 1) 225 *addr = ELF_TRUNC(uaddr, ph->p_align); 226 diff = uaddr - *addr; 227 } 228 229 *prot |= (ph->p_flags & PF_R) ? VM_PROT_READ : 0; 230 *prot |= (ph->p_flags & PF_W) ? VM_PROT_WRITE : 0; 231 *prot |= (ph->p_flags & PF_X) ? VM_PROT_EXECUTE : 0; 232 233 offset = ph->p_offset - diff; 234 *size = ph->p_filesz + diff; 235 msize = ph->p_memsz + diff; 236 psize = round_page(*size); 237 238 if ((ph->p_flags & PF_W) != 0) { 239 /* 240 * Because the pagedvn pager can't handle zero fill of the last 241 * data page if it's not page aligned we map the last page 242 * readvn. 243 */ 244 psize = trunc_page(*size); 245 } 246 if (psize > 0) { 247 NEW_VMCMD2(vcset, vmcmd_map_pagedvn, psize, *addr, vp, 248 offset, *prot, flags); 249 } 250 if (psize < *size) { 251 NEW_VMCMD2(vcset, vmcmd_map_readvn, *size - psize, 252 *addr + psize, vp, offset + psize, *prot, 253 psize > 0 ? flags & VMCMD_RELATIVE : flags); 254 } 255 256 /* 257 * Check if we need to extend the size of the segment 258 */ 259 rm = round_page(*addr + msize); 260 rf = round_page(*addr + *size); 261 262 if (rm != rf) { 263 NEW_VMCMD2(vcset, vmcmd_map_zero, rm - rf, rf, NULLVP, 264 0, *prot, flags & VMCMD_RELATIVE); 265 *size = msize; 266 } 267} 268 269/* 270 * elf_read_from(): 271 * 272 * Read from vnode into buffer at offset. 273 */ 274int 275ELFNAME(read_from)(struct proc *p, struct vnode *vp, u_long off, 276 caddr_t buf, int size) 277{ 278 int error; 279 size_t resid; 280 281 if ((error = vn_rdwr(UIO_READ, vp, buf, size, off, UIO_SYSSPACE, 282 0, p->p_ucred, &resid, p)) != 0) 283 return error; 284 /* 285 * See if we got all of it 286 */ 287 if (resid != 0) 288 return ENOEXEC; 289 return 0; 290} 291 292/* 293 * elf_load_file(): 294 * 295 * Load a file (interpreter/library) pointed to by path 296 * [stolen from coff_load_shlib()]. Made slightly generic 297 * so it might be used externally. 298 */ 299int 300ELFNAME(load_file)(struct proc *p, struct exec_package *epp, char *path, 301 struct exec_vmcmd_set *vcset, u_long *entry, struct elf_args *ap, 302 Elf_Addr *last) 303{ 304 int error, i; 305 struct nameidata nd; 306 struct vnode *vp; 307 struct vattr attr; 308 Elf_Ehdr eh; 309 Elf_Phdr *ph = NULL; 310 Elf_Phdr *base_ph = NULL; 311 u_long phsize; 312 char *bp = NULL; 313 Elf_Addr addr = *last; 314 315 bp = path; 316 /* 317 * 1. open file 318 * 2. read filehdr 319 * 3. map text, data, and bss out of it using VM_* 320 */ 321 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, p); 322 if ((error = namei(&nd)) != 0) 323 return error; 324 vp = nd.ni_vp; 325 326 /* 327 * Similarly, if it's not marked as executable, or it's not a regular 328 * file, we don't allow it to be used. 329 */ 330 if (vp->v_type != VREG) { 331 error = EACCES; 332 goto badunlock; 333 } 334 if ((error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p)) != 0) 335 goto badunlock; 336 337 /* get attributes */ 338 if ((error = VOP_GETATTR(vp, &attr, p->p_ucred, p)) != 0) 339 goto badunlock; 340 341 /* 342 * Check mount point. Though we're not trying to exec this binary, 343 * we will be executing code from it, so if the mount point 344 * disallows execution or set-id-ness, we punt or kill the set-id. 345 */ 346 if (vp->v_mount->mnt_flag & MNT_NOEXEC) { 347 error = EACCES; 348 goto badunlock; 349 } 350 if (vp->v_mount->mnt_flag & MNT_NOSUID) 351 epp->ep_vap->va_mode &= ~(S_ISUID | S_ISGID); 352 353#ifdef notyet /* XXX cgd 960926 */ 354 XXX cgd 960926: (maybe) VOP_OPEN it (and VOP_CLOSE in copyargs?) 355#endif 356 VOP_UNLOCK(vp, 0); 357 358 if ((error = ELFNAME(read_from)(p, vp, 0, (caddr_t) &eh, 359 sizeof(eh))) != 0) 360 goto bad; 361 362 if ((error = ELFNAME(check_header)(&eh, ET_DYN)) != 0) 363 goto bad; 364 365 phsize = eh.e_phnum * sizeof(Elf_Phdr); 366 ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); 367 368 if ((error = ELFNAME(read_from)(p, vp, eh.e_phoff, 369 (caddr_t) ph, phsize)) != 0) 370 goto bad; 371 372 /* 373 * Load all the necessary sections 374 */ 375 for (i = 0; i < eh.e_phnum; i++) { 376 u_long size = 0; 377 int prot = 0; 378 int flags; 379 380 switch (ph[i].p_type) { 381 case PT_LOAD: 382 if (base_ph == NULL) { 383 addr = *last; 384 flags = VMCMD_BASE; 385 } else { 386 addr = ph[i].p_vaddr - base_ph->p_vaddr; 387 flags = VMCMD_RELATIVE; 388 } 389 ELFNAME(load_psection)(vcset, vp, &ph[i], &addr, 390 &size, &prot, flags); 391 /* If entry is within this section it must be text */ 392 if (eh.e_entry >= ph[i].p_vaddr && 393 eh.e_entry < (ph[i].p_vaddr + size)) { 394 /* XXX */ 395 *entry = addr + eh.e_entry; 396#ifdef mips 397 *entry -= ph[i].p_vaddr; 398#endif 399 ap->arg_interp = addr; 400 } 401 if (base_ph == NULL) 402 base_ph = &ph[i]; 403 addr += size; 404 break; 405 406 case PT_DYNAMIC: 407 case PT_PHDR: 408 case PT_NOTE: 409 break; 410 411 default: 412 break; 413 } 414 } 415 416 free((char *)ph, M_TEMP); 417 *last = addr; 418 vrele(vp); 419 return 0; 420 421badunlock: 422 VOP_UNLOCK(vp, 0); 423 424bad: 425 if (ph != NULL) 426 free((char *)ph, M_TEMP); 427#ifdef notyet /* XXX cgd 960926 */ 428 (maybe) VOP_CLOSE it 429#endif 430 vrele(vp); 431 return error; 432} 433 434/* 435 * exec_elf_makecmds(): Prepare an Elf binary's exec package 436 * 437 * First, set of the various offsets/lengths in the exec package. 438 * 439 * Then, mark the text image busy (so it can be demand paged) or error 440 * out if this is not possible. Finally, set up vmcmds for the 441 * text, data, bss, and stack segments. 442 */ 443int 444ELFNAME2(exec,makecmds)(struct proc *p, struct exec_package *epp) 445{ 446 Elf_Ehdr *eh = epp->ep_hdr; 447 Elf_Phdr *ph, *pp; 448 Elf_Addr phdr = 0, pos = 0; 449 int error, i, nload; 450 char *interp = NULL; 451 u_long phsize; 452 453 if (epp->ep_hdrvalid < sizeof(Elf_Ehdr)) 454 return ENOEXEC; 455 456 /* 457 * XXX allow for executing shared objects. It seems silly 458 * but other ELF-based systems allow it as well. 459 */ 460 if (ELFNAME(check_header)(eh, ET_EXEC) != 0 && 461 ELFNAME(check_header)(eh, ET_DYN) != 0) 462 return ENOEXEC; 463 464 /* 465 * check if vnode is in open for writing, because we want to 466 * demand-page out of it. if it is, don't do it, for various 467 * reasons 468 */ 469 if (epp->ep_vp->v_writecount != 0) { 470#ifdef DIAGNOSTIC 471 if (epp->ep_vp->v_flag & VTEXT) 472 panic("exec: a VTEXT vnode has writecount != 0\n"); 473#endif 474 return ETXTBSY; 475 } 476 /* 477 * Allocate space to hold all the program headers, and read them 478 * from the file 479 */ 480 phsize = eh->e_phnum * sizeof(Elf_Phdr); 481 ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); 482 483 if ((error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_phoff, 484 (caddr_t) ph, phsize)) != 0) 485 goto bad; 486 487 epp->ep_taddr = epp->ep_tsize = ELFDEFNNAME(NO_ADDR); 488 epp->ep_daddr = epp->ep_dsize = ELFDEFNNAME(NO_ADDR); 489 490 MALLOC(interp, char *, MAXPATHLEN, M_TEMP, M_WAITOK); 491 interp[0] = '\0'; 492 493 for (i = 0; i < eh->e_phnum; i++) { 494 pp = &ph[i]; 495 if (pp->p_type == PT_INTERP) { 496 if (pp->p_filesz >= MAXPATHLEN) 497 goto bad; 498 if ((error = ELFNAME(read_from)(p, epp->ep_vp, 499 pp->p_offset, (caddr_t) interp, 500 pp->p_filesz)) != 0) 501 goto bad; 502 break; 503 } 504 } 505 506 /* 507 * On the same architecture, we may be emulating different systems. 508 * See which one will accept this executable. This currently only 509 * applies to SVR4, and IBCS2 on the i386 and Linux on the i386 510 * and the Alpha. 511 * 512 * Probe functions would normally see if the interpreter (if any) 513 * exists. Emulation packages may possibly replace the interpreter in 514 * interp[] with a changed path (/emul/xxx/<path>). 515 */ 516 if (!epp->ep_esch->u.elf_probe_func) { 517 p->p_emul = epp->ep_esch->es_emul; 518 pos = ELFDEFNNAME(NO_ADDR); 519 } else { 520 error = (*epp->ep_esch->u.elf_probe_func)(p, epp, eh, interp, 521 (vaddr_t *)&pos); 522 if (error) 523 goto bad; 524 } 525 526 /* 527 * Load all the necessary sections 528 */ 529 for (i = nload = 0; i < eh->e_phnum; i++) { 530 Elf_Addr addr = ELFDEFNNAME(NO_ADDR); 531 u_long size = 0; 532 int prot = 0; 533 534 pp = &ph[i]; 535 536 switch (ph[i].p_type) { 537 case PT_LOAD: 538 /* 539 * XXX 540 * Can handle only 2 sections: text and data 541 */ 542 if (nload++ == 2) 543 goto bad; 544 ELFNAME(load_psection)(&epp->ep_vmcmds, epp->ep_vp, 545 &ph[i], &addr, &size, &prot, 0); 546 547 /* 548 * Decide whether it's text or data by looking 549 * at the entry point. 550 */ 551 if (eh->e_entry >= addr && 552 eh->e_entry < (addr + size)) { 553 epp->ep_taddr = addr; 554 epp->ep_tsize = size; 555 if (epp->ep_daddr == ELFDEFNNAME(NO_ADDR)) { 556 epp->ep_daddr = addr; 557 epp->ep_dsize = size; 558 } 559 } else { 560 epp->ep_daddr = addr; 561 epp->ep_dsize = size; 562 } 563 break; 564 565 case PT_SHLIB: 566#ifndef COMPAT_IBCS2 /* SCO has these sections */ 567 error = ENOEXEC; 568 goto bad; 569#endif 570 571 case PT_INTERP: 572 /* Already did this one */ 573 case PT_DYNAMIC: 574 case PT_NOTE: 575 break; 576 577 case PT_PHDR: 578 /* Note address of program headers (in text segment) */ 579 phdr = pp->p_vaddr; 580 break; 581 582 default: 583 /* 584 * Not fatal; we don't need to understand everything. 585 */ 586 break; 587 } 588 } 589 590 /* this breaks on, e.g., OpenBSD-compatible mips shared binaries. */ 591#ifndef ELF_INTERP_NON_RELOCATABLE 592 /* 593 * If no position to load the interpreter was set by a probe 594 * function, pick the same address that a non-fixed mmap(0, ..) 595 * would (i.e. something safely out of the way). 596 */ 597 if (pos == ELFDEFNNAME(NO_ADDR)) 598 pos = round_page(epp->ep_daddr + MAXDSIZ); 599#endif /* !ELF_INTERP_NON_RELOCATABLE */ 600 601 /* 602 * Check if we found a dynamically linked binary and arrange to load 603 * it's interpreter 604 */ 605 if (interp[0]) { 606 struct elf_args *ap; 607 608 MALLOC(ap, struct elf_args *, sizeof(struct elf_args), 609 M_TEMP, M_WAITOK); 610 if ((error = ELFNAME(load_file)(p, epp, interp, 611 &epp->ep_vmcmds, &epp->ep_entry, ap, &pos)) != 0) { 612 FREE((char *)ap, M_TEMP); 613 goto bad; 614 } 615 pos += phsize; 616 ap->arg_phaddr = phdr; 617 618 ap->arg_phentsize = eh->e_phentsize; 619 ap->arg_phnum = eh->e_phnum; 620 ap->arg_entry = eh->e_entry; 621 622 epp->ep_emul_arg = ap; 623 } else 624 epp->ep_entry = eh->e_entry; 625 626#ifdef ELF_MAP_PAGE_ZERO 627 /* Dell SVR4 maps page zero, yeuch! */ 628 NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, PAGE_SIZE, 0, 629 epp->ep_vp, 0, VM_PROT_READ); 630#endif 631 FREE(interp, M_TEMP); 632 free((char *)ph, M_TEMP); 633 vn_marktext(epp->ep_vp); 634 return exec_elf_setup_stack(p, epp); 635 636bad: 637 if (interp) 638 FREE(interp, M_TEMP); 639 free((char *)ph, M_TEMP); 640 kill_vmcmds(&epp->ep_vmcmds); 641 return ENOEXEC; 642} 643 644static int 645ELFNAME2(netbsd,signature)(struct proc *p, struct exec_package *epp, 646 Elf_Ehdr *eh) 647{ 648 Elf_Phdr *hph, *ph; 649 Elf_Nhdr *np = NULL; 650 size_t phsize; 651 int error; 652 653 phsize = eh->e_phnum * sizeof(Elf_Phdr); 654 hph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); 655 if ((error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_phoff, 656 (caddr_t)hph, phsize)) != 0) 657 goto out1; 658 659 for (ph = hph; ph < &hph[eh->e_phnum]; ph++) { 660 if (ph->p_type != PT_NOTE || 661 ph->p_filesz < sizeof(Elf_Nhdr) + ELF_NOTE_NETBSD_NAMESZ) 662 continue; 663 664 np = (Elf_Nhdr *)malloc(ph->p_filesz, M_TEMP, M_WAITOK); 665 if ((error = ELFNAME(read_from)(p, epp->ep_vp, ph->p_offset, 666 (caddr_t)np, ph->p_filesz)) != 0) 667 goto out2; 668 669 if (np->n_type != ELF_NOTE_TYPE_OSVERSION) { 670 free(np, M_TEMP); 671 np = NULL; 672 continue; 673 } 674 675 /* Check the name and description sizes. */ 676 if (np->n_namesz != ELF_NOTE_NETBSD_NAMESZ || 677 np->n_descsz != ELF_NOTE_NETBSD_DESCSZ) 678 goto out3; 679 680 /* Is the name "NetBSD\0\0"? */ 681 if (memcmp((np + 1), ELF_NOTE_NETBSD_NAME, 682 ELF_NOTE_NETBSD_NAMESZ)) 683 goto out3; 684 685 /* XXX: We could check for the specific emulation here */ 686 /* All checks succeeded. */ 687 error = 0; 688 goto out2; 689 } 690 691out3: 692 error = ENOEXEC; 693out2: 694 if (np) 695 free(np, M_TEMP); 696out1: 697 free(hph, M_TEMP); 698 return error; 699} 700 701int 702ELFNAME2(netbsd,probe)(struct proc *p, struct exec_package *epp, 703 void *eh, char *itp, vaddr_t *pos) 704{ 705 int error; 706 707 if ((error = ELFNAME2(netbsd,signature)(p, epp, eh)) != 0) 708 return error; 709 *pos = ELFDEFNNAME(NO_ADDR); 710 return 0; 711} 712