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$
   30  */
   31 
   32 #include <sys/param.h>
   33 #include <sys/exec.h>
   34 #include <sys/fcntl.h>
   35 #include <sys/imgact.h>
   36 #include <sys/imgact_elf.h>
   37 #include <sys/kernel.h>
   38 #include <sys/malloc.h>
   39 #include <sys/mman.h>
   40 #include <sys/namei.h>
   41 #include <sys/pioctl.h>
   42 #include <sys/proc.h>
   43 #include <sys/procfs.h>
   44 #include <sys/resourcevar.h>
   45 #include <sys/signalvar.h>
   46 #include <sys/stat.h>
   47 #include <sys/syscall.h>
   48 #include <sys/sysctl.h>
   49 #include <sys/sysent.h>
   50 #include <sys/systm.h>
   51 #include <sys/vnode.h>
   52 
   53 #include <vm/vm.h>
   54 #include <vm/vm_kern.h>
   55 #include <vm/vm_param.h>
   56 #include <vm/pmap.h>
   57 #include <sys/lock.h>
   58 #include <vm/vm_map.h>
   59 #include <vm/vm_object.h>
   60 #include <vm/vm_extern.h>
   61 
   62 #include <machine/elf.h>
   63 #include <machine/md_var.h>
   64 
   65 #define OLD_EI_BRAND    8
   66 
   67 __ElfType(Brandinfo);
   68 __ElfType(Auxargs);
   69 
   70 static int elf_check_header __P((const Elf_Ehdr *hdr));
   71 static int elf_freebsd_fixup __P((register_t **stack_base,
   72     struct image_params *imgp));
   73 static int elf_load_file __P((struct proc *p, const char *file, u_long *addr,
   74     u_long *entry));
   75 static int elf_load_section __P((struct proc *p,
   76     struct vmspace *vmspace, struct vnode *vp,
   77     vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz,
   78     vm_prot_t prot));
   79 static int exec_elf_imgact __P((struct image_params *imgp));
   80 
   81 static int elf_trace = 0;
   82 SYSCTL_INT(_debug, OID_AUTO, elf_trace, CTLFLAG_RW, &elf_trace, 0, "");
   83 static int elf_legacy_coredump = 0;
   84 SYSCTL_INT(_debug, OID_AUTO, elf_legacy_coredump, CTLFLAG_RW,
   85     &elf_legacy_coredump, 0, "");
   86 
   87 static struct sysentvec elf_freebsd_sysvec = {
   88         SYS_MAXSYSCALL,
   89         sysent,
   90         0,
   91         0,
   92         0,
   93         0,
   94         0,
   95         0,
   96         elf_freebsd_fixup,
   97         sendsig,
   98         sigcode,
   99         &szsigcode,
  100         0,
  101         "FreeBSD ELF",
  102         elf_coredump,
  103         NULL,
  104         MINSIGSTKSZ
  105 };
  106 
  107 static Elf_Brandinfo freebsd_brand_info = {
  108                                                 ELFOSABI_FREEBSD,
  109                                                 "FreeBSD",
  110                                                 "",
  111                                                 "/usr/libexec/ld-elf.so.1",
  112                                                 &elf_freebsd_sysvec
  113                                           };
  114 static Elf_Brandinfo *elf_brand_list[MAX_BRANDS] = {
  115                                                         &freebsd_brand_info,
  116                                                         NULL, NULL, NULL,
  117                                                         NULL, NULL, NULL, NULL
  118                                                     };
  119 
  120 int
  121 elf_insert_brand_entry(Elf_Brandinfo *entry)
  122 {
  123         int i;
  124 
  125         for (i=1; i<MAX_BRANDS; i++) {
  126                 if (elf_brand_list[i] == NULL) {
  127                         elf_brand_list[i] = entry;
  128                         break;
  129                 }
  130         }
  131         if (i == MAX_BRANDS)
  132                 return -1;
  133         return 0;
  134 }
  135 
  136 int
  137 elf_remove_brand_entry(Elf_Brandinfo *entry)
  138 {
  139         int i;
  140 
  141         for (i=1; i<MAX_BRANDS; i++) {
  142                 if (elf_brand_list[i] == entry) {
  143                         elf_brand_list[i] = NULL;
  144                         break;
  145                 }
  146         }
  147         if (i == MAX_BRANDS)
  148                 return -1;
  149         return 0;
  150 }
  151 
  152 int
  153 elf_brand_inuse(Elf_Brandinfo *entry)
  154 {
  155         struct proc *p;
  156         int rval = FALSE;
  157 
  158         LIST_FOREACH(p, &allproc, p_list) {
  159                 if (p->p_sysent == entry->sysvec) {
  160                         rval = TRUE;
  161                         break;
  162                 }
  163         }
  164 
  165         return (rval);
  166 }
  167 
  168 static int
  169 elf_check_header(const Elf_Ehdr *hdr)
  170 {
  171         if (!IS_ELF(*hdr) ||
  172             hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS ||
  173             hdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
  174             hdr->e_ident[EI_VERSION] != EV_CURRENT)
  175                 return ENOEXEC;
  176 
  177         if (!ELF_MACHINE_OK(hdr->e_machine))
  178                 return ENOEXEC;
  179 
  180         if (hdr->e_version != ELF_TARG_VER)
  181                 return ENOEXEC;
  182         
  183         return 0;
  184 }
  185 
  186 static int
  187 elf_load_section(struct proc *p, struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot)
  188 {
  189         size_t map_len;
  190         vm_offset_t map_addr;
  191         int error, rv, cow;
  192         size_t copy_len;
  193         vm_object_t object;
  194         vm_offset_t file_addr;
  195         vm_offset_t data_buf = 0;
  196 
  197         VOP_GETVOBJECT(vp, &object);
  198         error = 0;
  199 
  200         /*
  201          * It's necessary to fail if the filsz + offset taken from the
  202          * header is greater than the actual file pager object's size.
  203          * If we were to allow this, then the vm_map_find() below would
  204          * walk right off the end of the file object and into the ether.
  205          *
  206          * While I'm here, might as well check for something else that
  207          * is invalid: filsz cannot be greater than memsz.
  208          */
  209         if ((off_t)filsz + offset > object->un_pager.vnp.vnp_size ||
  210             filsz > memsz) {
  211                 uprintf("elf_load_section: truncated ELF file\n");
  212                 return (ENOEXEC);
  213         }
  214 
  215         map_addr = trunc_page((vm_offset_t)vmaddr);
  216         file_addr = trunc_page(offset);
  217 
  218         /*
  219          * We have two choices.  We can either clear the data in the last page
  220          * of an oversized mapping, or we can start the anon mapping a page
  221          * early and copy the initialized data into that first page.  We
  222          * choose the second..
  223          */
  224         if (memsz > filsz)
  225                 map_len = trunc_page(offset+filsz) - file_addr;
  226         else
  227                 map_len = round_page(offset+filsz) - file_addr;
  228 
  229         if (map_len != 0) {
  230                 vm_object_reference(object);
  231 
  232                 /* cow flags: don't dump readonly sections in core */
  233                 cow = MAP_COPY_ON_WRITE | MAP_PREFAULT |
  234                     (prot & VM_PROT_WRITE ? 0 : MAP_DISABLE_COREDUMP);
  235 
  236                 vm_map_lock(&vmspace->vm_map);
  237                 rv = vm_map_insert(&vmspace->vm_map,
  238                                       object,
  239                                       file_addr,        /* file offset */
  240                                       map_addr,         /* virtual start */
  241                                       map_addr + map_len,/* virtual end */
  242                                       prot,
  243                                       VM_PROT_ALL,
  244                                       cow);
  245                 vm_map_unlock(&vmspace->vm_map);
  246                 if (rv != KERN_SUCCESS) {
  247                         vm_object_deallocate(object);
  248                         return EINVAL;
  249                 }
  250 
  251                 /* we can stop now if we've covered it all */
  252                 if (memsz == filsz) {
  253                         return 0;
  254                 }
  255         }
  256 
  257 
  258         /*
  259          * We have to get the remaining bit of the file into the first part
  260          * of the oversized map segment.  This is normally because the .data
  261          * segment in the file is extended to provide bss.  It's a neat idea
  262          * to try and save a page, but it's a pain in the behind to implement.
  263          */
  264         copy_len = (offset + filsz) - trunc_page(offset + filsz);
  265         map_addr = trunc_page((vm_offset_t)vmaddr + filsz);
  266         map_len = round_page((vm_offset_t)vmaddr + memsz) - map_addr;
  267 
  268         /* This had damn well better be true! */
  269         if (map_len != 0) {
  270                 vm_map_lock(&vmspace->vm_map);
  271                 rv = vm_map_insert(&vmspace->vm_map, NULL, 0,
  272                                         map_addr, map_addr + map_len,
  273                                         VM_PROT_ALL, VM_PROT_ALL, 0);
  274                 vm_map_unlock(&vmspace->vm_map);
  275                 if (rv != KERN_SUCCESS) {
  276                         return EINVAL; 
  277                 }
  278         }
  279 
  280         if (copy_len != 0) {
  281                 vm_object_reference(object);
  282                 rv = vm_map_find(exec_map,
  283                                  object, 
  284                                  trunc_page(offset + filsz),
  285                                  &data_buf,
  286                                  PAGE_SIZE,
  287                                  TRUE,
  288                                  VM_PROT_READ,
  289                                  VM_PROT_ALL,
  290                                  MAP_COPY_ON_WRITE | MAP_PREFAULT_PARTIAL);
  291                 if (rv != KERN_SUCCESS) {
  292                         vm_object_deallocate(object);
  293                         return EINVAL;
  294                 }
  295 
  296                 /* send the page fragment to user space */
  297                 error = copyout((caddr_t)data_buf, (caddr_t)map_addr, copy_len);
  298                 vm_map_remove(exec_map, data_buf, data_buf + PAGE_SIZE);
  299                 if (error) {
  300                         return (error);
  301                 }
  302         }
  303 
  304         /*
  305          * set it to the specified protection
  306          */
  307         vm_map_protect(&vmspace->vm_map, map_addr, map_addr + map_len,  prot,
  308                        FALSE);
  309 
  310         return error;
  311 }
  312 
  313 /*
  314  * Load the file "file" into memory.  It may be either a shared object
  315  * or an executable.
  316  *
  317  * The "addr" reference parameter is in/out.  On entry, it specifies
  318  * the address where a shared object should be loaded.  If the file is
  319  * an executable, this value is ignored.  On exit, "addr" specifies
  320  * where the file was actually loaded.
  321  *
  322  * The "entry" reference parameter is out only.  On exit, it specifies
  323  * the entry point for the loaded file.
  324  */
  325 static int
  326 elf_load_file(struct proc *p, const char *file, u_long *addr, u_long *entry)
  327 {
  328         struct {
  329                 struct nameidata nd;
  330                 struct vattr attr;
  331                 struct image_params image_params;
  332         } *tempdata;
  333         const Elf_Ehdr *hdr = NULL;
  334         const Elf_Phdr *phdr = NULL;
  335         struct nameidata *nd;
  336         struct vmspace *vmspace = p->p_vmspace;
  337         struct vattr *attr;
  338         struct image_params *imgp;
  339         vm_prot_t prot;
  340         u_long rbase;
  341         u_long base_addr = 0;
  342         int error, i, numsegs;
  343 
  344         tempdata = malloc(sizeof(*tempdata), M_TEMP, M_WAITOK);
  345         nd = &tempdata->nd;
  346         attr = &tempdata->attr;
  347         imgp = &tempdata->image_params;
  348 
  349         /*
  350          * Initialize part of the common data
  351          */
  352         imgp->proc = p;
  353         imgp->uap = NULL;
  354         imgp->attr = attr;
  355         imgp->firstpage = NULL;
  356         imgp->image_header = (char *)kmem_alloc_wait(exec_map, PAGE_SIZE);
  357 
  358         if (imgp->image_header == NULL) {
  359                 nd->ni_vp = NULL;
  360                 error = ENOMEM;
  361                 goto fail;
  362         }
  363 
  364         NDINIT(nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_SYSSPACE, file, p);   
  365                          
  366         if ((error = namei(nd)) != 0) {
  367                 nd->ni_vp = NULL;
  368                 goto fail;
  369         }
  370         NDFREE(nd, NDF_ONLY_PNBUF);
  371         imgp->vp = nd->ni_vp;
  372 
  373         /*
  374          * Check permissions, modes, uid, etc on the file, and "open" it.
  375          */
  376         error = exec_check_permissions(imgp);
  377         if (error) {
  378                 VOP_UNLOCK(nd->ni_vp, 0, p);
  379                 goto fail;
  380         }
  381 
  382         error = exec_map_first_page(imgp);
  383         /*
  384          * Also make certain that the interpreter stays the same, so set
  385          * its VTEXT flag, too.
  386          */
  387         if (error == 0)
  388                 nd->ni_vp->v_flag |= VTEXT;
  389         VOP_UNLOCK(nd->ni_vp, 0, p);
  390         if (error)
  391                 goto fail;
  392 
  393         hdr = (const Elf_Ehdr *)imgp->image_header;
  394         if ((error = elf_check_header(hdr)) != 0)
  395                 goto fail;
  396         if (hdr->e_type == ET_DYN)
  397                 rbase = *addr;
  398         else if (hdr->e_type == ET_EXEC)
  399                 rbase = 0;
  400         else {
  401                 error = ENOEXEC;
  402                 goto fail;
  403         }
  404 
  405         /* Only support headers that fit within first page for now */
  406         if ((hdr->e_phoff > PAGE_SIZE) ||
  407             (hdr->e_phoff + hdr->e_phentsize * hdr->e_phnum) > PAGE_SIZE) {
  408                 error = ENOEXEC;
  409                 goto fail;
  410         }
  411 
  412         phdr = (const Elf_Phdr *)(imgp->image_header + hdr->e_phoff);
  413 
  414         for (i = 0, numsegs = 0; i < hdr->e_phnum; i++) {
  415                 if (phdr[i].p_type == PT_LOAD) {        /* Loadable segment */
  416                         prot = 0;
  417                         if (phdr[i].p_flags & PF_X)
  418                                 prot |= VM_PROT_EXECUTE;
  419                         if (phdr[i].p_flags & PF_W)
  420                                 prot |= VM_PROT_WRITE;
  421                         if (phdr[i].p_flags & PF_R)
  422                                 prot |= VM_PROT_READ;
  423 
  424                         if ((error = elf_load_section(p, vmspace, nd->ni_vp,
  425                                                      phdr[i].p_offset,
  426                                                      (caddr_t)phdr[i].p_vaddr +
  427                                                         rbase,
  428                                                      phdr[i].p_memsz,
  429                                                      phdr[i].p_filesz, prot)) != 0)
  430                                 goto fail;
  431                         /*
  432                          * Establish the base address if this is the
  433                          * first segment.
  434                          */
  435                         if (numsegs == 0)
  436                                 base_addr = trunc_page(phdr[i].p_vaddr + rbase);
  437                         numsegs++;
  438                 }
  439         }
  440         *addr = base_addr;
  441         *entry=(unsigned long)hdr->e_entry + rbase;
  442 
  443 fail:
  444         if (imgp->firstpage)
  445                 exec_unmap_first_page(imgp);
  446         if (imgp->image_header)
  447                 kmem_free_wakeup(exec_map, (vm_offset_t)imgp->image_header,
  448                         PAGE_SIZE);
  449         if (nd->ni_vp)
  450                 vrele(nd->ni_vp);
  451 
  452         free(tempdata, M_TEMP);
  453 
  454         return error;
  455 }
  456 
  457 /*
  458  * non static, as it can be overridden by start_init()
  459  */
  460 int fallback_elf_brand = -1;
  461 SYSCTL_INT(_kern, OID_AUTO, fallback_elf_brand, CTLFLAG_RW,
  462                 &fallback_elf_brand, -1,
  463                 "ELF brand of last resort");
  464 
  465 static int
  466 exec_elf_imgact(struct image_params *imgp)
  467 {
  468         const Elf_Ehdr *hdr = (const Elf_Ehdr *) imgp->image_header;
  469         const Elf_Phdr *phdr;
  470         Elf_Auxargs *elf_auxargs = NULL;
  471         struct vmspace *vmspace;
  472         vm_prot_t prot;
  473         u_long text_size = 0, data_size = 0, total_size = 0;
  474         u_long text_addr = 0, data_addr = 0;
  475         u_long seg_size, seg_addr;
  476         u_long addr, entry = 0, proghdr = 0;
  477         int error, i;
  478         const char *interp = NULL;
  479         Elf_Brandinfo *brand_info;
  480         char *path;
  481 
  482         /*
  483          * Do we have a valid ELF header ?
  484          */
  485         if (elf_check_header(hdr) != 0 || hdr->e_type != ET_EXEC)
  486                 return -1;
  487 
  488         /*
  489          * From here on down, we return an errno, not -1, as we've
  490          * detected an ELF file.
  491          */
  492 
  493         if ((hdr->e_phoff > PAGE_SIZE) ||
  494             (hdr->e_phoff + hdr->e_phentsize * hdr->e_phnum) > PAGE_SIZE) {
  495                 /* Only support headers in first page for now */
  496                 return ENOEXEC;
  497         }
  498         phdr = (const Elf_Phdr*)(imgp->image_header + hdr->e_phoff);
  499         
  500         /*
  501          * From this point on, we may have resources that need to be freed.
  502          */
  503 
  504         if ((error = exec_extract_strings(imgp)) != 0)
  505                 goto fail;
  506 
  507         exec_new_vmspace(imgp);
  508 
  509         /*
  510          * Yeah, I'm paranoid.  There is every reason in the world to get
  511          * VTEXT now since from here on out, there are places we can have
  512          * a context switch.  Better safe than sorry; I really don't want
  513          * the file to change while it's being loaded.
  514          */
  515         simple_lock(&imgp->vp->v_interlock);
  516         imgp->vp->v_flag |= VTEXT;
  517         simple_unlock(&imgp->vp->v_interlock);
  518 
  519         vmspace = imgp->proc->p_vmspace;
  520 
  521         for (i = 0; i < hdr->e_phnum; i++) {
  522                 switch(phdr[i].p_type) {
  523 
  524                 case PT_LOAD:   /* Loadable segment */
  525                         prot = 0;
  526                         if (phdr[i].p_flags & PF_X)
  527                                 prot |= VM_PROT_EXECUTE;
  528                         if (phdr[i].p_flags & PF_W)
  529                                 prot |= VM_PROT_WRITE;
  530                         if (phdr[i].p_flags & PF_R)
  531                                 prot |= VM_PROT_READ;
  532 
  533                         if ((error = elf_load_section(imgp->proc,
  534                                                      vmspace, imgp->vp,
  535                                                      phdr[i].p_offset,
  536                                                      (caddr_t)phdr[i].p_vaddr,
  537                                                      phdr[i].p_memsz,
  538                                                      phdr[i].p_filesz, prot)) != 0)
  539                                 goto fail;
  540 
  541                         seg_addr = trunc_page(phdr[i].p_vaddr);
  542                         seg_size = round_page(phdr[i].p_memsz +
  543                                 phdr[i].p_vaddr - seg_addr);
  544 
  545                         /*
  546                          * Is this .text or .data?  We can't use
  547                          * VM_PROT_WRITE or VM_PROT_EXEC, it breaks the
  548                          * alpha terribly and possibly does other bad
  549                          * things so we stick to the old way of figuring
  550                          * it out:  If the segment contains the program
  551                          * entry point, it's a text segment, otherwise it
  552                          * is a data segment.
  553                          *
  554                          * Note that obreak() assumes that data_addr + 
  555                          * data_size == end of data load area, and the ELF
  556                          * file format expects segments to be sorted by
  557                          * address.  If multiple data segments exist, the
  558                          * last one will be used.
  559                          */
  560                         if (hdr->e_entry >= phdr[i].p_vaddr &&
  561                             hdr->e_entry < (phdr[i].p_vaddr +
  562                             phdr[i].p_memsz)) {
  563                                 text_size = seg_size;
  564                                 text_addr = seg_addr;
  565                                 entry = (u_long)hdr->e_entry;
  566                         } else {
  567                                 data_size = seg_size;
  568                                 data_addr = seg_addr;
  569                         }
  570                         total_size += seg_size;
  571 
  572                         /*
  573                          * Check limits.  It should be safe to check the
  574                          * limits after loading the segment since we do
  575                          * not actually fault in all the segment's pages.
  576                          */
  577                         if (data_size >
  578                             imgp->proc->p_rlimit[RLIMIT_DATA].rlim_cur ||
  579                             text_size > maxtsiz ||
  580                             total_size >
  581                             imgp->proc->p_rlimit[RLIMIT_VMEM].rlim_cur) {
  582                                 error = ENOMEM;
  583                                 goto fail;
  584                         }
  585                         break;
  586                 case PT_INTERP: /* Path to interpreter */
  587                         if (phdr[i].p_filesz > MAXPATHLEN ||
  588                             phdr[i].p_offset + phdr[i].p_filesz > PAGE_SIZE) {
  589                                 error = ENOEXEC;
  590                                 goto fail;
  591                         }
  592                         interp = imgp->image_header + phdr[i].p_offset;
  593                         break;
  594                 case PT_PHDR:   /* Program header table info */
  595                         proghdr = phdr[i].p_vaddr;
  596                         break;
  597                 default:
  598                         break;
  599                 }
  600         }
  601 
  602         vmspace->vm_tsize = text_size >> PAGE_SHIFT;
  603         vmspace->vm_taddr = (caddr_t)(uintptr_t)text_addr;
  604         vmspace->vm_dsize = data_size >> PAGE_SHIFT;
  605         vmspace->vm_daddr = (caddr_t)(uintptr_t)data_addr;
  606 
  607         addr = ELF_RTLD_ADDR(vmspace);
  608 
  609         imgp->entry_addr = entry;
  610 
  611         brand_info = NULL;
  612 
  613         /* We support three types of branding -- (1) the ELF EI_OSABI field
  614          * that SCO added to the ELF spec, (2) FreeBSD 3.x's traditional string
  615          * branding w/in the ELF header, and (3) path of the `interp_path'
  616          * field.  We should also look for an ".note.ABI-tag" ELF section now
  617          * in all Linux ELF binaries, FreeBSD 4.1+, and some NetBSD ones.
  618          */
  619 
  620         /* If the executable has a brand, search for it in the brand list. */
  621         if (brand_info == NULL) {
  622                 for (i = 0;  i < MAX_BRANDS;  i++) {
  623                         Elf_Brandinfo *bi = elf_brand_list[i];
  624 
  625                         if (bi != NULL && 
  626                             (hdr->e_ident[EI_OSABI] == bi->brand
  627                             || 0 == 
  628                             strncmp((const char *)&hdr->e_ident[OLD_EI_BRAND], 
  629                             bi->compat_3_brand, strlen(bi->compat_3_brand)))) {
  630                                 brand_info = bi;
  631                                 break;
  632                         }
  633                 }
  634         }
  635 
  636         /* Lacking a known brand, search for a recognized interpreter. */
  637         if (brand_info == NULL && interp != NULL) {
  638                 for (i = 0;  i < MAX_BRANDS;  i++) {
  639                         Elf_Brandinfo *bi = elf_brand_list[i];
  640 
  641                         if (bi != NULL &&
  642                             strcmp(interp, bi->interp_path) == 0) {
  643                                 brand_info = bi;
  644                                 break;
  645                         }
  646                 }
  647         }
  648 
  649         /* Lacking a recognized interpreter, try the default brand */
  650         if (brand_info == NULL) {
  651                 for (i = 0; i < MAX_BRANDS; i++) {
  652                         Elf_Brandinfo *bi = elf_brand_list[i];
  653 
  654                         if (bi != NULL && fallback_elf_brand == bi->brand) {
  655                                 brand_info = bi;
  656                                 break;
  657                         }
  658                 }
  659         }
  660 
  661         if (brand_info == NULL) {
  662                 uprintf("ELF binary type \"%u\" not known.\n",
  663                     hdr->e_ident[EI_OSABI]);
  664                 error = ENOEXEC;
  665                 goto fail;
  666         }
  667 
  668         imgp->proc->p_sysent = brand_info->sysvec;
  669         if (interp != NULL) {
  670                 path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
  671                 snprintf(path, MAXPATHLEN, "%s%s",
  672                          brand_info->emul_path, interp);
  673                 if ((error = elf_load_file(imgp->proc, path, &addr,
  674                                            &imgp->entry_addr)) != 0) {
  675                         if ((error = elf_load_file(imgp->proc, interp, &addr,
  676                                                    &imgp->entry_addr)) != 0) {
  677                                 uprintf("ELF interpreter %s not found\n", path);
  678                                 free(path, M_TEMP);
  679                                 goto fail;
  680                         }
  681                 }
  682                 free(path, M_TEMP);
  683         }
  684 
  685         /*
  686          * Construct auxargs table (used by the fixup routine)
  687          */
  688         elf_auxargs = malloc(sizeof(Elf_Auxargs), M_TEMP, M_WAITOK);
  689         elf_auxargs->execfd = -1;
  690         elf_auxargs->phdr = proghdr;
  691         elf_auxargs->phent = hdr->e_phentsize;
  692         elf_auxargs->phnum = hdr->e_phnum;
  693         elf_auxargs->pagesz = PAGE_SIZE;
  694         elf_auxargs->base = addr;
  695         elf_auxargs->flags = 0;
  696         elf_auxargs->entry = entry;
  697         elf_auxargs->trace = elf_trace;
  698 
  699         imgp->auxargs = elf_auxargs;
  700         imgp->interpreted = 0;
  701 
  702 fail:
  703         return error;
  704 }
  705 
  706 static int
  707 elf_freebsd_fixup(register_t **stack_base, struct image_params *imgp)
  708 {
  709         Elf_Auxargs *args = (Elf_Auxargs *)imgp->auxargs;
  710         register_t *pos;
  711 
  712         pos = *stack_base + (imgp->argc + imgp->envc + 2);
  713 
  714         if (args->trace) {
  715                 AUXARGS_ENTRY(pos, AT_DEBUG, 1);
  716         }
  717         if (args->execfd != -1) {
  718                 AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
  719         }
  720         AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
  721         AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
  722         AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
  723         AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
  724         AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
  725         AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
  726         AUXARGS_ENTRY(pos, AT_BASE, args->base);
  727         AUXARGS_ENTRY(pos, AT_NULL, 0);
  728 
  729         free(imgp->auxargs, M_TEMP);
  730         imgp->auxargs = NULL;
  731 
  732         (*stack_base)--;
  733         suword(*stack_base, (long) imgp->argc);
  734         return 0;
  735 } 
  736 
  737 /*
  738  * Code for generating ELF core dumps.
  739  */
  740 
  741 typedef void (*segment_callback) __P((vm_map_entry_t, void *));
  742 
  743 /* Closure for cb_put_phdr(). */
  744 struct phdr_closure {
  745         Elf_Phdr *phdr;         /* Program header to fill in */
  746         Elf_Off offset;         /* Offset of segment in core file */
  747 };
  748 
  749 /* Closure for cb_size_segment(). */
  750 struct sseg_closure {
  751         int count;              /* Count of writable segments. */
  752         size_t size;            /* Total size of all writable segments. */
  753 };
  754 
  755 static void cb_put_phdr __P((vm_map_entry_t, void *));
  756 static void cb_size_segment __P((vm_map_entry_t, void *));
  757 static void each_writable_segment __P((struct proc *, segment_callback,
  758     void *));
  759 static int elf_corehdr __P((struct proc *, struct vnode *, struct ucred *,
  760     int, void *, size_t));
  761 static void elf_puthdr __P((struct proc *, void *, size_t *,
  762     const prstatus_t *, const prfpregset_t *, const prpsinfo_t *, int));
  763 static void elf_putnote __P((void *, size_t *, const char *, int,
  764     const void *, size_t));
  765 
  766 extern int osreldate;
  767 
  768 int
  769 elf_coredump(p, vp, limit)
  770         register struct proc *p;
  771         register struct vnode *vp;
  772         off_t limit;
  773 {
  774         register struct ucred *cred = p->p_ucred;
  775         int error = 0;
  776         struct sseg_closure seginfo;
  777         void *hdr;
  778         size_t hdrsize;
  779 
  780         /* Size the program segments. */
  781         seginfo.count = 0;
  782         seginfo.size = 0;
  783         each_writable_segment(p, cb_size_segment, &seginfo);
  784 
  785         /*
  786          * Calculate the size of the core file header area by making
  787          * a dry run of generating it.  Nothing is written, but the
  788          * size is calculated.
  789          */
  790         hdrsize = 0;
  791         elf_puthdr((struct proc *)NULL, (void *)NULL, &hdrsize,
  792             (const prstatus_t *)NULL, (const prfpregset_t *)NULL,
  793             (const prpsinfo_t *)NULL, seginfo.count);
  794 
  795         if (hdrsize + seginfo.size >= limit)
  796                 return (EFAULT);
  797 
  798         /*
  799          * Allocate memory for building the header, fill it up,
  800          * and write it out.
  801          */
  802         hdr = malloc(hdrsize, M_TEMP, M_WAITOK);
  803         if (hdr == NULL) {
  804                 return EINVAL;
  805         }
  806         error = elf_corehdr(p, vp, cred, seginfo.count, hdr, hdrsize);
  807 
  808         /* Write the contents of all of the writable segments. */
  809         if (error == 0) {
  810                 Elf_Phdr *php;
  811                 off_t offset;
  812                 int i;
  813 
  814                 php = (Elf_Phdr *)((char *)hdr + sizeof(Elf_Ehdr)) + 1;
  815                 offset = hdrsize;
  816                 for (i = 0;  i < seginfo.count;  i++) {
  817                         error = vn_rdwr_inchunks(UIO_WRITE, vp, 
  818                             (caddr_t)php->p_vaddr,
  819                             php->p_filesz, offset, UIO_USERSPACE,
  820                             IO_UNIT | IO_DIRECT, cred, (int *)NULL, p);
  821                         if (error != 0)
  822                                 break;
  823                         offset += php->p_filesz;
  824                         php++;
  825                 }
  826         }
  827         free(hdr, M_TEMP);
  828         
  829         return error;
  830 }
  831 
  832 /*
  833  * A callback for each_writable_segment() to write out the segment's
  834  * program header entry.
  835  */
  836 static void
  837 cb_put_phdr(entry, closure)
  838         vm_map_entry_t entry;
  839         void *closure;
  840 {
  841         struct phdr_closure *phc = (struct phdr_closure *)closure;
  842         Elf_Phdr *phdr = phc->phdr;
  843 
  844         phc->offset = round_page(phc->offset);
  845 
  846         phdr->p_type = PT_LOAD;
  847         phdr->p_offset = phc->offset;
  848         phdr->p_vaddr = entry->start;
  849         phdr->p_paddr = 0;
  850         phdr->p_filesz = phdr->p_memsz = entry->end - entry->start;
  851         phdr->p_align = PAGE_SIZE;
  852         phdr->p_flags = 0;
  853         if (entry->protection & VM_PROT_READ)
  854                 phdr->p_flags |= PF_R;
  855         if (entry->protection & VM_PROT_WRITE)
  856                 phdr->p_flags |= PF_W;
  857         if (entry->protection & VM_PROT_EXECUTE)
  858                 phdr->p_flags |= PF_X;
  859 
  860         phc->offset += phdr->p_filesz;
  861         phc->phdr++;
  862 }
  863 
  864 /*
  865  * A callback for each_writable_segment() to gather information about
  866  * the number of segments and their total size.
  867  */
  868 static void
  869 cb_size_segment(entry, closure)
  870         vm_map_entry_t entry;
  871         void *closure;
  872 {
  873         struct sseg_closure *ssc = (struct sseg_closure *)closure;
  874 
  875         ssc->count++;
  876         ssc->size += entry->end - entry->start;
  877 }
  878 
  879 /*
  880  * For each writable segment in the process's memory map, call the given
  881  * function with a pointer to the map entry and some arbitrary
  882  * caller-supplied data.
  883  */
  884 static void
  885 each_writable_segment(p, func, closure)
  886         struct proc *p;
  887         segment_callback func;
  888         void *closure;
  889 {
  890         vm_map_t map = &p->p_vmspace->vm_map;
  891         vm_map_entry_t entry;
  892 
  893         for (entry = map->header.next;  entry != &map->header;
  894             entry = entry->next) {
  895                 vm_object_t obj;
  896 
  897                 /*
  898                  * Don't dump inaccessible mappings, deal with legacy
  899                  * coredump mode.
  900                  *
  901                  * Note that read-only segments related to the elf binary
  902                  * are marked MAP_ENTRY_NOCOREDUMP now so we no longer
  903                  * need to arbitrarily ignore such segments.
  904                  */
  905                 if (elf_legacy_coredump) {
  906                         if ((entry->protection & VM_PROT_RW) != VM_PROT_RW)
  907                                 continue;
  908                 } else {
  909                         if ((entry->protection & VM_PROT_ALL) == 0)
  910                                 continue;
  911                 }
  912 
  913                 /*
  914                  * Dont include memory segment in the coredump if
  915                  * MAP_NOCORE is set in mmap(2) or MADV_NOCORE in
  916                  * madvise(2).  Do not dump submaps (i.e. parts of the
  917                  * kernel map).
  918                  */
  919                 if (entry->eflags & (MAP_ENTRY_NOCOREDUMP|MAP_ENTRY_IS_SUB_MAP))
  920                         continue;
  921 
  922                 if ((obj = entry->object.vm_object) == NULL)
  923                         continue;
  924 
  925                 /* Find the deepest backing object. */
  926                 while (obj->backing_object != NULL)
  927                         obj = obj->backing_object;
  928 
  929                 /* Ignore memory-mapped devices and such things. */
  930                 if (obj->type != OBJT_DEFAULT &&
  931                     obj->type != OBJT_SWAP &&
  932                     obj->type != OBJT_VNODE)
  933                         continue;
  934 
  935                 (*func)(entry, closure);
  936         }
  937 }
  938 
  939 /*
  940  * Write the core file header to the file, including padding up to
  941  * the page boundary.
  942  */
  943 static int
  944 elf_corehdr(p, vp, cred, numsegs, hdr, hdrsize)
  945         struct proc *p;
  946         struct vnode *vp;
  947         struct ucred *cred;
  948         int numsegs;
  949         size_t hdrsize;
  950         void *hdr;
  951 {
  952         struct {
  953                 prstatus_t status;
  954                 prfpregset_t fpregset;
  955                 prpsinfo_t psinfo;
  956         } *tempdata;
  957         size_t off;
  958         prstatus_t *status;
  959         prfpregset_t *fpregset;
  960         prpsinfo_t *psinfo;
  961 
  962         tempdata = malloc(sizeof(*tempdata), M_TEMP, M_ZERO | M_WAITOK);
  963         status = &tempdata->status;
  964         fpregset = &tempdata->fpregset;
  965         psinfo = &tempdata->psinfo;
  966 
  967         /* Gather the information for the header. */
  968         status->pr_version = PRSTATUS_VERSION;
  969         status->pr_statussz = sizeof(prstatus_t);
  970         status->pr_gregsetsz = sizeof(gregset_t);
  971         status->pr_fpregsetsz = sizeof(fpregset_t);
  972         status->pr_osreldate = osreldate;
  973         status->pr_cursig = p->p_sig;
  974         status->pr_pid = p->p_pid;
  975         fill_regs(p, &status->pr_reg);
  976 
  977         fill_fpregs(p, fpregset);
  978 
  979         psinfo->pr_version = PRPSINFO_VERSION;
  980         psinfo->pr_psinfosz = sizeof(prpsinfo_t);
  981         strncpy(psinfo->pr_fname, p->p_comm, sizeof(psinfo->pr_fname) - 1);
  982 
  983         /* XXX - We don't fill in the command line arguments properly yet. */
  984         strncpy(psinfo->pr_psargs, p->p_comm, PRARGSZ);
  985 
  986         /* Fill in the header. */
  987         bzero(hdr, hdrsize);
  988         off = 0;
  989         elf_puthdr(p, hdr, &off, status, fpregset, psinfo, numsegs);
  990 
  991         free(tempdata, M_TEMP);
  992 
  993         /* Write it to the core file. */
  994         return vn_rdwr_inchunks(UIO_WRITE, vp, hdr, hdrsize, (off_t)0,
  995             UIO_SYSSPACE, IO_UNIT | IO_DIRECT, cred, NULL, p);
  996 }
  997 
  998 static void
  999 elf_puthdr(struct proc *p, void *dst, size_t *off, const prstatus_t *status,
 1000     const prfpregset_t *fpregset, const prpsinfo_t *psinfo, int numsegs)
 1001 {
 1002         size_t ehoff;
 1003         size_t phoff;
 1004         size_t noteoff;
 1005         size_t notesz;
 1006 
 1007         ehoff = *off;
 1008         *off += sizeof(Elf_Ehdr);
 1009 
 1010         phoff = *off;
 1011         *off += (numsegs + 1) * sizeof(Elf_Phdr);
 1012 
 1013         noteoff = *off;
 1014         elf_putnote(dst, off, "FreeBSD", NT_PRSTATUS, status,
 1015             sizeof *status);
 1016         elf_putnote(dst, off, "FreeBSD", NT_FPREGSET, fpregset,
 1017             sizeof *fpregset);
 1018         elf_putnote(dst, off, "FreeBSD", NT_PRPSINFO, psinfo,
 1019             sizeof *psinfo);
 1020         notesz = *off - noteoff;
 1021 
 1022         /* Align up to a page boundary for the program segments. */
 1023         *off = round_page(*off);
 1024 
 1025         if (dst != NULL) {
 1026                 Elf_Ehdr *ehdr;
 1027                 Elf_Phdr *phdr;
 1028                 struct phdr_closure phc;
 1029 
 1030                 /*
 1031                  * Fill in the ELF header.
 1032                  */
 1033                 ehdr = (Elf_Ehdr *)((char *)dst + ehoff);
 1034                 ehdr->e_ident[EI_MAG0] = ELFMAG0;
 1035                 ehdr->e_ident[EI_MAG1] = ELFMAG1;
 1036                 ehdr->e_ident[EI_MAG2] = ELFMAG2;
 1037                 ehdr->e_ident[EI_MAG3] = ELFMAG3;
 1038                 ehdr->e_ident[EI_CLASS] = ELF_CLASS;
 1039                 ehdr->e_ident[EI_DATA] = ELF_DATA;
 1040                 ehdr->e_ident[EI_VERSION] = EV_CURRENT;
 1041                 ehdr->e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
 1042                 ehdr->e_ident[EI_ABIVERSION] = 0;
 1043                 ehdr->e_ident[EI_PAD] = 0;
 1044                 ehdr->e_type = ET_CORE;
 1045                 ehdr->e_machine = ELF_ARCH;
 1046                 ehdr->e_version = EV_CURRENT;
 1047                 ehdr->e_entry = 0;
 1048                 ehdr->e_phoff = phoff;
 1049                 ehdr->e_flags = 0;
 1050                 ehdr->e_ehsize = sizeof(Elf_Ehdr);
 1051                 ehdr->e_phentsize = sizeof(Elf_Phdr);
 1052                 ehdr->e_phnum = numsegs + 1;
 1053                 ehdr->e_shentsize = sizeof(Elf_Shdr);
 1054                 ehdr->e_shnum = 0;
 1055                 ehdr->e_shstrndx = SHN_UNDEF;
 1056 
 1057                 /*
 1058                  * Fill in the program header entries.
 1059                  */
 1060                 phdr = (Elf_Phdr *)((char *)dst + phoff);
 1061 
 1062                 /* The note segement. */
 1063                 phdr->p_type = PT_NOTE;
 1064                 phdr->p_offset = noteoff;
 1065                 phdr->p_vaddr = 0;
 1066                 phdr->p_paddr = 0;
 1067                 phdr->p_filesz = notesz;
 1068                 phdr->p_memsz = 0;
 1069                 phdr->p_flags = 0;
 1070                 phdr->p_align = 0;
 1071                 phdr++;
 1072 
 1073                 /* All the writable segments from the program. */
 1074                 phc.phdr = phdr;
 1075                 phc.offset = *off;
 1076                 each_writable_segment(p, cb_put_phdr, &phc);
 1077         }
 1078 }
 1079 
 1080 static void
 1081 elf_putnote(void *dst, size_t *off, const char *name, int type,
 1082     const void *desc, size_t descsz)
 1083 {
 1084         Elf_Note note;
 1085 
 1086         note.n_namesz = strlen(name) + 1;
 1087         note.n_descsz = descsz;
 1088         note.n_type = type;
 1089         if (dst != NULL)
 1090                 bcopy(&note, (char *)dst + *off, sizeof note);
 1091         *off += sizeof note;
 1092         if (dst != NULL)
 1093                 bcopy(name, (char *)dst + *off, note.n_namesz);
 1094         *off += roundup2(note.n_namesz, sizeof(Elf_Size));
 1095         if (dst != NULL)
 1096                 bcopy(desc, (char *)dst + *off, note.n_descsz);
 1097         *off += roundup2(note.n_descsz, sizeof(Elf_Size));
 1098 }
 1099 
 1100 /*
 1101  * Tell kern_execve.c about it, with a little help from the linker.
 1102  */
 1103 static struct execsw elf_execsw = {exec_elf_imgact, "ELF"};
 1104 EXEC_SET(elf, elf_execsw);

Cache object: ce5541c3c7ea533c263e3bd41c424815


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