The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/exec_elf32.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: c0046ec8f4dd9c79c6b6b0e64590b0b3


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.