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.120.2.1 2007/07/09 10:30:57 liamjfoy 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.120.2.1 2007/07/09 10:30:57 liamjfoy 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 
   98 extern 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 
  108 int     elf_load_file(struct lwp *, struct exec_package *, char *,
  109             struct exec_vmcmd_set *, u_long *, struct elf_args *, Elf_Addr *);
  110 void    elf_load_psection(struct exec_vmcmd_set *, struct vnode *,
  111             const Elf_Phdr *, Elf_Addr *, u_long *, int *, int);
  112 
  113 int     netbsd_elf_signature(struct lwp *, struct exec_package *, Elf_Ehdr *);
  114 int     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  */
  127 int
  128 elf_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  */
  219 int
  220 elf_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  */
  252 void
  253 elf_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  */
  338 int
  339 elf_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 
  550 badunlock:
  551         VOP_UNLOCK(vp, 0);
  552 
  553 bad:
  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  */
  572 int
  573 exec_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                         break;
  696                 case PT_PHDR:
  697                         /* Note address of program headers (in text segment) */
  698                         phdr = pp->p_vaddr;
  699                         break;
  700 
  701                 default:
  702                         /*
  703                          * Not fatal; we don't need to understand everything.
  704                          */
  705                         break;
  706                 }
  707         }
  708 
  709 #if defined(PAX_MPROTECT) || defined(PAX_SEGVGUARD)
  710         if (epp->ep_pax_flags)
  711                 pax_adjust(l, epp->ep_pax_flags);
  712 #endif /* PAX_MPROTECT || PAX_SEGVGUARD */
  713 
  714         /*
  715          * Check if we found a dynamically linked binary and arrange to load
  716          * its interpreter
  717          */
  718         if (interp) {
  719                 struct elf_args *ap;
  720                 int j = epp->ep_vmcmds.evs_used;
  721                 u_long interp_offset;
  722 
  723                 MALLOC(ap, struct elf_args *, sizeof(struct elf_args),
  724                     M_TEMP, M_WAITOK);
  725                 if ((error = elf_load_file(l, epp, interp,
  726                     &epp->ep_vmcmds, &interp_offset, ap, &pos)) != 0) {
  727                         FREE(ap, M_TEMP);
  728                         goto bad;
  729                 }
  730                 ap->arg_interp = epp->ep_vmcmds.evs_cmds[j].ev_addr;
  731                 epp->ep_entry = ap->arg_interp + interp_offset;
  732                 ap->arg_phaddr = phdr;
  733 
  734                 ap->arg_phentsize = eh->e_phentsize;
  735                 ap->arg_phnum = eh->e_phnum;
  736                 ap->arg_entry = eh->e_entry;
  737 
  738                 epp->ep_emul_arg = ap;
  739 
  740                 PNBUF_PUT(interp);
  741         } else
  742                 epp->ep_entry = eh->e_entry;
  743 
  744 #ifdef ELF_MAP_PAGE_ZERO
  745         /* Dell SVR4 maps page zero, yeuch! */
  746         NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, PAGE_SIZE, 0,
  747             epp->ep_vp, 0, VM_PROT_READ);
  748 #endif
  749         free(ph, M_TEMP);
  750         return (*epp->ep_esch->es_setup_stack)(l, epp);
  751 
  752 bad:
  753         if (interp)
  754                 PNBUF_PUT(interp);
  755         free(ph, M_TEMP);
  756         kill_vmcmds(&epp->ep_vmcmds);
  757         return ENOEXEC;
  758 }
  759 
  760 int
  761 netbsd_elf_signature(struct lwp *l, struct exec_package *epp,
  762     Elf_Ehdr *eh)
  763 {
  764         size_t i;
  765         Elf_Phdr *ph;
  766         size_t phsize;
  767         int error;
  768         int isnetbsd = 0;
  769         char *ndata;
  770 
  771         epp->ep_pax_flags = 0;
  772         if (eh->e_phnum > MAXPHNUM)
  773                 return ENOEXEC;
  774 
  775         phsize = eh->e_phnum * sizeof(Elf_Phdr);
  776         ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);
  777         error = exec_read_from(l, epp->ep_vp, eh->e_phoff, ph, phsize);
  778         if (error)
  779                 goto out;
  780 
  781         for (i = 0; i < eh->e_phnum; i++) {
  782                 Elf_Phdr *ephp = &ph[i];
  783                 Elf_Nhdr *np;
  784 
  785                 if (ephp->p_type != PT_NOTE ||
  786                     ephp->p_filesz > 1024 ||
  787                     ephp->p_filesz < sizeof(Elf_Nhdr) + ELF_NOTE_NETBSD_NAMESZ)
  788                         continue;
  789 
  790                 np = (Elf_Nhdr *)malloc(ephp->p_filesz, M_TEMP, M_WAITOK);
  791                 error = exec_read_from(l, epp->ep_vp, ephp->p_offset, np,
  792                     ephp->p_filesz);
  793                 if (error)
  794                         goto next;
  795 
  796                 ndata = (char *)(np + 1);
  797                 switch (np->n_type) {
  798                 case ELF_NOTE_TYPE_NETBSD_TAG:
  799                         if (np->n_namesz != ELF_NOTE_NETBSD_NAMESZ ||
  800                             np->n_descsz != ELF_NOTE_NETBSD_DESCSZ ||
  801                             memcmp(ndata, ELF_NOTE_NETBSD_NAME,
  802                             ELF_NOTE_NETBSD_NAMESZ))
  803                                 goto next;
  804                         isnetbsd = 1;
  805                         break;
  806 
  807                 case ELF_NOTE_TYPE_PAX_TAG:
  808                         if (np->n_namesz != ELF_NOTE_PAX_NAMESZ ||
  809                             np->n_descsz != ELF_NOTE_PAX_DESCSZ ||
  810                             memcmp(ndata, ELF_NOTE_PAX_NAME,
  811                             ELF_NOTE_PAX_NAMESZ))
  812                                 goto next;
  813                         (void)memcpy(&epp->ep_pax_flags,
  814                             ndata + ELF_NOTE_PAX_NAMESZ,
  815                             sizeof(epp->ep_pax_flags));
  816                         break;
  817 
  818                 default:
  819                         break;
  820                 }
  821 
  822 next:
  823                 free(np, M_TEMP);
  824                 continue;
  825         }
  826 
  827         error = isnetbsd ? 0 : ENOEXEC;
  828 out:
  829         free(ph, M_TEMP);
  830         return error;
  831 }
  832 
  833 int
  834 netbsd_elf_probe(struct lwp *l, struct exec_package *epp, void *eh, char *itp,
  835     vaddr_t *pos)
  836 {
  837         int error;
  838 
  839         if ((error = netbsd_elf_signature(l, epp, eh)) != 0)
  840                 return error;
  841 #ifdef ELF_INTERP_NON_RELOCATABLE
  842         *pos = ELF_LINK_ADDR;
  843 #endif
  844         return 0;
  845 }

Cache object: 5b2c014a5b83fdee8a9996f72aa9c11f


[ 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.