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/imgact_elf.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 /*-
    2  * Copyright (c) 1995-1996 Søren Schmidt
    3  * Copyright (c) 1996 Peter Wemm
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer
   11  *    in this position and unchanged.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. The name of the author may not be used to endorse or promote products
   16  *    derived from this software withough specific prior written permission
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   28  *
   29  * $FreeBSD: src/sys/kern/imgact_elf.c,v 1.12.2.3 1999/09/05 08:14:45 peter Exp $
   30  */
   31 
   32 #include "opt_rlimit.h"
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/resourcevar.h>
   37 #include <sys/exec.h>
   38 #include <sys/mman.h>
   39 #include <sys/imgact.h>
   40 #include <sys/imgact_elf.h>
   41 #include <sys/kernel.h>
   42 #include <sys/sysent.h>
   43 #include <sys/file.h>
   44 #include <sys/malloc.h>
   45 #include <sys/mount.h>
   46 #include <sys/namei.h>
   47 #include <sys/proc.h>
   48 #include <sys/sysproto.h>
   49 #include <sys/syscall.h>
   50 #include <sys/signalvar.h>
   51 #include <sys/sysctl.h>
   52 #include <sys/vnode.h>
   53 
   54 #include <vm/vm.h>
   55 #include <vm/vm_kern.h>
   56 #include <vm/vm_param.h>
   57 #include <vm/pmap.h>
   58 #include <vm/lock.h>
   59 #include <vm/vm_map.h>
   60 #include <vm/vm_prot.h>
   61 #include <vm/vm_extern.h>
   62 
   63 #include <machine/md_var.h>
   64 #include <i386/linux/linux_syscall.h>
   65 #include <i386/linux/linux.h>
   66 
   67 #define MAX_PHDR        32      /* XXX enough ? */
   68 
   69 static int map_pages __P((struct vnode *vp, vm_offset_t offset, vm_offset_t *buf, vm_size_t size));
   70 static void unmap_pages __P((vm_offset_t buf, vm_size_t size));
   71 static int elf_check_permissions __P((struct proc *p, struct vnode *vp));
   72 static int elf_check_header __P((const Elf32_Ehdr *hdr, int type));
   73 static int elf_load_section __P((struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot));
   74 static int elf_load_file __P((struct proc *p, char *file, u_long *addr, u_long *entry));
   75 static int elf_freebsd_fixup __P((int **stack_base, struct image_params *imgp));
   76 int exec_elf_imgact __P((struct image_params *imgp));
   77 
   78 int elf_trace = 0;
   79 SYSCTL_INT(_debug, 1, elf_trace, CTLFLAG_RW, &elf_trace, 0, "");
   80 #define UPRINTF if (elf_trace) uprintf
   81 
   82 static struct sysentvec elf_freebsd_sysvec = {
   83         SYS_MAXSYSCALL,
   84         sysent,
   85         0,
   86         0,
   87         0,
   88         0,
   89         0,
   90         0,
   91         elf_freebsd_fixup,
   92         sendsig,
   93         sigcode,
   94         &szsigcode,
   95         0,
   96         "FreeBSD ELF"
   97 };
   98 
   99 static Elf32_Brandinfo freebsd_brand_info = {
  100                                                 "FreeBSD",
  101                                                 "",
  102                                                 "/usr/libexec/ld-elf.so.1",
  103                                                 &elf_freebsd_sysvec
  104                                           };
  105 static Elf32_Brandinfo *elf_brand_list[MAX_BRANDS] = {
  106                                                         &freebsd_brand_info,
  107                                                         NULL, NULL, NULL,
  108                                                         NULL, NULL, NULL, NULL
  109                                                     };
  110 
  111 int
  112 elf_insert_brand_entry(Elf32_Brandinfo *entry)
  113 {
  114         int i;
  115 
  116         for (i=1; i<MAX_BRANDS; i++) {
  117                 if (elf_brand_list[i] == NULL) {
  118                         elf_brand_list[i] = entry;
  119                         break;
  120                 }
  121         }
  122         if (i == MAX_BRANDS)
  123                 return -1;
  124         return 0;
  125 }
  126 
  127 int
  128 elf_remove_brand_entry(Elf32_Brandinfo *entry)
  129 {
  130         int i;
  131 
  132         for (i=1; i<MAX_BRANDS; i++) {
  133                 if (elf_brand_list[i] == entry) {
  134                         elf_brand_list[i] = NULL;
  135                         break;
  136                 }
  137         }
  138         if (i == MAX_BRANDS)
  139                 return -1;
  140         return 0;
  141 }
  142 
  143 static int
  144 map_pages(struct vnode *vp, vm_offset_t offset, 
  145              vm_offset_t *buf, vm_size_t size)
  146 {
  147         int error;
  148         vm_offset_t kern_buf;
  149         vm_size_t pageoff;
  150         
  151         /*
  152          * The request may not be aligned, and may even cross several
  153          * page boundaries in the file...
  154          */
  155         pageoff = (offset & PAGE_MASK);
  156         offset -= pageoff;              /* start of first aligned page to map */
  157         size += pageoff;
  158         size = round_page(size);        /* size of aligned pages to map */
  159         
  160         if (error = vm_mmap(kernel_map,
  161                             &kern_buf,
  162                             size,
  163                             VM_PROT_READ,
  164                             VM_PROT_READ,
  165                             0,
  166                             (caddr_t)vp,
  167                             offset))
  168                 return error;
  169 
  170         *buf = kern_buf + pageoff;
  171 
  172         return 0;
  173 }
  174 
  175 static void
  176 unmap_pages(vm_offset_t buf, vm_size_t size)
  177 {
  178         vm_size_t pageoff;
  179         
  180         pageoff = (buf & PAGE_MASK);
  181         buf -= pageoff;         /* start of first aligned page to map */
  182         size += pageoff;
  183         size = round_page(size);/* size of aligned pages to map */
  184         
  185         vm_map_remove(kernel_map, buf, buf + size);
  186 }
  187 
  188 static int
  189 elf_check_permissions(struct proc *p, struct vnode *vp)
  190 {
  191         struct vattr attr;
  192         int error;
  193 
  194         /*
  195          * Check number of open-for-writes on the file and deny execution
  196          *      if there are any.
  197          */
  198         if (vp->v_writecount) {
  199                 return (ETXTBSY);
  200         }
  201 
  202         /* Get file attributes */
  203         error = VOP_GETATTR(vp, &attr, p->p_ucred, p);
  204         if (error)
  205                 return (error);
  206 
  207         /*
  208          * 1) Check if file execution is disabled for the filesystem that this
  209          *      file resides on.
  210          * 2) Insure that at least one execute bit is on - otherwise root
  211          *      will always succeed, and we don't want to happen unless the
  212          *      file really is executable.
  213          * 3) Insure that the file is a regular file.
  214          */
  215         if ((vp->v_mount->mnt_flag & MNT_NOEXEC) ||
  216             ((attr.va_mode & 0111) == 0) ||
  217             (attr.va_type != VREG)) {
  218                 return (EACCES);
  219         }
  220 
  221         /*
  222          * Zero length files can't be exec'd
  223          */
  224         if (attr.va_size == 0)
  225                 return (ENOEXEC);
  226 
  227         /*
  228          *  Check for execute permission to file based on current credentials.
  229          *      Then call filesystem specific open routine (which does nothing
  230          *      in the general case).
  231          */
  232         error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
  233         if (error)
  234                 return (error);
  235 
  236         error = VOP_OPEN(vp, FREAD, p->p_ucred, p);
  237         if (error)
  238                 return (error);
  239 
  240         return (0);
  241 }
  242 
  243 static int
  244 elf_check_header(const Elf32_Ehdr *hdr, int type)
  245 {
  246         if (!(hdr->e_ident[EI_MAG0] == ELFMAG0 &&
  247               hdr->e_ident[EI_MAG1] == ELFMAG1 &&
  248               hdr->e_ident[EI_MAG2] == ELFMAG2 &&
  249               hdr->e_ident[EI_MAG3] == ELFMAG3))
  250                 return ENOEXEC;
  251 
  252         if (hdr->e_machine != EM_386 && hdr->e_machine != EM_486)
  253                 return ENOEXEC;
  254 
  255         if (hdr->e_type != type)
  256                 return ENOEXEC;
  257         
  258         return 0;
  259 }
  260 
  261 static int
  262 elf_load_section(struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot)
  263 {
  264         size_t map_len;
  265         vm_offset_t map_addr;
  266         int error;
  267         unsigned char *data_buf = 0;
  268         size_t copy_len;
  269 
  270         map_addr = trunc_page(vmaddr);
  271 
  272         if (memsz > filsz)
  273                 map_len = trunc_page(offset+filsz) - trunc_page(offset);
  274         else
  275                 map_len = round_page(offset+filsz) - trunc_page(offset);
  276 
  277         if (error = vm_mmap (&vmspace->vm_map,
  278                              &map_addr,
  279                              map_len,
  280                              prot,
  281                              VM_PROT_ALL,
  282                              MAP_PRIVATE | MAP_FIXED,
  283                              (caddr_t)vp,
  284                              trunc_page(offset)))
  285                 return error;
  286 
  287         if (memsz == filsz)
  288                 return 0;
  289 
  290         /*
  291          * We have to map the remaining bit of the file into the kernel's
  292          * memory map, allocate some anonymous memory, and copy that last
  293          * bit into it. The remaining space should be .bss...
  294          */
  295         copy_len = (offset + filsz) - trunc_page(offset + filsz);
  296         map_addr = trunc_page(vmaddr + filsz);
  297         map_len = round_page(vmaddr + memsz) - map_addr;
  298 
  299         if (map_len != 0) {
  300                 if (error = vm_map_find(&vmspace->vm_map, NULL, 0,
  301                                         &map_addr, map_len, FALSE,
  302                                         VM_PROT_ALL, VM_PROT_ALL,0))
  303                         return error; 
  304         }
  305 
  306         if (error = vm_mmap(kernel_map,
  307                             (vm_offset_t *)&data_buf,
  308                             PAGE_SIZE,
  309                             VM_PROT_READ,
  310                             VM_PROT_READ,
  311                             0,
  312                             (caddr_t)vp,
  313                             trunc_page(offset + filsz)))
  314                 return error;
  315 
  316         error = copyout(data_buf, (caddr_t)map_addr, copy_len);
  317 
  318         vm_map_remove(kernel_map, (vm_offset_t)data_buf, 
  319                       (vm_offset_t)data_buf + PAGE_SIZE);
  320 
  321         /*
  322          * set it to the specified protection
  323          */
  324         vm_map_protect(&vmspace->vm_map, map_addr, map_addr + map_len,  prot,
  325                        FALSE);
  326 
  327         UPRINTF("bss size %d (%x)\n", map_len-copy_len, map_len-copy_len);
  328         return error;
  329 }
  330 
  331 static int
  332 elf_load_file(struct proc *p, char *file, u_long *addr, u_long *entry)
  333 {
  334         Elf32_Ehdr *hdr = NULL;
  335         Elf32_Phdr *phdr = NULL;
  336         struct nameidata nd;
  337         struct vmspace *vmspace = p->p_vmspace;
  338         vm_prot_t prot = 0;
  339         unsigned long text_size = 0, data_size = 0;
  340         unsigned long text_addr = 0, data_addr = 0;
  341         int header_size = 0;
  342         int error, i;
  343 
  344         NDINIT(&nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_SYSSPACE, file, p);   
  345                          
  346         if (error = namei(&nd))
  347                 goto fail;
  348 
  349         if (nd.ni_vp == NULL) {
  350                 error = ENOEXEC;
  351                 goto fail;
  352         }
  353 
  354         /*
  355          * Check permissions, modes, uid, etc on the file, and "open" it.
  356          */
  357         error = elf_check_permissions(p, nd.ni_vp);
  358 
  359         /*
  360          * No longer need this, and it prevents demand paging.
  361          */
  362         VOP_UNLOCK(nd.ni_vp);
  363 
  364         if (error)
  365                 goto fail;
  366                 
  367         /*
  368          * Map in the header
  369          */
  370         if (error = map_pages(nd.ni_vp, 0, (vm_offset_t *)&hdr, sizeof(hdr)))
  371                 goto fail;
  372 
  373         /*
  374          * Do we have a valid ELF header ?
  375          */
  376         if (error = elf_check_header(hdr, ET_DYN))
  377                 goto fail;
  378 
  379         /*
  380          * ouch, need to bounds check in case user gives us a corrupted
  381          * file with an insane header size
  382          */
  383         if (hdr->e_phnum > MAX_PHDR) {  /* XXX: ever more than this? */
  384                 error = ENOEXEC;
  385                 goto fail;
  386         }
  387 
  388         header_size = hdr->e_phentsize * hdr->e_phnum;
  389 
  390         if (error = map_pages(nd.ni_vp, hdr->e_phoff, (vm_offset_t *)&phdr, 
  391                                  header_size))
  392                 goto fail;
  393 
  394         for (i = 0; i < hdr->e_phnum; i++) {
  395                 switch(phdr[i].p_type) {
  396 
  397                 case PT_NULL:   /* NULL section */
  398                         UPRINTF ("ELF(file) PT_NULL section\n");
  399                         break;
  400                 case PT_LOAD:   /* Loadable segment */
  401                 {
  402                         UPRINTF ("ELF(file) PT_LOAD section ");
  403                         if (phdr[i].p_flags & PF_X)
  404                                 prot |= VM_PROT_EXECUTE;
  405                         if (phdr[i].p_flags & PF_W)
  406                                 prot |= VM_PROT_WRITE;
  407                         if (phdr[i].p_flags & PF_R)
  408                                 prot |= VM_PROT_READ;
  409 
  410                         if (error = elf_load_section(vmspace, nd.ni_vp,
  411                                                      phdr[i].p_offset,
  412                                                      (caddr_t)phdr[i].p_vaddr +
  413                                                         (*addr),
  414                                                      phdr[i].p_memsz,
  415                                                      phdr[i].p_filesz, prot)) 
  416                                 goto fail;
  417 
  418                         /*
  419                          * Is this .text or .data ??
  420                          *
  421                          * We only handle one each of those yet XXX
  422                          */
  423                         if (hdr->e_entry >= phdr[i].p_vaddr &&
  424                         hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) {
  425                                 text_addr = trunc_page(phdr[i].p_vaddr+(*addr));
  426                                 text_size = round_page(phdr[i].p_memsz +
  427                                                        phdr[i].p_vaddr -
  428                                                        trunc_page(phdr[i].p_vaddr));
  429                                 *entry=(unsigned long)hdr->e_entry+(*addr);
  430                                 UPRINTF(".text <%08x,%08x> entry=%08x\n",
  431                                         text_addr, text_size, *entry);
  432                         } else {
  433                                 data_addr = trunc_page(phdr[i].p_vaddr+(*addr));
  434                                 data_size = round_page(phdr[i].p_memsz +
  435                                                        phdr[i].p_vaddr -
  436                                                        trunc_page(phdr[i].p_vaddr));
  437                                 UPRINTF(".data <%08x,%08x>\n",
  438                                         data_addr, data_size);
  439                         }
  440                 }
  441                 break;
  442 
  443                 case PT_DYNAMIC:/* Dynamic link information */
  444                         UPRINTF ("ELF(file) PT_DYNAMIC section\n");
  445                         break;
  446                 case PT_INTERP: /* Path to interpreter */
  447                         UPRINTF ("ELF(file) PT_INTERP section\n");
  448                         break;
  449                 case PT_NOTE:   /* Note section */
  450                         UPRINTF ("ELF(file) PT_NOTE section\n");
  451                         break;
  452                 case PT_SHLIB:  /* Shared lib section  */
  453                         UPRINTF ("ELF(file) PT_SHLIB section\n");
  454                         break;
  455                 case PT_PHDR:   /* Program header table info */
  456                         UPRINTF ("ELF(file) PT_PHDR section\n");
  457                         break;
  458                 default:
  459                         UPRINTF ("ELF(file) %d section ??\n", phdr[i].p_type );
  460                 }
  461         }
  462 
  463 fail:
  464         if (phdr)
  465                 unmap_pages((vm_offset_t)phdr, header_size);
  466         if (hdr)
  467                 unmap_pages((vm_offset_t)hdr, sizeof(hdr));
  468 
  469         return error;
  470 }
  471 
  472 int
  473 exec_elf_imgact(struct image_params *imgp)
  474 {
  475         const Elf32_Ehdr *hdr = (const Elf32_Ehdr *) imgp->image_header;
  476         const Elf32_Phdr *phdr, *mapped_phdr = NULL;
  477         Elf32_Auxargs *elf_auxargs = NULL;
  478         struct vmspace *vmspace = imgp->proc->p_vmspace;
  479         vm_prot_t prot = 0;
  480         u_long text_size = 0, data_size = 0;
  481         u_long text_addr = 0, data_addr = 0;
  482         u_long addr, entry = 0, proghdr = 0;
  483         int error, i, header_size = 0, interp_len = 0;
  484         char *interp = NULL;
  485         char *brand = NULL;
  486         char path[MAXPATHLEN];
  487 
  488         /*
  489          * Do we have a valid ELF header ?
  490          */
  491         if (elf_check_header(hdr, ET_EXEC))
  492                 return -1;
  493 
  494         /*
  495          * From here on down, we return an errno, not -1, as we've
  496          * detected an ELF file.
  497          */
  498 
  499         /*
  500          * ouch, need to bounds check in case user gives us a corrupted
  501          * file with an insane header size
  502          */
  503         if (hdr->e_phnum > MAX_PHDR) {  /* XXX: ever more than this? */
  504                 return ENOEXEC;
  505         }
  506 
  507         header_size = hdr->e_phentsize * hdr->e_phnum;
  508 
  509         if ((hdr->e_phoff > PAGE_SIZE) ||
  510             (hdr->e_phoff + header_size) > PAGE_SIZE) {
  511                 /*
  512                  * Ouch ! we only get one page full of header...
  513                  * Try to map it in ourselves, and see how we go.
  514                  */
  515                 if (error = map_pages(imgp->vp, hdr->e_phoff,
  516                                 (vm_offset_t *)&mapped_phdr, header_size))
  517                         return (error);
  518                 /*
  519                  * Save manual mapping for cleanup
  520                  */
  521                 phdr = mapped_phdr;
  522         } else {
  523                 phdr = (const Elf32_Phdr*)
  524                        ((const char *)imgp->image_header + hdr->e_phoff);
  525         }
  526         
  527         /*
  528          * From this point on, we may have resources that need to be freed.
  529          */
  530         if (error = exec_extract_strings(imgp))
  531                 goto fail;
  532 
  533         exec_new_vmspace(imgp);
  534 
  535         for (i = 0; i < hdr->e_phnum; i++) {
  536                 switch(phdr[i].p_type) {
  537 
  538                 case PT_NULL:   /* NULL section */
  539                         UPRINTF ("ELF PT_NULL section\n");
  540                         break;
  541                 case PT_LOAD:   /* Loadable segment */
  542                 {
  543                         UPRINTF ("ELF PT_LOAD section ");
  544                         if (phdr[i].p_flags & PF_X)
  545                                 prot |= VM_PROT_EXECUTE;
  546                         if (phdr[i].p_flags & PF_W)
  547                                 prot |= VM_PROT_WRITE;
  548                         if (phdr[i].p_flags & PF_R)
  549                                 prot |= VM_PROT_READ;
  550 
  551                         if (error = elf_load_section(vmspace, imgp->vp,
  552                                                      phdr[i].p_offset,
  553                                                      (caddr_t)phdr[i].p_vaddr,
  554                                                      phdr[i].p_memsz,
  555                                                      phdr[i].p_filesz, prot)) 
  556                                 goto fail;
  557 
  558                         /*
  559                          * Is this .text or .data ??
  560                          *
  561                          * We only handle one each of those yet XXX
  562                          */
  563                         if (hdr->e_entry >= phdr[i].p_vaddr &&
  564                         hdr->e_entry <(phdr[i].p_vaddr+phdr[i].p_memsz)) {
  565                                 text_addr = trunc_page(phdr[i].p_vaddr);
  566                                 text_size = round_page(phdr[i].p_memsz +
  567                                                        phdr[i].p_vaddr -
  568                                                        text_addr);
  569                                 entry = (u_long)hdr->e_entry;
  570                                 UPRINTF(".text <%08x,%08x> entry=%08x\n",
  571                                         text_addr, text_size, entry);
  572                         } else {
  573                                 data_addr = trunc_page(phdr[i].p_vaddr);
  574                                 data_size = round_page(phdr[i].p_memsz +
  575                                                        phdr[i].p_vaddr -
  576                                                        data_addr);
  577                                 UPRINTF(".data <%08x,%08x>\n",
  578                                         data_addr, data_size);
  579                         }
  580                 }
  581                 break;
  582 
  583                 case PT_DYNAMIC:/* Dynamic link information */
  584                         UPRINTF ("ELF PT_DYNAMIC section ??\n");
  585                         break;
  586                 case PT_INTERP: /* Path to interpreter */
  587                         UPRINTF ("ELF PT_INTERP section ");
  588                         if (phdr[i].p_filesz > MAXPATHLEN) {
  589                                 error = ENOEXEC;
  590                                 goto fail;
  591                         }
  592                         interp_len = MAXPATHLEN;
  593                         if (error = map_pages(imgp->vp, phdr[i].p_offset,
  594                                          (vm_offset_t *)&interp, interp_len))
  595                                 goto fail;
  596                         UPRINTF("<%s>\n", interp);
  597                         break;
  598                 case PT_NOTE:   /* Note section */
  599                         UPRINTF ("ELF PT_NOTE section\n");
  600                         break;
  601                 case PT_SHLIB:  /* Shared lib section  */
  602                         UPRINTF ("ELF PT_SHLIB section\n");
  603                         break;
  604                 case PT_PHDR:   /* Program header table info */
  605                         UPRINTF ("ELF PT_PHDR section <%x>\n", phdr[i].p_vaddr);
  606                         proghdr = phdr[i].p_vaddr;
  607                         break;
  608                 default:
  609                         UPRINTF ("ELF %d section ??\n", phdr[i].p_type);
  610                 }
  611         }
  612 
  613         vmspace->vm_tsize = text_size >> PAGE_SHIFT;
  614         vmspace->vm_taddr = (caddr_t)text_addr;
  615         vmspace->vm_dsize = data_size >> PAGE_SHIFT;
  616         vmspace->vm_daddr = (caddr_t)data_addr;
  617 
  618         addr = 2*MAXDSIZ; /* May depend on OS type XXX */
  619 
  620         imgp->entry_addr = entry;
  621 
  622         /* 
  623          * So which kind (brand) of ELF binary do we have at hand
  624          * FreeBSD, Linux, SVR4 or something else ??
  625          * If its has a interpreter section try that first
  626          */
  627         if (interp) {
  628                 for (i=0; i<MAX_BRANDS; i++) {
  629                         if (elf_brand_list[i] != NULL) {
  630                                 if (!strcmp(interp, elf_brand_list[i]->interp_path)) {
  631                                         imgp->proc->p_sysent =
  632                                                 elf_brand_list[i]->sysvec;
  633                                         strcpy(path, elf_brand_list[i]->emul_path);
  634                                         strcat(path, elf_brand_list[i]->interp_path);
  635                                         UPRINTF("interpreter=<%s> %s\n",
  636                                                 elf_brand_list[i]->interp_path,
  637                                                 elf_brand_list[i]->emul_path);
  638                                         break;
  639                                 }
  640                         }
  641                 }
  642         }
  643 
  644         /*
  645          * If there is no interpreter, or recognition of it
  646          * failed, se if the binary is branded.
  647          */
  648         if (!interp || i == MAX_BRANDS) {
  649                 brand = (char *)&(hdr->e_ident[EI_BRAND]);
  650                 for (i=0; i<MAX_BRANDS; i++) {
  651                         if (elf_brand_list[i] != NULL) {
  652                                 if (!strcmp(brand, elf_brand_list[i]->brand)) {
  653                                         imgp->proc->p_sysent = elf_brand_list[i]->sysvec;
  654                                         if (interp) {
  655                                                 strcpy(path, elf_brand_list[i]->emul_path);
  656                                                 strcat(path, elf_brand_list[i]->interp_path);
  657                                                 UPRINTF("interpreter=<%s> %s\n",
  658                                                 elf_brand_list[i]->interp_path,
  659                                                 elf_brand_list[i]->emul_path);
  660                                         }
  661                                         break;
  662                                 }
  663                         }
  664                 }
  665         }
  666         if (i == MAX_BRANDS) {
  667                 uprintf("ELF binary type not known\n");
  668                 error = ENOEXEC;
  669                 goto fail;
  670         }
  671         if (interp) {
  672                 if (error = elf_load_file(imgp->proc,
  673                                           path,
  674                                           &addr,        /* XXX */
  675                                           &imgp->entry_addr)) {
  676                         uprintf("ELF interpreter %s not found\n", path);
  677                         goto fail;
  678                 }
  679         }
  680 
  681         UPRINTF("Executing %s binary\n", elf_brand_list[i]->brand);
  682 
  683         /*
  684          * Construct auxargs table (used by the fixup routine)
  685          */
  686         elf_auxargs = malloc(sizeof(Elf32_Auxargs), M_TEMP, M_WAITOK);
  687         elf_auxargs->execfd = -1;
  688         elf_auxargs->phdr = proghdr;
  689         elf_auxargs->phent = hdr->e_phentsize;
  690         elf_auxargs->phnum = hdr->e_phnum;
  691         elf_auxargs->pagesz = PAGE_SIZE;
  692         elf_auxargs->base = addr;
  693         elf_auxargs->flags = 0;
  694         elf_auxargs->entry = entry;
  695         elf_auxargs->trace = elf_trace;
  696 
  697         imgp->auxargs = elf_auxargs;
  698         imgp->interpreted = 0;
  699 
  700         /* don't allow modifying the file while we run it */
  701         imgp->vp->v_flag |= VTEXT;
  702         
  703 fail:
  704         if (mapped_phdr)
  705                 unmap_pages((vm_offset_t)mapped_phdr, header_size);
  706         if (interp)
  707                 unmap_pages((vm_offset_t)interp, interp_len);
  708 
  709         return error;
  710 }
  711 
  712 static int
  713 elf_freebsd_fixup(int **stack_base, struct image_params *imgp)
  714 {
  715         Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs;
  716         int *pos;
  717 
  718         pos = *stack_base + (imgp->argc + imgp->envc + 2);
  719 
  720         if (args->trace) {
  721                 AUXARGS_ENTRY(pos, AT_DEBUG, 1);
  722         }
  723         if (args->execfd != -1) {
  724                 AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
  725         }
  726         AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
  727         AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
  728         AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
  729         AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
  730         AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
  731         AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
  732         AUXARGS_ENTRY(pos, AT_BASE, args->base);
  733         AUXARGS_ENTRY(pos, AT_NULL, 0);
  734 
  735         free(imgp->auxargs, M_TEMP);
  736         imgp->auxargs = NULL;
  737 
  738         (*stack_base)--;
  739         **stack_base = (int)imgp->argc;
  740         return 0;
  741 } 
  742 
  743 /*
  744  * Tell kern_execve.c about it, with a little help from the linker.
  745  * Since `const' objects end up in the text segment, TEXT_SET is the
  746  * correct directive to use.
  747  */
  748 const struct execsw elf_execsw = {exec_elf_imgact, "ELF"};
  749 TEXT_SET(execsw_set, elf_execsw);
  750 

Cache object: 886007bcbc22d8881c537f5ac3ae7b73


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