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/compat/linux/common/linux_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: linux_exec_elf32.c,v 1.81 2008/04/28 20:23:43 martin Exp $     */
    2 
    3 /*-
    4  * Copyright (c) 1995, 1998, 2000, 2001 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, Frank van der Linden, Eric Haszlakiewicz and
    9  * Emmanuel Dreyfus.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   30  * POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33 /*
   34  * based on exec_aout.c, sunos_exec.c and svr4_exec.c
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __KERNEL_RCSID(0, "$NetBSD: linux_exec_elf32.c,v 1.81 2008/04/28 20:23:43 martin Exp $");
   39 
   40 #ifndef ELFSIZE
   41 /* XXX should die */
   42 #define ELFSIZE         32
   43 #endif
   44 
   45 #include <sys/param.h>
   46 #include <sys/systm.h>
   47 #include <sys/kernel.h>
   48 #include <sys/proc.h>
   49 #include <sys/malloc.h>
   50 #include <sys/namei.h>
   51 #include <sys/vnode.h>
   52 #include <sys/mount.h>
   53 #include <sys/exec.h>
   54 #include <sys/exec_elf.h>
   55 #include <sys/stat.h>
   56 #include <sys/kauth.h>
   57 
   58 #include <sys/mman.h>
   59 #include <sys/syscallargs.h>
   60 
   61 #include <sys/cpu.h>
   62 #include <machine/reg.h>
   63 
   64 #include <compat/linux/common/linux_types.h>
   65 #include <compat/linux/common/linux_signal.h>
   66 #include <compat/linux/common/linux_util.h>
   67 #include <compat/linux/common/linux_exec.h>
   68 #include <compat/linux/common/linux_machdep.h>
   69 
   70 #include <compat/linux/linux_syscallargs.h>
   71 #include <compat/linux/linux_syscall.h>
   72 
   73 #ifdef DEBUG_LINUX
   74 #define DPRINTF(a)      uprintf a
   75 #else
   76 #define DPRINTF(a)
   77 #endif
   78 
   79 #ifdef LINUX_ATEXIT_SIGNATURE
   80 /*
   81  * On the PowerPC, statically linked Linux binaries are not recognized
   82  * by linux_signature nor by linux_gcc_signature. Fortunately, thoses
   83  * binaries features a __libc_atexit ELF section. We therefore assume we
   84  * have a Linux binary if we find this section.
   85  */
   86 int
   87 ELFNAME2(linux,atexit_signature)(l, epp, eh)
   88         struct lwp *l;
   89         struct exec_package *epp;
   90         Elf_Ehdr *eh;
   91 {
   92         size_t shsize;
   93         int strndx;
   94         size_t i;
   95         static const char signature[] = "__libc_atexit";
   96         char *strtable = NULL;
   97         Elf_Shdr *sh;
   98 
   99         int error;
  100 
  101         /*
  102          * load the section header table
  103          */
  104         shsize = eh->e_shnum * sizeof(Elf_Shdr);
  105         sh = (Elf_Shdr *) malloc(shsize, M_TEMP, M_WAITOK);
  106         error = exec_read_from(l, epp->ep_vp, eh->e_shoff, sh, shsize);
  107         if (error)
  108                 goto out;
  109 
  110         /*
  111          * Now let's find the string table. If it does not exists, give up.
  112          */
  113         strndx = (int)(eh->e_shstrndx);
  114         if (strndx == SHN_UNDEF) {
  115                 error = ENOEXEC;
  116                 goto out;
  117         }
  118 
  119         /*
  120          * strndx is the index in section header table of the string table
  121          * section get the whole string table in strtable, and then we get access to the names
  122          * s->sh_name is the offset of the section name in strtable.
  123          */
  124         strtable = malloc(sh[strndx].sh_size, M_TEMP, M_WAITOK);
  125         error = exec_read_from(l, epp->ep_vp, sh[strndx].sh_offset, strtable,
  126             sh[strndx].sh_size);
  127         if (error)
  128                 goto out;
  129 
  130         for (i = 0; i < eh->e_shnum; i++) {
  131                 Elf_Shdr *s = &sh[i];
  132                 if (!memcmp((void*)(&(strtable[s->sh_name])), signature,
  133                                 sizeof(signature))) {
  134                         DPRINTF(("linux_atexit_sig=%s\n",
  135                             &(strtable[s->sh_name])));
  136                         error = 0;
  137                         goto out;
  138                 }
  139         }
  140         error = ENOEXEC;
  141 
  142 out:
  143         free(sh, M_TEMP);
  144         if (strtable)
  145                 free(strtable, M_TEMP);
  146         return (error);
  147 }
  148 #endif
  149 
  150 #ifdef LINUX_GCC_SIGNATURE
  151 /*
  152  * Take advantage of the fact that all the linux binaries are compiled
  153  * with gcc, and gcc sticks in the comment field a signature. Note that
  154  * on SVR4 binaries, the gcc signature will follow the OS name signature,
  155  * that will not be a problem. We don't bother to read in the string table,
  156  * but we check all the progbits headers.
  157  *
  158  * XXX This only works in the i386.  On the alpha (at least)
  159  * XXX we have the same gcc signature which incorrectly identifies
  160  * XXX NetBSD binaries as Linux.
  161  */
  162 int
  163 ELFNAME2(linux,gcc_signature)(l, epp, eh)
  164         struct lwp *l;
  165         struct exec_package *epp;
  166         Elf_Ehdr *eh;
  167 {
  168         size_t shsize;
  169         size_t i;
  170         static const char signature[] = "\0GCC: (GNU) ";
  171         char tbuf[sizeof(signature) - 1];
  172         Elf_Shdr *sh;
  173         int error;
  174 
  175         shsize = eh->e_shnum * sizeof(Elf_Shdr);
  176         sh = (Elf_Shdr *) malloc(shsize, M_TEMP, M_WAITOK);
  177         error = exec_read_from(l, epp->ep_vp, eh->e_shoff, sh, shsize);
  178         if (error)
  179                 goto out;
  180 
  181         for (i = 0; i < eh->e_shnum; i++) {
  182                 Elf_Shdr *s = &sh[i];
  183 
  184                 /*
  185                  * Identify candidates for the comment header;
  186                  * Header cannot have a load address, or flags and
  187                  * it must be large enough.
  188                  */
  189                 if (s->sh_type != SHT_PROGBITS ||
  190                     s->sh_addr != 0 ||
  191                     s->sh_flags != 0 ||
  192                     s->sh_size < sizeof(signature) - 1)
  193                         continue;
  194 
  195                 error = exec_read_from(l, epp->ep_vp, s->sh_offset, tbuf,
  196                     sizeof(signature) - 1);
  197                 if (error)
  198                         continue;
  199 
  200                 /*
  201                  * error is 0, if the signatures match we are done.
  202                  */
  203                 DPRINTF(("linux_gcc_sig: sig=%s\n", tbuf));
  204                 if (!memcmp(tbuf, signature, sizeof(signature) - 1)) {
  205                         error = 0;
  206                         goto out;
  207                 }
  208         }
  209         error = ENOEXEC;
  210 
  211 out:
  212         free(sh, M_TEMP);
  213         return (error);
  214 }
  215 #endif
  216 
  217 #ifdef LINUX_DEBUGLINK_SIGNATURE
  218 /*
  219  * Look for a .gnu_debuglink, specific to x86_64 interpeter
  220  */
  221 int
  222 ELFNAME2(linux,debuglink_signature)(l, epp, eh)
  223         struct lwp *l;
  224         struct exec_package *epp;
  225         Elf_Ehdr *eh;
  226 {
  227         size_t shsize;
  228         int strndx;
  229         size_t i;
  230         static const char signature[] = ".gnu_debuglink";
  231         char *strtable = NULL;
  232         Elf_Shdr *sh;
  233 
  234         int error;
  235 
  236         /*
  237          * load the section header table
  238          */
  239         shsize = eh->e_shnum * sizeof(Elf_Shdr);
  240         sh = (Elf_Shdr *) malloc(shsize, M_TEMP, M_WAITOK);
  241         error = exec_read_from(l, epp->ep_vp, eh->e_shoff, sh, shsize);
  242         if (error)
  243                 goto out;
  244 
  245         /*
  246          * Now let's find the string table. If it does not exists, give up.
  247          */
  248         strndx = (int)(eh->e_shstrndx);
  249         if (strndx == SHN_UNDEF) {
  250                 error = ENOEXEC;
  251                 goto out;
  252         }
  253 
  254         /*
  255          * strndx is the index in section header table of the string table
  256          * section get the whole string table in strtable, and then we get access to the names
  257          * s->sh_name is the offset of the section name in strtable.
  258          */
  259         strtable = malloc(sh[strndx].sh_size, M_TEMP, M_WAITOK);
  260         error = exec_read_from(l, epp->ep_vp, sh[strndx].sh_offset, strtable,
  261             sh[strndx].sh_size);
  262         if (error)
  263                 goto out;
  264 
  265         for (i = 0; i < eh->e_shnum; i++) {
  266                 Elf_Shdr *s = &sh[i];
  267 
  268                 if (!memcmp((void*)(&(strtable[s->sh_name])), signature,
  269                                 sizeof(signature))) {
  270                         DPRINTF(("linux_debuglink_sig=%s\n",
  271                             &(strtable[s->sh_name])));
  272                         error = 0;
  273                         goto out;
  274                 }
  275         }
  276         error = ENOEXEC;
  277 
  278 out:
  279         free(sh, M_TEMP);
  280         if (strtable)
  281                 free(strtable, M_TEMP);
  282         return (error);
  283 }
  284 #endif
  285 
  286 int
  287 ELFNAME2(linux,signature)(l, epp, eh, itp)
  288         struct lwp *l;
  289         struct exec_package *epp;
  290         Elf_Ehdr *eh;
  291         char *itp;
  292 {
  293         size_t i;
  294         Elf_Phdr *ph;
  295         size_t phsize;
  296         int error;
  297         static const char linux[] = "Linux";
  298 
  299         if (eh->e_ident[EI_OSABI] == 3 ||
  300             memcmp(&eh->e_ident[EI_ABIVERSION], linux, sizeof(linux)) == 0)
  301                 return 0;
  302 
  303         phsize = eh->e_phnum * sizeof(Elf_Phdr);
  304         ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);
  305         error = exec_read_from(l, epp->ep_vp, eh->e_phoff, ph, phsize);
  306         if (error)
  307                 goto out;
  308 
  309         for (i = 0; i < eh->e_phnum; i++) {
  310                 Elf_Phdr *ephp = &ph[i];
  311                 Elf_Nhdr *np;
  312                 u_int32_t *abi;
  313 
  314                 if (ephp->p_type != PT_NOTE ||
  315                     ephp->p_filesz > 1024 ||
  316                     ephp->p_filesz < sizeof(Elf_Nhdr) + 20)
  317                         continue;
  318 
  319                 np = (Elf_Nhdr *)malloc(ephp->p_filesz, M_TEMP, M_WAITOK);
  320                 error = exec_read_from(l, epp->ep_vp, ephp->p_offset, np,
  321                     ephp->p_filesz);
  322                 if (error)
  323                         goto next;
  324 
  325                 if (np->n_type != ELF_NOTE_TYPE_ABI_TAG ||
  326                     np->n_namesz != ELF_NOTE_ABI_NAMESZ ||
  327                     np->n_descsz != ELF_NOTE_ABI_DESCSZ ||
  328                     memcmp((void *)(np + 1), ELF_NOTE_ABI_NAME,
  329                     ELF_NOTE_ABI_NAMESZ))
  330                         goto next;
  331 
  332                 /* Make sure the OS is Linux. */
  333                 abi = (u_int32_t *)((char *)np + sizeof(Elf_Nhdr) +
  334                     np->n_namesz);
  335                 if (abi[0] == ELF_NOTE_ABI_OS_LINUX)
  336                         error = 0;
  337                 else
  338                         error = ENOEXEC;
  339                 free(np, M_TEMP);
  340                 goto out;
  341 
  342         next:
  343                 free(np, M_TEMP);
  344                 continue;
  345         }
  346 
  347         /* Check for certain intepreter names. */
  348         if (itp) {
  349                 if (!strncmp(itp, "/lib/ld-linux", 13) ||
  350 #if (ELFSIZE == 64)
  351                     !strncmp(itp, "/lib64/ld-linux", 15) ||
  352 #endif
  353                     !strncmp(itp, "/lib/ld.so.", 11))
  354                         error = 0;
  355                 else
  356                         error = ENOEXEC;
  357                 goto out;
  358         }
  359 
  360         error = ENOEXEC;
  361 out:
  362         free(ph, M_TEMP);
  363         return (error);
  364 }
  365 
  366 int
  367 ELFNAME2(linux,probe)(struct lwp *l, struct exec_package *epp, void *eh,
  368     char *itp, vaddr_t *pos)
  369 {
  370         int error;
  371 
  372         if (((error = ELFNAME2(linux,signature)(l, epp, eh, itp)) != 0) &&
  373 #ifdef LINUX_GCC_SIGNATURE
  374             ((error = ELFNAME2(linux,gcc_signature)(l, epp, eh)) != 0) &&
  375 #endif
  376 #ifdef LINUX_ATEXIT_SIGNATURE
  377             ((error = ELFNAME2(linux,atexit_signature)(l, epp, eh)) != 0) &&
  378 #endif
  379 #ifdef LINUX_DEBUGLINK_SIGNATURE
  380             ((error = ELFNAME2(linux,debuglink_signature)(l, epp, eh)) != 0) &&
  381 #endif
  382             1) {
  383                         DPRINTF(("linux_probe: returning %d\n", error));
  384                         return error;
  385         }
  386 
  387         if (itp) {
  388                 if ((error = emul_find_interp(l, epp, itp)))
  389                         return (error);
  390         }
  391         DPRINTF(("linux_probe: returning 0\n"));
  392         return 0;
  393 }
  394 
  395 #ifndef LINUX_MACHDEP_ELF_COPYARGS
  396 /*
  397  * Copy arguments onto the stack in the normal way, but add some
  398  * extra information in case of dynamic binding.
  399  */
  400 int
  401 ELFNAME2(linux,copyargs)(struct lwp *l, struct exec_package *pack,
  402     struct ps_strings *arginfo, char **stackp, void *argp)
  403 {
  404         size_t len;
  405         AuxInfo ai[LINUX_ELF_AUX_ENTRIES], *a;
  406         struct elf_args *ap;
  407         int error;
  408         struct vattr *vap;
  409 
  410         if ((error = copyargs(l, pack, arginfo, stackp, argp)) != 0)
  411                 return error;
  412 
  413         a = ai;
  414 
  415         /*
  416          * Push extra arguments used by glibc on the stack.
  417          */
  418 
  419         a->a_type = AT_PAGESZ;
  420         a->a_v = PAGE_SIZE;
  421         a++;
  422 
  423         if ((ap = (struct elf_args *)pack->ep_emul_arg)) {
  424 
  425                 a->a_type = AT_PHDR;
  426                 a->a_v = ap->arg_phaddr;
  427                 a++;
  428 
  429                 a->a_type = AT_PHENT;
  430                 a->a_v = ap->arg_phentsize;
  431                 a++;
  432 
  433                 a->a_type = AT_PHNUM;
  434                 a->a_v = ap->arg_phnum;
  435                 a++;
  436 
  437                 a->a_type = AT_BASE;
  438                 a->a_v = ap->arg_interp;
  439                 a++;
  440 
  441                 a->a_type = AT_FLAGS;
  442                 a->a_v = 0;
  443                 a++;
  444 
  445                 a->a_type = AT_ENTRY;
  446                 a->a_v = ap->arg_entry;
  447                 a++;
  448 
  449                 free(pack->ep_emul_arg, M_TEMP);
  450                 pack->ep_emul_arg = NULL;
  451         }
  452 
  453         /* Linux-specific items */
  454         a->a_type = LINUX_AT_CLKTCK;
  455         a->a_v = hz;
  456         a++;
  457 
  458         vap = pack->ep_vap;
  459 
  460         a->a_type = LINUX_AT_UID;
  461         a->a_v = kauth_cred_getuid(l->l_cred);
  462         a++;
  463 
  464         a->a_type = LINUX_AT_EUID;
  465         if (vap->va_mode & S_ISUID)
  466                 a->a_v = vap->va_uid;
  467         else
  468                 a->a_v = kauth_cred_geteuid(l->l_cred);
  469         a++;
  470 
  471         a->a_type = LINUX_AT_GID;
  472         a->a_v = kauth_cred_getgid(l->l_cred);
  473         a++;
  474 
  475         a->a_type = LINUX_AT_EGID;
  476         if (vap->va_mode & S_ISGID)
  477                 a->a_v = vap->va_gid;
  478         else
  479                 a->a_v = kauth_cred_getegid(l->l_cred);
  480         a++;
  481 
  482         a->a_type = AT_NULL;
  483         a->a_v = 0;
  484         a++;
  485 
  486         len = (a - ai) * sizeof(AuxInfo);
  487         if ((error = copyout(ai, *stackp, len)) != 0)
  488                 return error;
  489         *stackp += len;
  490 
  491         return 0;
  492 }
  493 #endif /* !LINUX_MACHDEP_ELF_COPYARGS */

Cache object: 3b8b795c4be5905c140eed24e07b3623


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