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-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

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

Cache object: 57ee5f43f7cb0cf94014f0bf1ce36b91


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