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

Cache object: dd406b5e27785b77ff5d1c332704843a


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