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


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

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

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

    1 /*      $NetBSD: exec_macho.c,v 1.42 2008/04/28 20:24:02 martin Exp $   */
    2 
    3 /*-
    4  * Copyright (c) 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.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __KERNEL_RCSID(0, "$NetBSD: exec_macho.c,v 1.42 2008/04/28 20:24:02 martin Exp $");
   34 
   35 #include <sys/param.h>
   36 #include <sys/proc.h>
   37 #include <sys/malloc.h>
   38 #include <sys/namei.h>
   39 #include <sys/vnode.h>
   40 #include <sys/exec.h>
   41 #include <sys/exec_macho.h>
   42 #include <sys/syscall.h>
   43 #include <sys/signalvar.h>
   44 #include <sys/resourcevar.h>
   45 #include <sys/mount.h>
   46 #include <sys/stat.h>
   47 
   48 #include <uvm/uvm.h>
   49 
   50 #ifdef DEBUG_MACHO
   51 #define DPRINTF(a) printf a
   52 #else
   53 #define DPRINTF(a)
   54 #endif
   55 
   56 static int exec_macho_load_segment(struct exec_package *, struct vnode *,
   57     u_long, struct exec_macho_segment_command *, int);
   58 static int exec_macho_load_dylinker(struct lwp *, struct exec_package *,
   59     struct exec_macho_dylinker_command *, u_long *, int);
   60 static int exec_macho_load_dylib(struct lwp *, struct exec_package *,
   61     struct exec_macho_dylib_command *, int);
   62 static u_long exec_macho_load_thread(struct exec_macho_thread_command *);
   63 static int exec_macho_load_file(struct lwp *, struct exec_package *,
   64     const char *, u_long *, int, int, int);
   65 static int exec_macho_load_vnode(struct lwp *, struct exec_package *,
   66     struct vnode *, struct exec_macho_fat_header *, u_long *, int, int, int);
   67 
   68 #ifdef DEBUG_MACHO
   69 static void
   70 exec_macho_print_segment_command(struct exec_macho_segment_command *ls)
   71 {
   72         printf("ls.cmd 0x%lx\n", ls->cmd);
   73         printf("ls.cmdsize 0x%ld\n", ls->cmdsize);
   74         printf("ls.segname %s\n", ls->segname);
   75         printf("ls.vmaddr 0x%lx\n", ls->vmaddr);
   76         printf("ls.vmsize %ld\n", ls->vmsize);
   77         printf("ls.fileoff 0x%lx\n", ls->fileoff);
   78         printf("ls.filesize %ld\n", ls->filesize);
   79         printf("ls.maxprot 0x%x\n", ls->maxprot);
   80         printf("ls.initprot 0x%x\n", ls->initprot);
   81         printf("ls.nsects %ld\n", ls->nsects);
   82         printf("ls.flags 0x%lx\n", ls->flags);
   83 }
   84 
   85 static void
   86 exec_macho_print_fat_header(struct exec_macho_fat_header *fat)
   87 {
   88         printf("fat.magic 0x%x\n", be32toh(fat->magic));
   89         printf("fat.nfat_arch %d\n", be32toh(fat->nfat_arch));
   90 }
   91 
   92 static void
   93 exec_macho_print_fat_arch(struct exec_macho_fat_arch *arch)
   94 {
   95         printf("arch.cputype %x\n", be32toh(arch->cputype));
   96         printf("arch.cpusubtype %d\n", be32toh(arch->cpusubtype));
   97         printf("arch.offset 0x%x\n", (int32_t)be32toh(arch->offset));
   98         printf("arch.size %d\n", (int32_t)be32toh(arch->size));
   99         printf("arch.align 0x%x\n", (int32_t)be32toh(arch->align));
  100 }
  101 
  102 static void
  103 exec_macho_print_object_header(struct exec_macho_object_header *hdr)
  104 {
  105         printf("hdr.magic 0x%lx\n", hdr->magic);
  106         printf("hdr.cputype %x\n", hdr->cputype);
  107         printf("hdr.cpusubtype %d\n", hdr->cpusubtype);
  108         printf("hdr.filetype 0x%lx\n", hdr->filetype);
  109         printf("hdr.ncmds %ld\n", hdr->ncmds);
  110         printf("hdr.sizeofcmds %ld\n", hdr->sizeofcmds);
  111         printf("hdr.flags 0x%lx\n", hdr->flags);
  112 }
  113 
  114 static void
  115 exec_macho_print_load_command(struct exec_macho_load_command *lc)
  116 {
  117         printf("lc.cmd %lx\n", lc->cmd);
  118         printf("lc.cmdsize %ld\n", lc->cmdsize);
  119 }
  120 
  121 static void
  122 exec_macho_print_dylinker_command(struct exec_macho_dylinker_command *dy)
  123 {
  124         printf("dy.cmd %lx\n", dy->cmd);
  125         printf("dy.cmdsize %ld\n", dy->cmdsize);
  126         printf("dy.name.offset 0x%lx\n", dy->name.offset);
  127         printf("dy.name %s\n", ((char *)dy) + dy->name.offset);
  128 }
  129 
  130 static void
  131 exec_macho_print_dylib_command(struct exec_macho_dylib_command *dy)
  132 {
  133         printf("dy.cmd %lx\n", dy->cmd);
  134         printf("dy.cmdsize %ld\n", dy->cmdsize);
  135         printf("dy.dylib.name.offset 0x%lx\n", dy->dylib.name.offset);
  136         printf("dy.dylib.name %s\n", ((char *)dy) + dy->dylib.name.offset);
  137         printf("dy.dylib.timestamp %ld\n", dy->dylib.timestamp);
  138         printf("dy.dylib.current_version %ld\n", dy->dylib.current_version);
  139         printf("dy.dylib.compatibility_version %ld\n",
  140             dy->dylib.compatibility_version);
  141 }
  142 
  143 static void
  144 exec_macho_print_thread_command(struct exec_macho_thread_command *th)
  145 {
  146         printf("th.cmd %lx\n", th->cmd);
  147         printf("th.cmdsize %ld\n", th->cmdsize);
  148         printf("th.flavor %ld\n", th->flavor);
  149         printf("th.count %ld\n", th->count);
  150 }
  151 #endif /* DEBUG_MACHO */
  152 
  153 static int
  154 exec_macho_load_segment(struct exec_package *epp, struct vnode *vp,
  155     u_long foff, struct exec_macho_segment_command *ls, int type)
  156 {
  157         int flags;
  158         struct exec_macho_emul_arg *emea;
  159         u_long addr = trunc_page(ls->vmaddr), size = round_page(ls->filesize);
  160 
  161         emea = (struct exec_macho_emul_arg *)epp->ep_emul_arg;
  162 
  163         flags = VMCMD_BASE;
  164 
  165 #ifdef DEBUG_MACHO
  166         exec_macho_print_segment_command(ls);
  167 #endif
  168         if (strcmp(ls->segname, "__PAGEZERO") == 0)
  169                 return 0;
  170 
  171         if (strcmp(ls->segname, "__TEXT") != 0 &&
  172             strcmp(ls->segname, "__DATA") != 0 &&
  173             strcmp(ls->segname, "__LOCK") != 0 &&
  174             strcmp(ls->segname, "__OBJC") != 0 &&
  175             strcmp(ls->segname, "__CGSERVER") != 0 &&
  176             strcmp(ls->segname, "__IMAGE") != 0 &&
  177             strcmp(ls->segname, "__LINKEDIT") != 0) {
  178                 DPRINTF(("Unknown exec_macho segment %s\n", ls->segname));
  179                 return ENOEXEC;
  180         }
  181         if (type == MACHO_MOH_EXECUTE) {
  182                 if (strcmp(ls->segname, "__TEXT") == 0) {
  183                         epp->ep_taddr = addr;
  184                         epp->ep_tsize = round_page(ls->vmsize);
  185                         emea->macho_hdr =
  186                             (struct exec_macho_object_header *)addr;
  187                 }
  188                 if ((strcmp(ls->segname, "__DATA") == 0) ||
  189                     (strcmp(ls->segname, "__OBJC") == 0) ||
  190                     (strcmp(ls->segname, "__IMAGE") == 0) ||
  191                     (strcmp(ls->segname, "__CGSERVER") == 0)) {
  192                         epp->ep_daddr = addr;
  193                         epp->ep_dsize = round_page(ls->vmsize);
  194                 }
  195         }
  196 
  197         /*
  198          * Some libraries do not have a load base address. The Darwin
  199          * kernel seems to skip them, and dyld will do the job.
  200          */
  201         if (addr == 0)
  202                 return ENOMEM;
  203 
  204         if (ls->filesize > 0) {
  205                 NEW_VMCMD2(&epp->ep_vmcmds, vmcmd_map_pagedvn, size,
  206                     addr, vp, (off_t)(ls->fileoff + foff),
  207                     ls->initprot, flags);
  208                 DPRINTF(("map(0x%lx, 0x%lx, %o, fd@ 0x%lx)\n",
  209                     addr, size, ls->initprot,
  210                     ls->fileoff + foff));
  211         }
  212 
  213         if (ls->vmsize > size) {
  214                 addr += size;
  215                 size = round_page(ls->vmsize - size);
  216                 NEW_VMCMD2(&epp->ep_vmcmds, vmcmd_map_zero, size,
  217                     addr, vp, (off_t)(ls->fileoff + foff),
  218                     ls->initprot, flags);
  219                 DPRINTF(("mmap(0x%lx, 0x%lx, %o, zero)\n",
  220                     ls->vmaddr + ls->filesize, ls->vmsize - ls->filesize,
  221                     ls->initprot));
  222         }
  223         return 0;
  224 }
  225 
  226 
  227 static int
  228 exec_macho_load_dylinker(struct lwp *l, struct exec_package *epp,
  229     struct exec_macho_dylinker_command *dy, u_long *entry, int depth)
  230 {
  231         struct exec_macho_emul_arg *emea;
  232         const char *name = ((const char *)dy) + dy->name.offset;
  233         char path[MAXPATHLEN];
  234         int error;
  235 #ifdef DEBUG_MACHO
  236         exec_macho_print_dylinker_command(dy);
  237 #endif
  238         emea = (struct exec_macho_emul_arg *)epp->ep_emul_arg;
  239 
  240         (void)snprintf(path, sizeof(path), "%s%s", emea->path, name);
  241         DPRINTF(("loading linker %s\n", path));
  242         if ((error = exec_macho_load_file(l, epp, path, entry,
  243             MACHO_MOH_DYLINKER, 1, depth)) != 0)
  244                 return error;
  245         return 0;
  246 }
  247 
  248 static int
  249 exec_macho_load_dylib(struct lwp *l, struct exec_package *epp,
  250     struct exec_macho_dylib_command *dy, int depth)
  251 {
  252         struct exec_macho_emul_arg *emea;
  253         const char *name = ((const char *)dy) + dy->dylib.name.offset;
  254         char path[MAXPATHLEN];
  255         int error;
  256         u_long entry;
  257 #ifdef DEBUG_MACHO
  258         exec_macho_print_dylib_command(dy);
  259 #endif
  260         emea = (struct exec_macho_emul_arg *)epp->ep_emul_arg;
  261         (void)snprintf(path, sizeof(path), "%s%s", emea->path, name);
  262         DPRINTF(("loading library %s\n", path));
  263         if ((error = exec_macho_load_file(l, epp, path, &entry,
  264             MACHO_MOH_DYLIB, 0, depth)) != 0)
  265                 return error;
  266         return 0;
  267 }
  268 
  269 static u_long
  270 exec_macho_load_thread(struct exec_macho_thread_command *th)
  271 {
  272 #ifdef DEBUG_MACHO
  273         exec_macho_print_thread_command(th);
  274 #endif
  275         return exec_macho_thread_entry(th);
  276 }
  277 
  278 /*
  279  * exec_macho_load_file(): Load a macho-binary. This is used
  280  * for the dynamic linker and library recursive loading.
  281  */
  282 static int
  283 exec_macho_load_file(struct lwp *l, struct exec_package *epp,
  284     const char *path, u_long *entry, int type, int recursive, int depth)
  285 {
  286         int error;
  287         struct nameidata nd;
  288         struct vnode *vp;
  289         struct vattr attr;
  290         struct exec_macho_fat_header fat;
  291 
  292         /*
  293          * Check for excessive rercursive loading
  294          */
  295         if (depth++ > 6)
  296                 return E2BIG;
  297 
  298         /*
  299          * 1. open file
  300          * 2. read filehdr
  301          * 3. map text, data, and bss out of it using VM_*
  302          */
  303         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path);
  304         if ((error = namei(&nd)) != 0)
  305                 return error;
  306         vp = nd.ni_vp;
  307 
  308         /*
  309          * Similarly, if it's not marked as executable, or it's not a regular
  310          * file, we don't allow it to be used.
  311          */
  312         if (vp->v_type != VREG) {
  313                 error = EACCES;
  314                 goto badunlock;
  315         }
  316 
  317         error = vn_marktext(vp);
  318         if (error)
  319                 return (error);
  320 
  321         if ((error = VOP_ACCESS(vp, VEXEC, l->l_cred)) != 0)
  322                 goto badunlock;
  323 
  324         /* get attributes */
  325         if ((error = VOP_GETATTR(vp, &attr, l->l_cred)) != 0)
  326                 goto badunlock;
  327 
  328 #ifdef notyet /* XXX cgd 960926 */
  329         XXX cgd 960926: (maybe) VOP_OPEN it (and VOP_CLOSE in copyargs?)
  330 #endif
  331         VOP_UNLOCK(vp, 0);
  332 
  333         if ((error = exec_read_from(l, vp, 0, &fat, sizeof(fat))) != 0)
  334                 goto bad;
  335 
  336         if ((error = exec_macho_load_vnode(l, epp, vp, &fat,
  337             entry, type, recursive, depth)) != 0)
  338                 goto bad;
  339 
  340         vrele(vp);
  341         return 0;
  342 
  343 badunlock:
  344         VOP_UNLOCK(vp, 0);
  345 
  346 bad:
  347 #ifdef notyet /* XXX cgd 960926 */
  348         (maybe) VOP_CLOSE it
  349 #endif
  350         vrele(vp);
  351         return error;
  352 }
  353 
  354 /*
  355  * exec_macho_load_vnode(): Map a file from the given vnode.
  356  * The fat signature is checked,
  357  * and it will return the address of the entry point in entry.
  358  * The type determines what we are loading, a dynamic linker,
  359  * a dynamic library, or a binary. We use that to guess at
  360  * the entry point.
  361  */
  362 static int
  363 exec_macho_load_vnode(struct lwp *l, struct exec_package *epp,
  364     struct vnode *vp, struct exec_macho_fat_header *fat, u_long *entry,
  365     int type, int recursive, int depth)
  366 {
  367         u_long aoffs, offs;
  368         struct exec_macho_fat_arch arch;
  369         struct exec_macho_object_header hdr;
  370         struct exec_macho_load_command lc;
  371         struct exec_macho_emul_arg *emea;
  372         int error = ENOEXEC, i;
  373         size_t size;
  374         void *bf = &lc;
  375         uint32_t *sc = NULL;
  376 
  377 #ifdef DEBUG_MACHO
  378         exec_macho_print_fat_header(fat);
  379 #endif
  380 
  381         switch (fat->magic) {
  382         case MACHO_FAT_MAGIC:
  383                 for (i = 0; i < be32toh(fat->nfat_arch); i++, arch) {
  384                         if ((error = exec_read_from(l, vp, sizeof(*fat) +
  385                             sizeof(arch) * i, &arch, sizeof(arch))) != 0)
  386                                 goto bad;
  387 #ifdef DEBUG_MACHO
  388                         exec_macho_print_fat_arch(&arch);
  389 #endif
  390                         for (sc = exec_macho_supported_cpu; *sc; sc++)
  391                                 if (*sc == be32toh(arch.cputype))
  392                                         break;
  393 
  394                         if (sc != NULL)
  395                                 break;
  396                 }
  397                 if (sc == NULL || *sc == 0) {
  398                         DPRINTF(("CPU %d not supported by this binary",
  399                                 be32toh(arch.cputype)));
  400                         goto bad;
  401                 }
  402                 break;
  403 
  404         case MACHO_MOH_MAGIC:
  405                 /*
  406                  * This is not a FAT Mach-O binary, the file starts
  407                  * with the object header.
  408                  */
  409                 arch.offset = 0;
  410                 break;
  411 
  412         default:
  413                 DPRINTF(("bad exec_macho magic %x\n", fat->magic));
  414                 goto bad;
  415                 break;
  416         }
  417 
  418         if ((error = exec_read_from(l, vp, be32toh(arch.offset), &hdr,
  419             sizeof(hdr))) != 0)
  420                 goto bad;
  421 
  422         if (hdr.magic != MACHO_MOH_MAGIC) {
  423                 DPRINTF(("bad exec_macho header magic %lx\n", hdr.magic));
  424                 goto bad;
  425         }
  426 
  427 #ifdef DEBUG_MACHO
  428         exec_macho_print_object_header(&hdr);
  429 #endif
  430         switch (hdr.filetype) {
  431         case MACHO_MOH_PRELOAD:
  432         case MACHO_MOH_EXECUTE:
  433         case MACHO_MOH_DYLINKER:
  434         case MACHO_MOH_DYLIB:
  435         case MACHO_MOH_BUNDLE:
  436                 break;
  437         default:
  438                 DPRINTF(("Unsupported exec_macho filetype 0x%lx\n",
  439                     hdr.filetype));
  440                 goto bad;
  441         }
  442 
  443 
  444         aoffs = be32toh(arch.offset);
  445         offs = aoffs + sizeof(hdr);
  446         size = sizeof(lc);
  447         for (i = 0; i < hdr.ncmds; i++) {
  448                 if ((error = exec_read_from(l, vp, offs, &lc, sizeof(lc))) != 0)
  449                         goto bad;
  450 
  451 #ifdef DEBUG_MACHO
  452                 exec_macho_print_load_command(&lc);
  453 #endif
  454                 if (size < lc.cmdsize) {
  455                         if (lc.cmdsize > 4096) {
  456                                 DPRINTF(("Bad command size %ld\n", lc.cmdsize));
  457                                 goto bad;
  458                         }
  459                         if (bf != &lc)
  460                                 free(bf, M_TEMP);
  461                         bf = malloc(size = lc.cmdsize, M_TEMP, M_WAITOK);
  462                 }
  463 
  464                 if ((error = exec_read_from(l, vp, offs, bf, lc.cmdsize)) != 0)
  465                         goto bad;
  466 
  467                 switch (lc.cmd) {
  468                 case MACHO_LC_SEGMENT:
  469                         error = exec_macho_load_segment(epp, vp, aoffs,
  470                             (struct exec_macho_segment_command *)bf, type);
  471 
  472                         switch(error) {
  473                         case ENOMEM:    /* Just skip, dyld will load it */
  474                                 DPRINTF(("load segment failed, skipping\n"));
  475                                 i = hdr.ncmds;
  476                                 break;
  477                         case 0:         /* No error, carry on loading file */
  478                                 break;
  479                         default:        /* Abort file load */
  480                                 DPRINTF(("load segment failed, aborting\n"));
  481                                 goto bad;
  482                                 break;
  483                         }
  484                         break;
  485                 case MACHO_LC_LOAD_DYLINKER:
  486                         if ((error = exec_macho_load_dylinker(l, epp,
  487                             (struct exec_macho_dylinker_command *)bf,
  488                             entry, depth)) != 0) {
  489                                 DPRINTF(("load linker failed\n"));
  490                                 goto bad;
  491                         }
  492                         emea = (struct exec_macho_emul_arg *)epp->ep_emul_arg;
  493                         emea->dynamic = 1;
  494                         break;
  495                 case MACHO_LC_LOAD_DYLIB:
  496                         /*
  497                          * We should only load libraries required by the
  498                          * binary we want to load, not libraries required
  499                          * by theses libraries.
  500                          */
  501                         if (recursive == 0)
  502                                 break;
  503                         if ((error = exec_macho_load_dylib(l, epp,
  504                             (struct exec_macho_dylib_command *)bf,
  505                             depth)) != 0) {
  506                                 DPRINTF(("load dylib failed\n"));
  507                                 goto bad;
  508                         }
  509                         break;
  510 
  511                 case MACHO_LC_THREAD:
  512                 case MACHO_LC_UNIXTHREAD:
  513                         if (type == MACHO_MOH_DYLINKER || *entry == 0) {
  514                                 *entry = exec_macho_load_thread(
  515                                     (struct exec_macho_thread_command *)bf);
  516                         } else {
  517                                 (void)exec_macho_load_thread(
  518                                     (struct exec_macho_thread_command *)bf);
  519                         }
  520                         break;
  521 
  522                 case MACHO_LC_ID_DYLINKER:
  523                 case MACHO_LC_ID_DYLIB:
  524                 case MACHO_LC_SYMTAB:
  525                 case MACHO_LC_DYSYMTAB:
  526                         break;
  527                 default:
  528                         DPRINTF(("Unhandled exec_macho command 0x%lx\n",
  529                             lc.cmd));
  530                         break;
  531                 }
  532                 offs += lc.cmdsize;
  533         }
  534         error = 0;
  535 bad:
  536         if (bf != &lc)
  537                 free(bf, M_TEMP);
  538         return error;
  539 }
  540 
  541 /*
  542  * exec_macho_makecmds(): Prepare an Mach-O binary's exec package
  543  *
  544  * First, set of the various offsets/lengths in the exec package.
  545  *
  546  * Then, mark the text image busy (so it can be demand paged) or error
  547  * out if this is not possible.  Finally, set up vmcmds for the
  548  * text, data, bss, and stack segments.
  549  */
  550 int
  551 exec_macho_makecmds(struct lwp *l, struct exec_package *epp)
  552 {
  553         struct exec_macho_fat_header *fat = epp->ep_hdr;
  554         struct exec_macho_emul_arg *emea;
  555         int error;
  556 
  557         if (epp->ep_hdrvalid < sizeof(*fat))
  558                 return ENOEXEC;
  559 
  560         /*
  561          * Check mount point.  Though we're not trying to exec this binary,
  562          * we will be executing code from it, so if the mount point
  563          * disallows execution or set-id-ness, we punt or kill the set-id.
  564          */
  565         if (epp->ep_vp->v_mount->mnt_flag & MNT_NOEXEC)
  566                 return EACCES;
  567 
  568         if (epp->ep_vp->v_mount->mnt_flag & MNT_NOSUID)
  569                 epp->ep_vap->va_mode &= ~(S_ISUID | S_ISGID);
  570 
  571         error = vn_marktext(epp->ep_vp);
  572         if (error)
  573                 return (error);
  574 
  575         emea = malloc(sizeof(struct exec_macho_emul_arg), M_TEMP, M_WAITOK);
  576         epp->ep_emul_arg = (void *)emea;
  577         emea->dynamic = 0;
  578 
  579         if (!epp->ep_esch->u.mach_probe_func)
  580                 emea->path = "/";
  581         else {
  582             if ((error = (*epp->ep_esch->u.mach_probe_func)(&emea->path)) != 0)
  583                     goto bad2;
  584         }
  585 
  586         /*
  587          * Make sure the underlying functions will not get
  588          * a random value here. 0 means that no entry point
  589          * has been found yet.
  590          */
  591         epp->ep_entry = 0;
  592 
  593         if ((error = exec_macho_load_vnode(l, epp, epp->ep_vp, fat,
  594             &epp->ep_entry, MACHO_MOH_EXECUTE, 1, 0)) != 0)
  595                 goto bad;
  596 
  597         /*
  598          * stash a copy of the program name in epp->ep_emul_arg because
  599          * we will need it later.
  600          */
  601         if ((error = copyinstr(epp->ep_name, emea->filename,
  602             MAXPATHLEN, NULL)) != 0) {
  603                 DPRINTF(("Copyinstr %p failed\n", epp->ep_name));
  604                 goto bad;
  605         }
  606 
  607         return (*epp->ep_esch->es_setup_stack)(l, epp);
  608 bad:
  609         kill_vmcmds(&epp->ep_vmcmds);
  610 bad2:
  611         free(emea, M_TEMP);
  612         return error;
  613 }

Cache object: 3ee1c91413d645968b82f7de2184a56c


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