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

FreeBSD/Linux Kernel Cross Reference
sys/bsd/kern/kern_exec.c

Version: -  FREEBSD  -  FREEBSD8  -  FREEBSD7  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  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  -  OPENSOLARIS  -  minix-3-1-1  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
    3  *
    4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
    5  * 
    6  * This file contains Original Code and/or Modifications of Original Code
    7  * as defined in and that are subject to the Apple Public Source License
    8  * Version 2.0 (the 'License'). You may not use this file except in
    9  * compliance with the License. The rights granted to you under the License
   10  * may not be used to create, or enable the creation or redistribution of,
   11  * unlawful or unlicensed copies of an Apple operating system, or to
   12  * circumvent, violate, or enable the circumvention or violation of, any
   13  * terms of an Apple operating system software license agreement.
   14  * 
   15  * Please obtain a copy of the License at
   16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
   17  * 
   18  * The Original Code and all software distributed under the License are
   19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   23  * Please see the License for the specific language governing rights and
   24  * limitations under the License.
   25  * 
   26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
   27  */
   28 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
   29 /*
   30  * Mach Operating System
   31  * Copyright (c) 1987 Carnegie-Mellon University
   32  * All rights reserved.  The CMU software License Agreement specifies
   33  * the terms and conditions for use and redistribution.
   34  */
   35  
   36 #include <cputypes.h>
   37 
   38 /*-
   39  * Copyright (c) 1982, 1986, 1991, 1993
   40  *      The Regents of the University of California.  All rights reserved.
   41  * (c) UNIX System Laboratories, Inc.
   42  * All or some portions of this file are derived from material licensed
   43  * to the University of California by American Telephone and Telegraph
   44  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   45  * the permission of UNIX System Laboratories, Inc.
   46  *
   47  * Redistribution and use in source and binary forms, with or without
   48  * modification, are permitted provided that the following conditions
   49  * are met:
   50  * 1. Redistributions of source code must retain the above copyright
   51  *    notice, this list of conditions and the following disclaimer.
   52  * 2. Redistributions in binary form must reproduce the above copyright
   53  *    notice, this list of conditions and the following disclaimer in the
   54  *    documentation and/or other materials provided with the distribution.
   55  * 3. All advertising materials mentioning features or use of this software
   56  *    must display the following acknowledgement:
   57  *      This product includes software developed by the University of
   58  *      California, Berkeley and its contributors.
   59  * 4. Neither the name of the University nor the names of its contributors
   60  *    may be used to endorse or promote products derived from this software
   61  *    without specific prior written permission.
   62  *
   63  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   64  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   65  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   66  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   67  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   68  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   69  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   70  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   71  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   72  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   73  * SUCH DAMAGE.
   74  *
   75  *      from: @(#)kern_exec.c   8.1 (Berkeley) 6/10/93
   76  */
   77 /*
   78  * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
   79  * support for mandatory and extensible security protections.  This notice
   80  * is included in support of clause 2.2 (b) of the Apple Public License,
   81  * Version 2.0.
   82  */
   83 #include <machine/reg.h>
   84 
   85 #include <sys/param.h>
   86 #include <sys/systm.h>
   87 #include <sys/filedesc.h>
   88 #include <sys/kernel.h>
   89 #include <sys/proc_internal.h>
   90 #include <sys/kauth.h>
   91 #include <sys/user.h>
   92 #include <sys/socketvar.h>
   93 #include <sys/malloc.h>
   94 #include <sys/namei.h>
   95 #include <sys/mount_internal.h>
   96 #include <sys/vnode_internal.h>         
   97 #include <sys/file_internal.h>
   98 #include <sys/stat.h>
   99 #include <sys/uio_internal.h>
  100 #include <sys/acct.h>
  101 #include <sys/exec.h>
  102 #include <sys/kdebug.h>
  103 #include <sys/signal.h>
  104 #include <sys/aio_kern.h>
  105 #include <sys/sysproto.h>
  106 #if SYSV_SHM
  107 #include <sys/shm_internal.h>           /* shmexec() */
  108 #endif
  109 #include <sys/ubc_internal.h>           /* ubc_map() */
  110 #include <sys/spawn.h>
  111 #include <sys/spawn_internal.h>
  112 #include <sys/codesign.h>
  113 
  114 #include <bsm/audit_kernel.h>
  115 
  116 #include <ipc/ipc_types.h>
  117 
  118 #include <mach/mach_types.h>
  119 #include <mach/task.h>
  120 #include <mach/thread_act.h>
  121 #include <mach/vm_map.h>
  122 #include <mach/mach_vm.h>
  123 #include <mach/vm_param.h>
  124 
  125 #if CONFIG_MACF
  126 #include <security/mac.h>
  127 #include <security/mac_mach_internal.h>
  128 #endif
  129 
  130 #include <vm/vm_map.h>
  131 #include <vm/vm_kern.h>
  132 #include <vm/vm_protos.h>
  133 #include <vm/vm_kern.h>
  134 
  135 #if CONFIG_DTRACE
  136 /* Do not include dtrace.h, it redefines kmem_[alloc/free] */
  137 extern void (*dtrace_fasttrap_exec_ptr)(proc_t);
  138 extern void (*dtrace_helpers_cleanup)(proc_t);
  139 extern void dtrace_lazy_dofs_destroy(proc_t);
  140 
  141 #include <sys/dtrace_ptss.h>
  142 #endif
  143 
  144 /* support for child creation in exec after vfork */
  145 thread_t fork_create_child(task_t parent_task, proc_t child_proc, int inherit_memory, int is64bit);
  146 void vfork_exit(proc_t p, int rv);
  147 int setsigvec(proc_t, int, struct __user_sigaction *);
  148 
  149 /*
  150  * Mach things for which prototypes are unavailable from Mach headers
  151  */
  152 void            ipc_task_reset(
  153                         task_t          task);
  154 void            ipc_thread_reset(
  155                         thread_t        thread);
  156 kern_return_t ipc_object_copyin(
  157         ipc_space_t             space,
  158         mach_port_name_t        name,
  159         mach_msg_type_name_t    msgt_name,
  160         ipc_object_t            *objectp);
  161 void ipc_port_release_send(ipc_port_t);
  162 
  163 extern struct savearea *get_user_regs(thread_t);
  164 
  165 
  166 #include <kern/thread.h>
  167 #include <kern/task.h>
  168 #include <kern/ast.h>
  169 #include <kern/mach_loader.h>
  170 #include <mach-o/fat.h>
  171 #include <mach-o/loader.h>
  172 #include <machine/vmparam.h>
  173 #include <sys/imgact.h>
  174 
  175 #include <sys/sdt.h>
  176 
  177 
  178 /*
  179  * SIZE_MAXPTR          The maximum size of a user space pointer, in bytes
  180  * SIZE_IMG_STRSPACE    The available string space, minus two pointers; we
  181  *                      define it interms of the maximum, since we don't
  182  *                      know the pointer size going in, until after we've
  183  *                      parsed the executable image.
  184  */
  185 #define SIZE_MAXPTR             8                               /* 64 bits */
  186 #define SIZE_IMG_STRSPACE       (NCARGS - 2 * SIZE_MAXPTR)
  187 
  188 /*
  189  * EAI_ITERLIMIT        The maximum number of times to iterate an image
  190  *                      activator in exec_activate_image() before treating
  191  *                      it as malformed/corrupt.
  192  */
  193 #define EAI_ITERLIMIT           10
  194 
  195 extern vm_map_t bsd_pageable_map;
  196 extern struct fileops vnops;
  197 
  198 #define ROUND_PTR(type, addr)   \
  199         (type *)( ( (unsigned)(addr) + 16 - 1) \
  200                   & ~(16 - 1) )
  201 
  202 struct image_params;    /* Forward */
  203 static int exec_activate_image(struct image_params *imgp);
  204 static int exec_copyout_strings(struct image_params *imgp, user_addr_t *stackp);
  205 static int load_return_to_errno(load_return_t lrtn);
  206 static int execargs_alloc(struct image_params *imgp);
  207 static int execargs_free(struct image_params *imgp);
  208 static int exec_check_permissions(struct image_params *imgp);
  209 static int exec_extract_strings(struct image_params *imgp);
  210 static int exec_handle_sugid(struct image_params *imgp);
  211 static int sugid_scripts = 0;
  212 SYSCTL_INT (_kern, OID_AUTO, sugid_scripts, CTLFLAG_RW, &sugid_scripts, 0, "");
  213 static kern_return_t create_unix_stack(vm_map_t map, user_addr_t user_stack,
  214                                         int customstack, proc_t p);
  215 static int copyoutptr(user_addr_t ua, user_addr_t ptr, int ptr_size);
  216 static void exec_resettextvp(proc_t, struct image_params *);
  217 
  218 /* We don't want this one exported */
  219 __private_extern__
  220 int  open1(vfs_context_t, struct nameidata *, int, struct vnode_attr *, register_t *);
  221 
  222 /*
  223  * exec_add_string
  224  *
  225  * Add the requested string to the string space area.
  226  *
  227  * Parameters;  struct image_params *           image parameter block
  228  *              user_addr_t                     string to add to strings area
  229  *
  230  * Returns:     0                       Success
  231  *              !0                      Failure errno from copyinstr()
  232  *
  233  * Implicit returns:
  234  *              (imgp->ip_strendp)      updated location of next add, if any
  235  *              (imgp->ip_strspace)     updated byte count of space remaining
  236  */
  237 static int
  238 exec_add_string(struct image_params *imgp, user_addr_t str)
  239 {
  240         int error = 0;
  241 
  242         do {
  243                 size_t len = 0;
  244                 if (imgp->ip_strspace <= 0) {
  245                         error = E2BIG;
  246                         break;
  247                 }
  248                 if (IS_UIO_SYS_SPACE(imgp->ip_seg)) {
  249                         char *kstr = CAST_DOWN(char *,str);     /* SAFE */
  250                         error = copystr(kstr, imgp->ip_strendp, imgp->ip_strspace, &len);
  251                 } else  {
  252                         error = copyinstr(str, imgp->ip_strendp, imgp->ip_strspace,
  253                             &len);
  254                 }
  255                 imgp->ip_strendp += len;
  256                 imgp->ip_strspace -= len;
  257         } while (error == ENAMETOOLONG);
  258 
  259         return error;
  260 }
  261 
  262 /*
  263  * exec_save_path
  264  *
  265  * To support new app package launching for Mac OS X, the dyld needs the
  266  * first argument to execve() stored on the user stack.
  267  *
  268  * Save the executable path name at the top of the strings area and set
  269  * the argument vector pointer to the location following that to indicate
  270  * the start of the argument and environment tuples, setting the remaining
  271  * string space count to the size of the string area minus the path length
  272  * and a reserve for two pointers.
  273  *
  274  * Parameters;  struct image_params *           image parameter block
  275  *              char *                          path used to invoke program
  276  *              int                             segment from which path comes
  277  *
  278  * Returns:     int                     0       Success
  279  *              EFAULT                          Bad address
  280  *      copy[in]str:EFAULT                      Bad address
  281  *      copy[in]str:ENAMETOOLONG                Filename too long
  282  *
  283  * Implicit returns:
  284  *              (imgp->ip_strings)              saved path
  285  *              (imgp->ip_strspace)             space remaining in ip_strings
  286  *              (imgp->ip_argv)                 beginning of argument list
  287  *              (imgp->ip_strendp)              start of remaining copy area
  288  *
  289  * Note:        We have to do this before the initial namei() since in the
  290  *              path contains symbolic links, namei() will overwrite the
  291  *              original path buffer contents.  If the last symbolic link
  292  *              resolved was a relative pathname, we would lose the original
  293  *              "path", which could be an absolute pathname. This might be
  294  *              unacceptable for dyld.
  295  */
  296 static int
  297 exec_save_path(struct image_params *imgp, user_addr_t path, int seg)
  298 {
  299         int error;
  300         size_t  len;
  301         char *kpath = CAST_DOWN(char *,path);   /* SAFE */
  302 
  303         imgp->ip_strendp = imgp->ip_strings;
  304         imgp->ip_strspace = SIZE_IMG_STRSPACE;
  305 
  306         len = MIN(MAXPATHLEN, imgp->ip_strspace);
  307 
  308         switch(seg) {
  309         case UIO_USERSPACE32:
  310         case UIO_USERSPACE64:   /* Same for copyin()... */
  311                 error = copyinstr(path, imgp->ip_strings, len, &len);
  312                 break;
  313         case UIO_SYSSPACE32:
  314                 error = copystr(kpath, imgp->ip_strings, len, &len);
  315                 break;
  316         default:
  317                 error = EFAULT;
  318                 break;
  319         }
  320 
  321         if (!error) {
  322                 imgp->ip_strendp += len;
  323                 imgp->ip_strspace -= len;
  324                 imgp->ip_argv = imgp->ip_strendp;
  325         }
  326 
  327         return(error);
  328 }
  329 
  330 #ifdef IMGPF_POWERPC
  331 /*
  332  * exec_powerpc32_imgact
  333  *
  334  * Implicitly invoke the PowerPC handler for a byte-swapped image magic
  335  * number.  This may happen either as a result of an attempt to invoke a
  336  * PowerPC image directly, or indirectly as the interpreter used in an
  337  * interpreter script.
  338  *
  339  * Parameters;  struct image_params *   image parameter block
  340  *
  341  * Returns:     -1              not an PowerPC image (keep looking)
  342  *              -3              Success: exec_archhandler_ppc: relookup
  343  *              >0              Failure: exec_archhandler_ppc: error number
  344  *
  345  * Note:        This image activator does not handle the case of a direct
  346  *              invocation of the exec_archhandler_ppc, since in that case, the
  347  *              exec_archhandler_ppc itself is not a PowerPC binary; instead,
  348  *              binary image activators must recognize the exec_archhandler_ppc;
  349  *              This is managed in exec_check_permissions().
  350  *
  351  * Note:        This image activator is limited to 32 bit powerpc images;
  352  *              if support for 64 bit powerpc images is desired, it would
  353  *              be more in line with this design to write a separate 64 bit
  354  *              image activator.
  355  */
  356 static int
  357 exec_powerpc32_imgact(struct image_params *imgp)
  358 {
  359         struct mach_header *mach_header = (struct mach_header *)imgp->ip_vdata;
  360         int error;
  361         size_t len = 0;
  362 
  363         /*
  364          * Make sure it's a PowerPC binary.  If we've already redirected
  365          * from an interpreted file once, don't do it again.
  366          */
  367         if (mach_header->magic != MH_CIGAM) {
  368                 /*
  369                  * If it's a cross-architecture 64 bit binary, then claim
  370                  * it, but refuse to run it.
  371                  */
  372                 if (mach_header->magic == MH_CIGAM_64)
  373                         return (EBADARCH);
  374                 return (-1);
  375         }
  376 
  377         /* If there is no exec_archhandler_ppc, we can't run it */
  378         if (exec_archhandler_ppc.path[0] == 0)
  379                 return (EBADARCH);
  380 
  381         /* Remember the type of the original file for later grading */
  382         if (!imgp->ip_origcputype) {
  383                 imgp->ip_origcputype = 
  384                         OSSwapBigToHostInt32(mach_header->cputype);
  385                 imgp->ip_origcpusubtype = 
  386                         OSSwapBigToHostInt32(mach_header->cpusubtype);
  387         }
  388 
  389         /*
  390          * The PowerPC flag will be set by the exec_check_permissions()
  391          * call anyway; however, we set this flag here so that the relookup
  392          * in execve() does not follow symbolic links, as a side effect.
  393          */
  394         imgp->ip_flags |= IMGPF_POWERPC;
  395 
  396         /* impute an interpreter */
  397         error = copystr(exec_archhandler_ppc.path, imgp->ip_interp_name,
  398                         IMG_SHSIZE, &len);
  399         if (error)
  400                 return (error);
  401 
  402         /*
  403          * provide a replacement string for p->p_comm; we have to use an
  404          * an alternate buffer for this, rather than replacing it directly,
  405          * since the exec may fail and return to the parent.  In that case,
  406          * we would have erroneously changed the parent p->p_comm instead.
  407          */
  408         strlcpy(imgp->ip_p_comm, imgp->ip_ndp->ni_cnd.cn_nameptr, MAXCOMLEN);
  409 
  410         return (-3);
  411 }
  412 #endif  /* IMGPF_POWERPC */
  413 
  414 
  415 /*
  416  * exec_shell_imgact
  417  *
  418  * Image activator for interpreter scripts.  If the image begins with the
  419  * characters "#!", then it is an interpreter script.  Verify that we are
  420  * not already executing in PowerPC mode, and that the length of the script
  421  * line indicating the interpreter is not in excess of the maximum allowed
  422  * size.  If this is the case, then break out the arguments, if any, which
  423  * are separated by white space, and copy them into the argument save area
  424  * as if they were provided on the command line before all other arguments.
  425  * The line ends when we encounter a comment character ('#') or newline.
  426  *
  427  * Parameters;  struct image_params *   image parameter block
  428  *
  429  * Returns:     -1                      not an interpreter (keep looking)
  430  *              -3                      Success: interpreter: relookup
  431  *              >0                      Failure: interpreter: error number
  432  *
  433  * A return value other than -1 indicates subsequent image activators should
  434  * not be given the opportunity to attempt to activate the image.
  435  */
  436 static int
  437 exec_shell_imgact(struct image_params *imgp)
  438 {
  439         char *vdata = imgp->ip_vdata;
  440         char *ihp;
  441         char *line_endp;
  442         char *interp;
  443         char temp[16];
  444         proc_t p;
  445         struct fileproc *fp;
  446         int fd;
  447         int error;
  448         size_t len;
  449 
  450         /*
  451          * Make sure it's a shell script.  If we've already redirected
  452          * from an interpreted file once, don't do it again.
  453          *
  454          * Note: We disallow PowerPC, since the expectation is that we
  455          * may run a PowerPC interpreter, but not an interpret a PowerPC 
  456          * image.  This is consistent with historical behaviour.
  457          */
  458         if (vdata[0] != '#' ||
  459             vdata[1] != '!' ||
  460             (imgp->ip_flags & IMGPF_INTERPRET) != 0) {
  461                 return (-1);
  462         }
  463 
  464 #ifdef IMGPF_POWERPC
  465         if ((imgp->ip_flags & IMGPF_POWERPC) != 0)
  466                   return (EBADARCH);
  467 #endif  /* IMGPF_POWERPC */
  468 
  469         imgp->ip_flags |= IMGPF_INTERPRET;
  470 
  471         /* Check to see if SUGID scripts are permitted.  If they aren't then
  472          * clear the SUGID bits.
  473          * imgp->ip_vattr is known to be valid.
  474          */
  475         if (sugid_scripts == 0) {
  476            imgp->ip_origvattr->va_mode &= ~(VSUID | VSGID);
  477         }
  478 
  479         /* Find the nominal end of the interpreter line */
  480         for( ihp = &vdata[2]; *ihp != '\n' && *ihp != '#'; ihp++) {
  481                 if (ihp >= &vdata[IMG_SHSIZE])
  482                         return (ENOEXEC);
  483         }
  484 
  485         line_endp = ihp;
  486         ihp = &vdata[2];
  487         /* Skip over leading spaces - until the interpreter name */
  488         while ( ihp < line_endp && ((*ihp == ' ') || (*ihp == '\t')))
  489                 ihp++;
  490 
  491         /*
  492          * Find the last non-whitespace character before the end of line or
  493          * the beginning of a comment; this is our new end of line.
  494          */
  495         for (;line_endp > ihp && ((*line_endp == ' ') || (*line_endp == '\t')); line_endp--)
  496                 continue;
  497 
  498         /* Empty? */
  499         if (line_endp == ihp)
  500                 return (ENOEXEC);
  501 
  502         /* copy the interpreter name */
  503         interp = imgp->ip_interp_name;
  504         while ((ihp < line_endp) && (*ihp != ' ') && (*ihp != '\t'))
  505                 *interp++ = *ihp++;
  506         *interp = '\0';
  507 
  508         exec_save_path(imgp, CAST_USER_ADDR_T(imgp->ip_interp_name),
  509                                                         UIO_SYSSPACE32);
  510 
  511         ihp = &vdata[2];
  512         while (ihp < line_endp) {
  513                 /* Skip leading whitespace before each argument */
  514                 while ((*ihp == ' ') || (*ihp == '\t'))
  515                         ihp++;
  516 
  517                 if (ihp >= line_endp)
  518                         break;
  519 
  520                 /* We have an argument; copy it */
  521                 while ((ihp < line_endp) && (*ihp != ' ') && (*ihp != '\t')) {  
  522                         *imgp->ip_strendp++ = *ihp++;
  523                         imgp->ip_strspace--;
  524                 }
  525                 *imgp->ip_strendp++ = 0;
  526                 imgp->ip_strspace--;
  527                 imgp->ip_argc++;
  528         }
  529 
  530         /*
  531          * If we have a SUID oder SGID script, create a file descriptor
  532          * from the vnode and pass /dev/fd/%d instead of the actual
  533          * path name so that the script does not get opened twice
  534          */
  535         if (imgp->ip_origvattr->va_mode & (VSUID | VSGID)) {
  536                 p = vfs_context_proc(imgp->ip_vfs_context);
  537                 error = falloc(p, &fp, &fd, imgp->ip_vfs_context);
  538                 if (error)
  539                         return(error);
  540 
  541                 fp->f_fglob->fg_flag = FREAD;
  542                 fp->f_fglob->fg_type = DTYPE_VNODE;
  543                 fp->f_fglob->fg_ops = &vnops;
  544                 fp->f_fglob->fg_data = (caddr_t)imgp->ip_vp;
  545                 
  546                 proc_fdlock(p);
  547                 procfdtbl_releasefd(p, fd, NULL);
  548                 fp_drop(p, fd, fp, 1);
  549                 proc_fdunlock(p);
  550                 vnode_ref(imgp->ip_vp);
  551 
  552                 snprintf(temp, sizeof(temp), "/dev/fd/%d", fd);
  553                 error = copyoutstr(temp, imgp->ip_user_fname, sizeof(temp), &len);
  554                 if (error)
  555                         return(error);
  556         }
  557 
  558         return (-3);
  559 }
  560 
  561 
  562 
  563 /*
  564  * exec_fat_imgact
  565  *
  566  * Image activator for fat 1.0 binaries.  If the binary is fat, then we
  567  * need to select an image from it internally, and make that the image
  568  * we are going to attempt to execute.  At present, this consists of
  569  * reloading the first page for the image with a first page from the
  570  * offset location indicated by the fat header.
  571  *
  572  * Parameters;  struct image_params *   image parameter block
  573  *
  574  * Returns:     -1                      not a fat binary (keep looking)
  575  *              -2                      Success: encapsulated binary: reread
  576  *              >0                      Failure: error number
  577  *
  578  * Important:   This image activator is byte order neutral.
  579  *
  580  * Note:        A return value other than -1 indicates subsequent image
  581  *              activators should not be given the opportunity to attempt
  582  *              to activate the image.
  583  *
  584  *              If we find an encapsulated binary, we make no assertions
  585  *              about its  validity; instead, we leave that up to a rescan
  586  *              for an activator to claim it, and, if it is claimed by one,
  587  *              that activator is responsible for determining validity.
  588  */
  589 static int
  590 exec_fat_imgact(struct image_params *imgp)
  591 {
  592         proc_t p = vfs_context_proc(imgp->ip_vfs_context);
  593         kauth_cred_t cred = kauth_cred_proc_ref(p);
  594         struct fat_header *fat_header = (struct fat_header *)imgp->ip_vdata;
  595         struct _posix_spawnattr *psa = NULL;
  596         struct fat_arch fat_arch;
  597         int resid, error;
  598         load_return_t lret;
  599 
  600         /* Make sure it's a fat binary */
  601         if ((fat_header->magic != FAT_MAGIC) &&
  602             (fat_header->magic != FAT_CIGAM)) {
  603                 error = -1;
  604                 goto bad;
  605         }
  606 
  607         /* If posix_spawn binprefs exist, respect those prefs. */
  608         psa = (struct _posix_spawnattr *) imgp->ip_px_sa;
  609         if (psa != NULL && psa->psa_binprefs[0] != 0) {
  610                 struct fat_arch *arches = (struct fat_arch *) (fat_header + 1);
  611                 int nfat_arch = 0, pr = 0, f = 0;
  612 
  613                 nfat_arch = OSSwapBigToHostInt32(fat_header->nfat_arch);
  614                 /* Check each preference listed against all arches in header */
  615                 for (pr = 0; pr < NBINPREFS; pr++) {
  616                         cpu_type_t pref = psa->psa_binprefs[pr];
  617                         if (pref == 0) {
  618                                 /* No suitable arch in the pref list */
  619                                 error = EBADARCH;
  620                                 goto bad;
  621                         }
  622 
  623                         if (pref == CPU_TYPE_ANY) {
  624                                 /* Fall through to regular grading */
  625                                 break;
  626                         }
  627 
  628                         for (f = 0; f < nfat_arch; f++) {
  629                                 cpu_type_t archtype = OSSwapBigToHostInt32(
  630                                                 arches[f].cputype);
  631                                 cpu_type_t archsubtype = OSSwapBigToHostInt32(
  632                                                 arches[f].cpusubtype) & ~CPU_SUBTYPE_MASK;
  633                                 if (pref == archtype &&
  634                                         grade_binary(archtype, archsubtype)) {
  635                                         /* We have a winner! */
  636                                         fat_arch.cputype = archtype; 
  637                                         fat_arch.cpusubtype = archsubtype; 
  638                                         fat_arch.offset = OSSwapBigToHostInt32(
  639                                                         arches[f].offset);
  640                                         fat_arch.size = OSSwapBigToHostInt32(
  641                                                         arches[f].size);
  642                                         fat_arch.align = OSSwapBigToHostInt32(
  643                                                         arches[f].align);
  644                                         goto use_arch;
  645                                 }
  646                         }
  647                 }
  648         }
  649 
  650         /* Look up our preferred architecture in the fat file. */
  651         lret = fatfile_getarch_affinity(imgp->ip_vp,
  652                                         (vm_offset_t)fat_header,
  653                                         &fat_arch,
  654                                         (p->p_flag & P_AFFINITY));
  655         if (lret != LOAD_SUCCESS) {
  656                 error = load_return_to_errno(lret);
  657                 goto bad;
  658         }
  659 
  660 use_arch:
  661         /* Read the Mach-O header out of fat_arch */
  662         error = vn_rdwr(UIO_READ, imgp->ip_vp, imgp->ip_vdata,
  663                         PAGE_SIZE, fat_arch.offset,
  664                         UIO_SYSSPACE32, (IO_UNIT|IO_NODELOCKED),
  665                         cred, &resid, p);
  666         if (error) {
  667                 goto bad;
  668         }
  669 
  670         /* Did we read a complete header? */
  671         if (resid) {
  672                 error = EBADEXEC;
  673                 goto bad;
  674         }
  675 
  676         /* Success.  Indicate we have identified an encapsulated binary */
  677         error = -2;
  678         imgp->ip_arch_offset = (user_size_t)fat_arch.offset;
  679         imgp->ip_arch_size = (user_size_t)fat_arch.size;
  680 
  681 bad:
  682         kauth_cred_unref(&cred);
  683         return (error);
  684 }
  685 
  686 /*
  687  * exec_mach_imgact
  688  *
  689  * Image activator for mach-o 1.0 binaries.
  690  *
  691  * Parameters;  struct image_params *   image parameter block
  692  *
  693  * Returns:     -1                      not a fat binary (keep looking)
  694  *              -2                      Success: encapsulated binary: reread
  695  *              >0                      Failure: error number
  696  *              EBADARCH                Mach-o binary, but with an unrecognized
  697  *                                      architecture
  698  *              ENOMEM                  No memory for child process after -
  699  *                                      can only happen after vfork()
  700  *
  701  * Important:   This image activator is NOT byte order neutral.
  702  *
  703  * Note:        A return value other than -1 indicates subsequent image
  704  *              activators should not be given the opportunity to attempt
  705  *              to activate the image.
  706  *
  707  * TODO:        More gracefully handle failures after vfork
  708  */
  709 static int
  710 exec_mach_imgact(struct image_params *imgp)
  711 {
  712         struct mach_header *mach_header = (struct mach_header *)imgp->ip_vdata;
  713         proc_t                  p = vfs_context_proc(imgp->ip_vfs_context);
  714         int                     error = 0;
  715         int                     vfexec = 0;
  716         task_t                  task;
  717         task_t                  new_task = NULL; /* protected by vfexec */
  718         thread_t                thread;
  719         struct uthread          *uthread;
  720         vm_map_t old_map = VM_MAP_NULL;
  721         vm_map_t map;
  722         load_return_t           lret;
  723         load_result_t           load_result;
  724         struct _posix_spawnattr *psa = NULL;
  725 
  726         /*
  727          * make sure it's a Mach-O 1.0 or Mach-O 2.0 binary; the difference
  728          * is a reserved field on the end, so for the most part, we can
  729          * treat them as if they were identical.
  730          */
  731         if ((mach_header->magic != MH_MAGIC) &&
  732             (mach_header->magic != MH_MAGIC_64)) {
  733                 error = -1;
  734                 goto bad;
  735         }
  736 
  737         switch (mach_header->filetype) {
  738         case MH_DYLIB:
  739         case MH_BUNDLE:
  740                 error = -1;
  741                 goto bad;
  742         }
  743 
  744         if (!imgp->ip_origcputype) {
  745                 imgp->ip_origcputype = mach_header->cputype;
  746                 imgp->ip_origcpusubtype = mach_header->cpusubtype;
  747         }
  748 
  749         task = current_task();
  750         thread = current_thread();
  751         uthread = get_bsdthread_info(thread);
  752 
  753         if (uthread->uu_flag & UT_VFORK)
  754                 vfexec = 1;      /* Mark in exec */
  755 
  756         if ((mach_header->cputype & CPU_ARCH_ABI64) == CPU_ARCH_ABI64)
  757                 imgp->ip_flags |= IMGPF_IS_64BIT;
  758 
  759         /* If posix_spawn binprefs exist, respect those prefs. */
  760         psa = (struct _posix_spawnattr *) imgp->ip_px_sa;
  761         if (psa != NULL && psa->psa_binprefs[0] != 0) {
  762                 int pr = 0;
  763                 for (pr = 0; pr < NBINPREFS; pr++) {
  764                         cpu_type_t pref = psa->psa_binprefs[pr];
  765                         if (pref == 0) {
  766                                 /* No suitable arch in the pref list */
  767                                 error = EBADARCH;
  768                                 goto bad;
  769                         }
  770 
  771                         if (pref == CPU_TYPE_ANY) {
  772                                 /* Jump to regular grading */
  773                                 goto grade;
  774                         }
  775 
  776                         if (pref == imgp->ip_origcputype) {
  777                                 /* We have a match! */
  778                                 goto grade;
  779                         }
  780                 }
  781                 error = EBADARCH;
  782                 goto bad;
  783         }
  784 grade:
  785         if (!grade_binary(imgp->ip_origcputype & ~CPU_SUBTYPE_LIB64, 
  786                                 imgp->ip_origcpusubtype & ~CPU_SUBTYPE_MASK)) {
  787                 error = EBADARCH;
  788                 goto bad;
  789         }
  790 
  791         /* Copy in arguments/environment from the old process */
  792         error = exec_extract_strings(imgp);
  793         if (error)
  794                 goto bad;
  795 
  796         /*
  797          * Hack for binary compatability; put three NULs on the end of the
  798          * string area, and round it up to the next word boundary.  This
  799          * ensures padding with NULs to the boundary.
  800          */
  801         imgp->ip_strendp[0] = 0;
  802         imgp->ip_strendp[1] = 0;
  803         imgp->ip_strendp[2] = 0;
  804         imgp->ip_strendp += (((imgp->ip_strendp - imgp->ip_strings) + NBPW-1) & ~(NBPW-1));
  805 
  806 #ifdef IMGPF_POWERPC
  807         /*
  808          * XXX
  809          *
  810          * Should be factored out; this is here because we might be getting
  811          * invoked this way as the result of a shell script, and the check
  812          * in exec_check_permissions() is not interior to the jump back up
  813          * to the "encapsulated_binary:" label in exec_activate_image().
  814          */
  815         if (imgp->ip_vattr->va_fsid == exec_archhandler_ppc.fsid &&
  816                 imgp->ip_vattr->va_fileid == (uint64_t)((u_long)exec_archhandler_ppc.fileid)) {
  817                 imgp->ip_flags |= IMGPF_POWERPC;
  818         }
  819 #endif  /* IMGPF_POWERPC */
  820 
  821         if (vfexec) {
  822                 imgp->ip_vfork_thread = fork_create_child(task, p, FALSE, (imgp->ip_flags & IMGPF_IS_64BIT));
  823                 if (imgp->ip_vfork_thread == NULL) {
  824                         error = ENOMEM;
  825                         goto bad;
  826                 }
  827                 /* reset local idea of thread, uthread, task */
  828                 thread = imgp->ip_vfork_thread;
  829                 uthread = get_bsdthread_info(thread);
  830                 task = new_task = get_threadtask(thread);
  831                 map = get_task_map(task);
  832         } else {
  833                 map = VM_MAP_NULL;
  834         }
  835 
  836         /*
  837          * We set these flags here; this is OK, since if we fail after
  838          * this point, we have already destroyed the parent process anyway.
  839          */
  840         if (imgp->ip_flags & IMGPF_IS_64BIT) {
  841                 task_set_64bit(task, TRUE);
  842                 OSBitOrAtomic(P_LP64, (UInt32 *)&p->p_flag);
  843         } else {
  844                 task_set_64bit(task, FALSE);
  845                 OSBitAndAtomic(~((uint32_t)P_LP64), (UInt32 *)&p->p_flag);
  846         }
  847 
  848         /*
  849          *      Load the Mach-O file.
  850          */
  851 
  852         /*
  853          * NOTE: An error after this point  indicates we have potentially
  854          * destroyed or overwrote some process state while attempting an
  855          * execve() following a vfork(), which is an unrecoverable condition.
  856          */
  857 
  858         /*
  859          * We reset the task to 64-bit (or not) here.  It may have picked up
  860          * a new map, and we need that to reflect its true 64-bit nature.
  861          */
  862 
  863         task_set_64bit(task, 
  864                        ((imgp->ip_flags & IMGPF_IS_64BIT) == IMGPF_IS_64BIT));
  865 
  866         /*
  867          * Actually load the image file we previously decided to load.
  868          */
  869         lret = load_machfile(imgp, mach_header, thread, map, &load_result);
  870 
  871         if (lret != LOAD_SUCCESS) {
  872                 error = load_return_to_errno(lret);
  873                 goto badtoolate;
  874         }
  875 
  876         vm_map_set_user_wire_limit(get_task_map(task), p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur);
  877 
  878         /* 
  879          * Set code-signing flags if this binary is signed, or if parent has
  880          * requested them on exec.
  881          */
  882         if (load_result.csflags & CS_VALID) {
  883                 imgp->ip_csflags |= load_result.csflags &
  884                         (CS_VALID|
  885                          CS_HARD|CS_KILL|CS_EXEC_SET_HARD|CS_EXEC_SET_KILL);
  886         } else {
  887                 imgp->ip_csflags &= ~CS_VALID;
  888         }
  889 
  890         if (p->p_csflags & CS_EXEC_SET_HARD)
  891                 imgp->ip_csflags |= CS_HARD;
  892         if (p->p_csflags & CS_EXEC_SET_KILL)
  893                 imgp->ip_csflags |= CS_KILL;
  894 
  895 
  896         /* load_machfile() maps the vnode */
  897         (void)ubc_map(imgp->ip_vp, PROT_READ | PROT_EXEC);
  898 
  899         /*
  900          * Set up the system reserved areas in the new address space.
  901          */
  902         vm_map_exec(get_task_map(task),
  903                     task,
  904                     (void *) p->p_fd->fd_rdir,
  905 #ifdef IMGPF_POWERPC
  906                     imgp->ip_flags & IMGPF_POWERPC ?
  907                     CPU_TYPE_POWERPC :
  908 #endif
  909                     cpu_type());
  910         
  911         /*
  912          * Close file descriptors
  913          * which specify close-on-exec.
  914          */
  915         fdexec(p);
  916 
  917         /*
  918          * deal with set[ug]id.
  919          */
  920         error = exec_handle_sugid(imgp);
  921 
  922         proc_knote(p, NOTE_EXEC);
  923 
  924         if (!vfexec && (p->p_lflag & P_LTRACED))
  925                 psignal(p, SIGTRAP);
  926 
  927         if (error) {
  928                 goto badtoolate;
  929         }
  930         
  931         if (load_result.unixproc &&
  932                 create_unix_stack(get_task_map(task),
  933                                   load_result.user_stack,
  934                                   load_result.customstack,
  935                                   p) != KERN_SUCCESS) {
  936                 error = load_return_to_errno(LOAD_NOSPACE);
  937                 goto badtoolate;
  938         }
  939 
  940         if (vfexec) {
  941                 old_map = vm_map_switch(get_task_map(task));
  942         }
  943 
  944         if (load_result.unixproc) {
  945                 user_addr_t     ap;
  946 
  947                 /*
  948                  * Copy the strings area out into the new process address
  949                  * space.
  950                  */
  951                 ap = p->user_stack;
  952                 error = exec_copyout_strings(imgp, &ap);
  953                 if (error) {
  954                         if (vfexec)
  955                                 vm_map_switch(old_map);
  956                         goto badtoolate;
  957                 }
  958                 /* Set the stack */
  959                 thread_setuserstack(thread, ap);
  960         }
  961         
  962         if (load_result.dynlinker) {
  963                 uint64_t        ap;
  964 
  965                 /* Adjust the stack */
  966                 if (imgp->ip_flags & IMGPF_IS_64BIT) {
  967                         ap = thread_adjuserstack(thread, -8);
  968                         error = copyoutptr(load_result.mach_header, ap, 8);
  969                 } else {
  970                         ap = thread_adjuserstack(thread, -4);
  971                         error = suword(ap, load_result.mach_header);
  972                 }
  973                 if (error) {
  974                         if (vfexec)
  975                                 vm_map_switch(old_map);
  976                         goto badtoolate;
  977                 }
  978         }
  979 
  980         if (vfexec) {
  981                 vm_map_switch(old_map);
  982         }
  983         /* Set the entry point */
  984         thread_setentrypoint(thread, load_result.entry_point);
  985 
  986         /* Stop profiling */
  987         stopprofclock(p);
  988 
  989         /*
  990          * Reset signal state.
  991          */
  992         execsigs(p, thread);
  993 
  994         /*
  995          * need to cancel async IO requests that can be cancelled and wait for those
  996          * already active.  MAY BLOCK!
  997          */
  998         _aio_exec( p );
  999 
 1000 #if SYSV_SHM
 1001         /* FIXME: Till vmspace inherit is fixed: */
 1002         if (!vfexec && p->vm_shm)
 1003                 shmexec(p);
 1004 #endif
 1005 #if SYSV_SEM
 1006         /* Clean up the semaphores */
 1007         semexit(p);
 1008 #endif
 1009 
 1010         /*
 1011          * Remember file name for accounting.
 1012          */
 1013         p->p_acflag &= ~AFORK;
 1014         /* If the translated name isn't NULL, then we want to use
 1015          * that translated name as the name we show as the "real" name.
 1016          * Otherwise, use the name passed into exec.
 1017          */
 1018         if (0 != imgp->ip_p_comm[0]) {
 1019                 bcopy((caddr_t)imgp->ip_p_comm, (caddr_t)p->p_comm,
 1020                         sizeof(p->p_comm));
 1021         } else {
 1022                 if (imgp->ip_ndp->ni_cnd.cn_namelen > MAXCOMLEN)
 1023                         imgp->ip_ndp->ni_cnd.cn_namelen = MAXCOMLEN;
 1024                 bcopy((caddr_t)imgp->ip_ndp->ni_cnd.cn_nameptr, (caddr_t)p->p_comm,
 1025                         (unsigned)imgp->ip_ndp->ni_cnd.cn_namelen);
 1026                 p->p_comm[imgp->ip_ndp->ni_cnd.cn_namelen] = '\0';
 1027         }
 1028 
 1029 #if CONFIG_DTRACE
 1030         /*
 1031          * Invalidate any predicate evaluation already cached for this thread by DTrace.
 1032          * That's because we've just stored to p_comm and DTrace refers to that when it
 1033          * evaluates the "execname" special variable. uid and gid may have changed as well.
 1034          */
 1035         dtrace_set_thread_predcache(current_thread(), 0);
 1036 
 1037         /*
 1038          * Free any outstanding lazy dof entries. It is imperative we
 1039          * always call dtrace_lazy_dofs_destroy, rather than null check
 1040          * and call if !NULL. If we NULL test, during lazy dof faulting
 1041          * we can race with the faulting code and proceed from here to
 1042          * beyond the helpers cleanup. The lazy dof faulting will then
 1043          * install new helpers which no longer belong to this process!
 1044          */
 1045         dtrace_lazy_dofs_destroy(p);
 1046 
 1047 
 1048         /*
 1049          * Clean up any DTrace helpers for the process.
 1050          */
 1051         if (p->p_dtrace_helpers != NULL && dtrace_helpers_cleanup) {
 1052                 (*dtrace_helpers_cleanup)(p);
 1053         }
 1054         
 1055         /*
 1056          * Cleanup the DTrace provider associated with this process.
 1057          */
 1058         proc_lock(p);
 1059         if (p->p_dtrace_probes && dtrace_fasttrap_exec_ptr) {
 1060                 (*dtrace_fasttrap_exec_ptr)(p);
 1061         }
 1062         proc_unlock(p);
 1063 #endif
 1064 
 1065         if (kdebug_enable) {
 1066                 long dbg_arg1, dbg_arg2, dbg_arg3, dbg_arg4;
 1067 
 1068                 /*
 1069                  * Collect the pathname for tracing
 1070                  */
 1071                 kdbg_trace_string(p, &dbg_arg1, &dbg_arg2, &dbg_arg3, &dbg_arg4);
 1072 
 1073                 if (vfexec) {
 1074                         KERNEL_DEBUG_CONSTANT1((TRACEDBG_CODE(DBG_TRACE_DATA, 2)) | DBG_FUNC_NONE,
 1075                                         p->p_pid ,0,0,0, (unsigned int)thread);
 1076                         KERNEL_DEBUG_CONSTANT1((TRACEDBG_CODE(DBG_TRACE_STRING, 2)) | DBG_FUNC_NONE,
 1077                                         dbg_arg1, dbg_arg2, dbg_arg3, dbg_arg4, (unsigned int)thread);
 1078                 } else {
 1079                         KERNEL_DEBUG_CONSTANT((TRACEDBG_CODE(DBG_TRACE_DATA, 2)) | DBG_FUNC_NONE,
 1080                                         p->p_pid ,0,0,0,0);
 1081                         KERNEL_DEBUG_CONSTANT((TRACEDBG_CODE(DBG_TRACE_STRING, 2)) | DBG_FUNC_NONE,
 1082                                         dbg_arg1, dbg_arg2, dbg_arg3, dbg_arg4, 0);
 1083                 }
 1084         }
 1085 
 1086 #ifdef IMGPF_POWERPC
 1087         /*
 1088          * Mark the process as powerpc or not.  If powerpc, set the affinity
 1089          * flag, which will be used for grading binaries in future exec's
 1090          * from the process.
 1091          */
 1092         if (((imgp->ip_flags & IMGPF_POWERPC) != 0))
 1093                 OSBitOrAtomic(P_TRANSLATED, (UInt32 *)&p->p_flag);
 1094         else
 1095 #endif  /* IMGPF_POWERPC */
 1096                 OSBitAndAtomic(~((uint32_t)P_TRANSLATED), (UInt32 *)&p->p_flag);
 1097         OSBitAndAtomic(~((uint32_t)P_AFFINITY), (UInt32 *)&p->p_flag);
 1098 
 1099         /*
 1100          * If posix_spawned with the START_SUSPENDED flag, stop the
 1101          * process before it runs.
 1102          */
 1103         if (imgp->ip_px_sa != NULL) {
 1104                 psa = (struct _posix_spawnattr *) imgp->ip_px_sa;
 1105                 if (psa->psa_flags & POSIX_SPAWN_START_SUSPENDED) {
 1106                         proc_lock(p);
 1107                         p->p_stat = SSTOP;
 1108                         proc_unlock(p);
 1109                         (void) task_suspend(p->task);
 1110                 }
 1111         }
 1112 
 1113         /*
 1114          * mark as execed, wakeup the process that vforked (if any) and tell
 1115          * it that it now has it's own resources back
 1116          */
 1117         OSBitOrAtomic(P_EXEC, (UInt32 *)&p->p_flag);
 1118         if (p->p_pptr && (p->p_lflag & P_LPPWAIT)) {
 1119                 proc_lock(p);
 1120                 p->p_lflag &= ~P_LPPWAIT;
 1121                 proc_unlock(p);
 1122                 wakeup((caddr_t)p->p_pptr);
 1123         }
 1124 
 1125         if (vfexec && (p->p_lflag & P_LTRACED)) {
 1126                 psignal_vfork(p, new_task, thread, SIGTRAP);
 1127         }
 1128 
 1129 badtoolate:
 1130         if (vfexec) {
 1131                 task_deallocate(new_task);
 1132                 thread_deallocate(thread);
 1133                 if (error)
 1134                         error = 0;
 1135         }
 1136 
 1137 bad:
 1138         return(error);
 1139 }
 1140 
 1141 
 1142 
 1143 
 1144 /*
 1145  * Our image activator table; this is the table of the image types we are
 1146  * capable of loading.  We list them in order of preference to ensure the
 1147  * fastest image load speed.
 1148  *
 1149  * XXX hardcoded, for now; should use linker sets
 1150  */
 1151 struct execsw {
 1152         int (*ex_imgact)(struct image_params *);
 1153         const char *ex_name;
 1154 } execsw[] = {
 1155         { exec_mach_imgact,             "Mach-o Binary" },
 1156         { exec_fat_imgact,              "Fat Binary" },
 1157 #ifdef IMGPF_POWERPC
 1158         { exec_powerpc32_imgact,        "PowerPC binary" },
 1159 #endif  /* IMGPF_POWERPC */
 1160         { exec_shell_imgact,            "Interpreter Script" },
 1161         { NULL, NULL}
 1162 };
 1163 
 1164 
 1165 /*
 1166  * exec_activate_image
 1167  *
 1168  * Description: Iterate through the available image activators, and activate
 1169  *              the image associated with the imgp structure.  We start with
 1170  *              the
 1171  *
 1172  * Parameters:  struct image_params *   Image parameter block
 1173  *
 1174  * Returns:     0                       Success
 1175  *              EBADEXEC                The executable is corrupt/unknown
 1176  *      execargs_alloc:EINVAL           Invalid argument
 1177  *      execargs_alloc:EACCES           Permission denied
 1178  *      execargs_alloc:EINTR            Interrupted function
 1179  *      execargs_alloc:ENOMEM           Not enough space
 1180  *      exec_save_path:EFAULT           Bad address
 1181  *      exec_save_path:ENAMETOOLONG     Filename too long
 1182  *      exec_check_permissions:EACCES   Permission denied
 1183  *      exec_check_permissions:ENOEXEC  Executable file format error
 1184  *      exec_check_permissions:ETXTBSY  Text file busy [misuse of error code]
 1185  *      exec_check_permissions:???
 1186  *      namei:???
 1187  *      vn_rdwr:???                     [anything vn_rdwr can return]
 1188  *      <ex_imgact>:???                 [anything an imgact can return]
 1189  */
 1190 static int
 1191 exec_activate_image(struct image_params *imgp)
 1192 {
 1193         struct nameidata nd;
 1194         int error;
 1195         int resid;
 1196         int once = 1;   /* save SGUID-ness for interpreted files */
 1197         int i;
 1198         int iterlimit = EAI_ITERLIMIT;
 1199 
 1200         error = execargs_alloc(imgp);
 1201         if (error)
 1202                 goto bad;
 1203         
 1204         /*
 1205          * XXXAUDIT: Note: the double copyin introduces an audit
 1206          * race.  To correct this race, we must use a single
 1207          * copyin(), e.g. by passing a flag to namei to indicate an
 1208          * external path buffer is being used.
 1209          */
 1210         error = exec_save_path(imgp, imgp->ip_user_fname, imgp->ip_seg);
 1211         if (error) {
 1212                 goto bad;
 1213         }
 1214 
 1215         DTRACE_PROC1(exec, uintptr_t, imgp->ip_strings);
 1216 
 1217         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNPATH1,
 1218                 imgp->ip_seg, imgp->ip_user_fname, imgp->ip_vfs_context);
 1219 
 1220 again:
 1221         error = namei(&nd);
 1222         if (error)
 1223                 goto bad;
 1224         imgp->ip_ndp = &nd;     /* successful namei(); call nameidone() later */
 1225         imgp->ip_vp = nd.ni_vp; /* if set, need to vnode_put() at some point */
 1226 
 1227         error = exec_check_permissions(imgp);
 1228         if (error)
 1229                 goto bad;
 1230 
 1231         /* Copy; avoid invocation of an interpreter overwriting the original */
 1232         if (once) {
 1233                 once = 0;
 1234                 *imgp->ip_origvattr = *imgp->ip_vattr;
 1235         }
 1236 
 1237         error = vn_rdwr(UIO_READ, imgp->ip_vp, imgp->ip_vdata, PAGE_SIZE, 0,
 1238                         UIO_SYSSPACE32, IO_NODELOCKED,
 1239                         vfs_context_ucred(imgp->ip_vfs_context),
 1240                         &resid, vfs_context_proc(imgp->ip_vfs_context));
 1241         if (error)
 1242                 goto bad;
 1243                 
 1244 encapsulated_binary:
 1245         /* Limit the number of iterations we will attempt on each binary */
 1246         if (--iterlimit == 0) {
 1247                 error = EBADEXEC;
 1248                 goto bad;
 1249         }
 1250         error = -1;
 1251         for(i = 0; error == -1 && execsw[i].ex_imgact != NULL; i++) {
 1252 
 1253                 error = (*execsw[i].ex_imgact)(imgp);
 1254 
 1255                 switch (error) {
 1256                 /* case -1: not claimed: continue */
 1257                 case -2:                /* Encapsulated binary */
 1258                         goto encapsulated_binary;
 1259 
 1260                 case -3:                /* Interpreter */
 1261 #if CONFIG_MACF
 1262                         /*
 1263                          * Copy the script label for later use. Note that
 1264                          * the label can be different when the script is
 1265                          * actually read by the interpreter.
 1266                          */
 1267                         if (imgp->ip_scriptlabelp)
 1268                                 mac_vnode_label_free(imgp->ip_scriptlabelp);
 1269                         imgp->ip_scriptlabelp = mac_vnode_label_alloc();
 1270                         if (imgp->ip_scriptlabelp == NULL) {
 1271                                 error = ENOMEM;
 1272                                 break;
 1273                         }
 1274                         mac_vnode_label_copy(imgp->ip_vp->v_label,
 1275                                     imgp->ip_scriptlabelp);
 1276 #endif
 1277                         vnode_put(imgp->ip_vp);
 1278                         imgp->ip_vp = NULL;     /* already put */
 1279                         nd.ni_cnd.cn_nameiop = LOOKUP;
 1280                         nd.ni_cnd.cn_flags = (nd.ni_cnd.cn_flags & HASBUF) |
 1281                                                 (FOLLOW | LOCKLEAF);
 1282 
 1283 #ifdef IMGPF_POWERPC
 1284                         /*
 1285                          * PowerPC does not follow symlinks because the
 1286                          * code which sets exec_archhandler_ppc.fsid and
 1287                          * exec_archhandler_ppc.fileid doesn't follow them.
 1288                          */
 1289                         if (imgp->ip_flags & IMGPF_POWERPC)
 1290                                 nd.ni_cnd.cn_flags &= ~FOLLOW;
 1291 #endif  /* IMGPF_POWERPC */
 1292 
 1293                         nd.ni_segflg = UIO_SYSSPACE32;
 1294                         nd.ni_dirp = CAST_USER_ADDR_T(imgp->ip_interp_name);
 1295                         goto again;
 1296 
 1297                 default:
 1298                         break;
 1299                 }
 1300         }
 1301 
 1302         /*
 1303          * Call out to allow 3rd party notification of exec. 
 1304          * Ignore result of kauth_authorize_fileop call.
 1305          */
 1306         if (error == 0 && kauth_authorize_fileop_has_listeners()) {
 1307                 kauth_authorize_fileop(vfs_context_ucred(imgp->ip_vfs_context),
 1308                                         KAUTH_FILEOP_EXEC,
 1309                                         (uintptr_t)nd.ni_vp, 0);
 1310         }
 1311 
 1312 bad:
 1313         if (imgp->ip_strings)
 1314                 execargs_free(imgp);
 1315         if (imgp->ip_ndp)
 1316                 nameidone(imgp->ip_ndp);
 1317 
 1318         return (error);
 1319 }
 1320 
 1321 /*
 1322  * exec_handle_port_actions
 1323  *
 1324  * Description: Go through the _posix_port_actions_t contents, 
 1325  *              calling task_set_special_port and task_set_exception_ports
 1326  *              for the current task.
 1327  *
 1328  * Parameters:  struct image_params *   Image parameter block
 1329  *
 1330  * Returns:     0                       Success
 1331  *              KERN_FAILURE            Failure
 1332  */
 1333 static int
 1334 exec_handle_port_actions(struct image_params *imgp)
 1335 {
 1336         _posix_spawn_port_actions_t pacts = imgp->ip_px_spa;
 1337         proc_t p = vfs_context_proc(imgp->ip_vfs_context);
 1338         _ps_port_action_t *act = NULL;
 1339         task_t task = p->task;
 1340         ipc_port_t port = NULL;
 1341         kern_return_t ret = KERN_SUCCESS;
 1342         int i;
 1343 
 1344         for (i = 0; i < pacts->pspa_count; i++) {
 1345                 act = &pacts->pspa_actions[i];
 1346 
 1347                 ret = ipc_object_copyin(get_task_ipcspace(current_task()),
 1348                                 (mach_port_name_t) act->new_port,
 1349                                 MACH_MSG_TYPE_COPY_SEND,
 1350                                 (ipc_object_t *) &port);
 1351 
 1352                 if (ret)                        
 1353                         return ret;
 1354 
 1355                 switch (act->port_type) {
 1356                         case PSPA_SPECIAL:
 1357                                 ret = task_set_special_port(task, 
 1358                                                 act->which, 
 1359                                                 port);
 1360                                 break;
 1361                         case PSPA_EXCEPTION:
 1362                                 ret = task_set_exception_ports(task, 
 1363                                                 act->mask,
 1364                                                 port, 
 1365                                                 act->behavior, 
 1366                                                 act->flavor);
 1367                                 break;
 1368                         default:
 1369                                 ret = KERN_FAILURE;
 1370                 }
 1371                 /* action failed, so release port resources */
 1372                 if (ret) { 
 1373                         ipc_port_release_send(port);
 1374                         return ret;
 1375                 }
 1376         }
 1377 
 1378         return ret;
 1379 }
 1380 
 1381 /*
 1382  * exec_handle_file_actions
 1383  *
 1384  * Description: Go through the _posix_file_actions_t contents applying the
 1385  *              open, close, and dup2 operations to the open file table for
 1386  *              the current process.
 1387  *
 1388  * Parameters:  struct image_params *   Image parameter block
 1389  *
 1390  * Returns:     0                       Success
 1391  *              ???
 1392  *
 1393  * Note:        Actions are applied in the order specified, with the credential
 1394  *              of the parent process.  This is done to permit the parent
 1395  *              process to utilize POSIX_SPAWN_RESETIDS to drop privilege in
 1396  *              the child following operations the child may in fact not be
 1397  *              normally permitted to perform.
 1398  */
 1399 static int
 1400 exec_handle_file_actions(struct image_params *imgp)
 1401 {
 1402         int error = 0;
 1403         int action;
 1404         proc_t p = vfs_context_proc(imgp->ip_vfs_context);
 1405         _posix_spawn_file_actions_t px_sfap = imgp->ip_px_sfa;
 1406         register_t ival[2];             /* dummy retval for system calls) */
 1407 
 1408         for (action = 0; action < px_sfap->psfa_act_count; action++) {
 1409                 _psfa_action_t *psfa = &px_sfap->psfa_act_acts[ action];
 1410 
 1411                 switch(psfa->psfaa_type) {
 1412                 case PSFA_OPEN: {
 1413                         /*
 1414                          * Open is different, in that it requires the use of
 1415                          * a path argument, which is normally copied in from
 1416                          * user space; because of this, we have to support an
 1417                          * open from kernel space that passes an address space
 1418                          * context oof UIO_SYSSPACE, and casts the address
 1419                          * argument to a user_addr_t.
 1420                          */
 1421                         struct vnode_attr va;
 1422                         struct nameidata nd;
 1423                         int mode = psfa->psfaa_openargs.psfao_mode;
 1424                         struct dup2_args dup2a;
 1425                         struct close_nocancel_args ca;
 1426                         int origfd;
 1427 
 1428                         VATTR_INIT(&va);
 1429                         /* Mask off all but regular access permissions */
 1430                         mode = ((mode &~ p->p_fd->fd_cmask) & ALLPERMS) & ~S_ISTXT;
 1431                         VATTR_SET(&va, va_mode, mode & ACCESSPERMS);
 1432 
 1433                         NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNPATH1, UIO_SYSSPACE,
 1434                                CAST_USER_ADDR_T(psfa->psfaa_openargs.psfao_path),
 1435                                imgp->ip_vfs_context);
 1436 
 1437                         error = open1(imgp->ip_vfs_context, 
 1438                                         &nd,
 1439                                         psfa->psfaa_openargs.psfao_oflag,
 1440                                         &va,
 1441                                         ival);
 1442 
 1443                         /*
 1444                          * If there's an error, or we get the right fd by
 1445                          * accident, then drop out here.  This is easier that
 1446                          * rearchitecting all the open code to preallocate fd
 1447                          * slots, and internally taking one as an argument.
 1448                          */
 1449                         if (error || ival[0] == psfa->psfaa_filedes)
 1450                                 break;
 1451 
 1452                         origfd = ival[0];
 1453                         /*
 1454                          * If we didn't fall out from an error, we ended up
 1455                          * with the wrong fd; so now we've got to try to dup2
 1456                          * it to the right one.
 1457                          */
 1458                         dup2a.from = origfd;
 1459                         dup2a.to = psfa->psfaa_filedes;
 1460 
 1461                         /*
 1462                          * The dup2() system call implementation sets
 1463                          * ival to newfd in the success case, but we
 1464                          * can ignore that, since if we didn't get the
 1465                          * fd we wanted, the error will stop us.
 1466                          */
 1467                         error = dup2(p, &dup2a, ival);
 1468                         if (error)
 1469                                 break;
 1470 
 1471                         /*
 1472                          * Finally, close the original fd.
 1473                          */
 1474                         ca.fd = origfd;
 1475 
 1476                         error = close_nocancel(p, &ca, ival);
 1477                         }
 1478                         break;
 1479 
 1480                 case PSFA_DUP2: {
 1481                         struct dup2_args dup2a;
 1482 
 1483                         dup2a.from = psfa->psfaa_filedes;
 1484                         dup2a.to = psfa->psfaa_openargs.psfao_oflag;
 1485 
 1486                         /*
 1487                          * The dup2() system call implementation sets
 1488                          * ival to newfd in the success case, but we
 1489                          * can ignore that, since if we didn't get the
 1490                          * fd we wanted, the error will stop us.
 1491                          */
 1492                         error = dup2(p, &dup2a, ival);
 1493                         }
 1494                         break;
 1495 
 1496                 case PSFA_CLOSE: {
 1497                         struct close_nocancel_args ca;
 1498 
 1499                         ca.fd = psfa->psfaa_filedes;
 1500 
 1501                         error = close_nocancel(p, &ca, ival);
 1502                         }
 1503                         break;
 1504 
 1505                 default:
 1506                         error = EINVAL;
 1507                         break;
 1508                 }
 1509                 /* All file actions failures are considered fatal, per POSIX */
 1510                 if (error)
 1511                         break;
 1512         }
 1513 
 1514         return (error);
 1515 }
 1516 
 1517 
 1518 /*
 1519  * posix_spawn
 1520  *
 1521  * Parameters:  uap->pid                Pointer to pid return area
 1522  *              uap->fname              File name to exec
 1523  *              uap->argp               Argument list
 1524  *              uap->envp               Environment list
 1525  *
 1526  * Returns:     0                       Success
 1527  *              EINVAL                  Invalid argument
 1528  *              ENOTSUP                 Not supported
 1529  *              ENOEXEC                 Executable file format error
 1530  *      exec_activate_image:EINVAL      Invalid argument
 1531  *      exec_activate_image:EACCES      Permission denied
 1532  *      exec_activate_image:EINTR       Interrupted function
 1533  *      exec_activate_image:ENOMEM      Not enough space
 1534  *      exec_activate_image:EFAULT      Bad address
 1535  *      exec_activate_image:ENAMETOOLONG        Filename too long
 1536  *      exec_activate_image:ENOEXEC     Executable file format error
 1537  *      exec_activate_image:ETXTBSY     Text file busy [misuse of error code]
 1538  *      exec_activate_image:EBADEXEC    The executable is corrupt/unknown
 1539  *      exec_activate_image:???
 1540  *      mac_execve_enter:???
 1541  *
 1542  * TODO:        More gracefully handle failures after vfork
 1543  *              Expect to need __mac_posix_spawn() at some point...
 1544  *              Handle posix_spawnattr_t
 1545  *              Handle posix_spawn_file_actions_t
 1546  */
 1547 int
 1548 posix_spawn(proc_t ap, struct posix_spawn_args *uap, register_t *retval)
 1549 {
 1550         proc_t p = ap;          /* quiet bogus GCC vfork() warning */
 1551         register_t ival[2];             /* dummy retval for vfork() */
 1552         struct image_params image_params, *imgp;
 1553         struct vnode_attr va;
 1554         struct vnode_attr origva;
 1555         struct uthread  *uthread = 0;   /* compiler complains if not set to 0*/
 1556         int error, sig;
 1557         task_t  task;
 1558         int numthreads;
 1559         char alt_p_comm[sizeof(p->p_comm)] = {0};       /* for PowerPC */
 1560         int is_64 = IS_64BIT_PROCESS(p);
 1561         int undo_vfork = 0;
 1562         struct vfs_context context;
 1563         struct user__posix_spawn_args_desc px_args;
 1564         struct _posix_spawnattr px_sa;
 1565         _posix_spawn_file_actions_t px_sfap = NULL;
 1566         _posix_spawn_port_actions_t px_spap = NULL;
 1567         struct __user_sigaction vec;
 1568 
 1569         imgp = &image_params;
 1570 
 1571         /* Initialize the common data in the image_params structure */
 1572         bzero(imgp, sizeof(*imgp));
 1573         imgp->ip_user_fname = uap->path;
 1574         imgp->ip_user_argv = uap->argv;
 1575         imgp->ip_user_envv = uap->envp;
 1576         imgp->ip_vattr = &va;
 1577         imgp->ip_origvattr = &origva;
 1578         imgp->ip_vfs_context = &context;
 1579         imgp->ip_flags = (is_64 ? IMGPF_WAS_64BIT : IMGPF_NONE);
 1580         imgp->ip_p_comm = alt_p_comm;           /* for PowerPC */
 1581         imgp->ip_seg = (is_64 ? UIO_USERSPACE64 : UIO_USERSPACE32);
 1582 
 1583         if (uap->adesc != USER_ADDR_NULL) {
 1584                 if(is_64) {
 1585                         error = copyin(uap->adesc, &px_args, sizeof(px_args));
 1586                 } else {
 1587                         struct _posix_spawn_args_desc px_args32;
 1588 
 1589                         error = copyin(uap->adesc, &px_args32, sizeof(px_args32));
 1590 
 1591                         /*
 1592                          * Convert arguments descriptor from external 32 bit
 1593                          * representation to internal 64 bit representation
 1594                          */
 1595                         px_args.attr_size = px_args32.attr_size;
 1596                         px_args.attrp = CAST_USER_ADDR_T(px_args32.attrp);
 1597                         px_args.file_actions_size = px_args32.file_actions_size;
 1598                         px_args.file_actions = CAST_USER_ADDR_T(px_args32.file_actions);
 1599                         px_args.port_actions_size = px_args32.port_actions_size;
 1600                         px_args.port_actions = CAST_USER_ADDR_T(px_args32.port_actions);
 1601                 }
 1602                 if (error)
 1603                         goto bad;
 1604 
 1605                 if (px_args.attr_size != 0) {
 1606                         /* 
 1607                          * This could lose some of the port_actions pointer, 
 1608                          * but we already have it from px_args. 
 1609                          */
 1610                         if ((error = copyin(px_args.attrp, &px_sa, sizeof(px_sa))) != 0)
 1611                         goto bad;
 1612 
 1613                         imgp->ip_px_sa = &px_sa;
 1614                 }
 1615                 if (px_args.file_actions_size != 0) {
 1616                         /* Limit file_actions to allowed number of open files */
 1617                         int maxfa = (p->p_limit ? p->p_rlimit[RLIMIT_NOFILE].rlim_cur : NOFILE);
 1618                         if (px_args.file_actions_size < PSF_ACTIONS_SIZE(1) ||
 1619                                 px_args.file_actions_size > PSF_ACTIONS_SIZE(maxfa)) {
 1620                                 error = EINVAL;
 1621                                 goto bad;
 1622                         }
 1623                         MALLOC(px_sfap, _posix_spawn_file_actions_t, px_args.file_actions_size, M_TEMP, M_WAITOK);
 1624                         if (px_sfap == NULL) {
 1625                                 error = ENOMEM;
 1626                                 goto bad;
 1627                         }
 1628                         imgp->ip_px_sfa = px_sfap;
 1629 
 1630                         if ((error = copyin(px_args.file_actions, px_sfap, 
 1631                                                         px_args.file_actions_size)) != 0)
 1632                                 goto bad;
 1633                 }
 1634                 if (px_args.port_actions_size != 0) {
 1635                         /* Limit port_actions to one page of data */
 1636                         if (px_args.port_actions_size < PS_PORT_ACTIONS_SIZE(1) ||
 1637                                 px_args.port_actions_size > PAGE_SIZE) {
 1638                                 error = EINVAL;
 1639                                 goto bad;
 1640                         }
 1641 
 1642                         MALLOC(px_spap, _posix_spawn_port_actions_t, 
 1643                                         px_args.port_actions_size, M_TEMP, M_WAITOK);
 1644                         if (px_spap == NULL) {
 1645                                 error = ENOMEM;
 1646                                 goto bad;
 1647                         }
 1648                         imgp->ip_px_spa = px_spap;
 1649 
 1650                         if ((error = copyin(px_args.port_actions, px_spap, 
 1651                                                         px_args.port_actions_size)) != 0)
 1652                                 goto bad;
 1653                 }
 1654         }
 1655 
 1656         if (imgp->ip_px_sa == NULL || !(px_sa.psa_flags & POSIX_SPAWN_SETEXEC)){
 1657                 if ((error = vfork(p, NULL, ival)) != 0)
 1658                         goto bad;
 1659                 undo_vfork = 1;
 1660         }
 1661 
 1662         /* "reenter the kernel" on a new vfork()'ed process */
 1663         uthread = get_bsdthread_info(current_thread());
 1664         if (undo_vfork)
 1665                 p = uthread->uu_proc;
 1666 
 1667         context.vc_thread = current_thread();
 1668         context.vc_ucred = p->p_ucred;  /* XXX must NOT be kauth_cred_get() */
 1669 
 1670         /*
 1671          * Post fdcopy(), pre exec_handle_sugid() - this is where we want
 1672          * to handle the file_actions.  Since vfork() also ends up setting
 1673          * us into the parent process group, and saved off the signal flags,
 1674          * this is also where we want to handle the spawn flags.
 1675          */
 1676         /* Has spawn file actions? */
 1677         if (imgp->ip_px_sfa != NULL &&
 1678             (error = exec_handle_file_actions(imgp)) != 0) {
 1679                 goto bad;
 1680         }
 1681 
 1682         /* Has spawn port actions? */
 1683         if (imgp->ip_px_spa != NULL) { 
 1684                 /* Only allowed when not under vfork */
 1685                 if (!(px_sa.psa_flags & POSIX_SPAWN_SETEXEC)) {
 1686                         error = ENOTSUP;
 1687                         goto bad;
 1688                 }
 1689                 if((error = exec_handle_port_actions(imgp)) != 0) 
 1690                         goto bad;
 1691         }
 1692 
 1693         /* Has spawn attr? */
 1694         if (imgp->ip_px_sa != NULL) {
 1695                 /* Set the process group ID of the child process */
 1696                 if (px_sa.psa_flags & POSIX_SPAWN_SETPGROUP) {
 1697                         struct setpgid_args spga;
 1698                         spga.pid = p->p_pid;
 1699                         spga.pgid = px_sa.psa_pgroup;
 1700                         /*
 1701                          * Effectively, call setpgid() system call; works
 1702                          * because there are no pointer arguments.
 1703                          */
 1704                         if((error = setpgid(p, &spga, ival)) != 0)
 1705                                 goto bad;
 1706                 }
 1707                 /*
 1708                  * Reset UID/GID to parent's RUID/RGID; This works only
 1709                  * because the operation occurs *after* the vfork() and
 1710                  * before the call to exec_handle_sugid() by the image
 1711                  * activator called from exec_activate_image().
 1712                  *
 1713                  * The use of p_ucred is safe, since we are acting on the
 1714                  * new process, and it has no threads other than the one
 1715                  * we are creating for it.
 1716                  */
 1717                 if (px_sa.psa_flags & POSIX_SPAWN_RESETIDS) {
 1718                         kauth_cred_t my_cred = p->p_ucred;
 1719                         kauth_cred_t my_new_cred = kauth_cred_setuidgid(my_cred, my_cred->cr_ruid, my_cred->cr_rgid);
 1720                         if (my_new_cred != my_cred)
 1721                                 p->p_ucred = my_new_cred;
 1722                 }
 1723                 /*
 1724                  * Mask a list of signals, instead of them being unmasked, if
 1725                  * they were unmasked in the parent; note that some signals
 1726                  * are not maskable.
 1727                  */
 1728                 if (px_sa.psa_flags & POSIX_SPAWN_SETSIGMASK)
 1729                         uthread->uu_sigmask = (px_sa.psa_sigmask & ~sigcantmask);
 1730                 /*
 1731                  * Default a list of signals instead of ignoring them, if
 1732                  * they were ignored in the parent.
 1733                  */
 1734                 if (px_sa.psa_flags & POSIX_SPAWN_SETSIGDEF) {
 1735                         vec.sa_handler = SIG_DFL;
 1736                         vec.sa_tramp = 0;
 1737                         vec.sa_mask = 0;
 1738                         vec.sa_flags = 0;
 1739                         for (sig = 0; sig < NSIG; sig++)
 1740                                 if (px_sa.psa_sigdefault && 1 << sig) {
 1741                                         error = setsigvec(p, sig, &vec);
 1742                         }
 1743                 }
 1744         }
 1745 
 1746         /*
 1747          * XXXAUDIT: Currently, we only audit the pathname of the binary.
 1748          * There may also be poor interaction with dyld.
 1749          */
 1750 
 1751         task = current_task();
 1752 
 1753         /* If we're not in vfork, don't permit a mutithreaded task to exec */
 1754         if (!(uthread->uu_flag & UT_VFORK)) {
 1755                 if (task != kernel_task) { 
 1756                         numthreads = get_task_numacts(task);
 1757                         if (numthreads <= 0 ) {
 1758                                 error = EINVAL;
 1759                                 goto bad;
 1760                         }
 1761                         if (numthreads > 1) {
 1762                                 error = ENOTSUP;
 1763                                 goto bad;
 1764                         }
 1765                 }
 1766         }
 1767 
 1768 #if MAC_SPAWN   /* XXX */
 1769         if (uap->mac_p != USER_ADDR_NULL) {
 1770                 error = mac_execve_enter(uap->mac_p, imgp);
 1771                 if (error)
 1772                         goto bad;
 1773         }
 1774 #endif
 1775 
 1776         if ((error = exec_activate_image(imgp)) != 0) 
 1777                 goto bad;
 1778 bad:
 1779         /* Image not claimed by any activator? */
 1780         if (error == -1)
 1781                 error = ENOEXEC;
 1782         if (error == 0) {
 1783                 exec_resettextvp(p, imgp);
 1784         }       
 1785         if (imgp->ip_vp)
 1786                 vnode_put(imgp->ip_vp);
 1787         if (imgp->ip_strings)
 1788                 execargs_free(imgp);
 1789         if (imgp->ip_px_sfa != NULL)
 1790                 FREE(imgp->ip_px_sfa, M_TEMP);
 1791         if (imgp->ip_px_spa != NULL)
 1792                 FREE(imgp->ip_px_spa, M_TEMP);
 1793 
 1794 #if CONFIG_MACF
 1795         if (imgp->ip_execlabelp)
 1796                 mac_cred_label_free(imgp->ip_execlabelp);
 1797         if (imgp->ip_scriptlabelp)
 1798                 mac_vnode_label_free(imgp->ip_scriptlabelp);
 1799 #endif
 1800         if (undo_vfork) {
 1801                 if (error) {
 1802                         DTRACE_PROC1(exec__failure, int, error);
 1803                         vfork_exit(p, W_EXITCODE(-1, 0));
 1804                 } else {
 1805                         DTRACE_PROC(exec__success);
 1806                 }
 1807                 /*
 1808                  * Returning to the parent process...
 1809                  *
 1810                  * If the parent wants the pid, copy it out
 1811                  */
 1812                 if (uap->pid != USER_ADDR_NULL)
 1813                         (void)suword(uap->pid, p->p_pid);
 1814                 retval[0] = error;
 1815                 /*
 1816                  * Override inherited code signing flags with the
 1817                  * ones for the process that is being successfully
 1818                  * loaded
 1819                  */
 1820                 proc_lock(p);
 1821                 p->p_csflags = imgp->ip_csflags;
 1822                 proc_unlock(p);
 1823                 vfork_return(p, NULL, error);
 1824                 (void)thread_resume(imgp->ip_vfork_thread);
 1825         }
 1826 
 1827         if (!error) {
 1828                 /*
 1829                  * Override inherited code signing flags with the
 1830                  * ones for the process that is being successfully
 1831                  * loaded
 1832                  */
 1833                 proc_lock(p);
 1834                 p->p_csflags = imgp->ip_csflags;
 1835                 proc_unlock(p);
 1836                 DTRACE_PROC(exec__success);
 1837         } else {
 1838                 DTRACE_PROC1(exec__failure, int, error);
 1839         }
 1840 
 1841         return(error);
 1842 }
 1843 
 1844 
 1845 /*
 1846  * execve
 1847  *
 1848  * Parameters:  uap->fname              File name to exec
 1849  *              uap->argp               Argument list
 1850  *              uap->envp               Environment list
 1851  *
 1852  * Returns:     0                       Success
 1853  *      __mac_execve:EINVAL             Invalid argument
 1854  *      __mac_execve:ENOTSUP            Invalid argument
 1855  *      __mac_execve:EACCES             Permission denied
 1856  *      __mac_execve:EINTR              Interrupted function
 1857  *      __mac_execve:ENOMEM             Not enough space
 1858  *      __mac_execve:EFAULT             Bad address
 1859  *      __mac_execve:ENAMETOOLONG       Filename too long
 1860  *      __mac_execve:ENOEXEC            Executable file format error
 1861  *      __mac_execve:ETXTBSY            Text file busy [misuse of error code]
 1862  *      __mac_execve:???
 1863  *
 1864  * TODO:        Dynamic linker header address on stack is copied via suword()
 1865  */
 1866 /* ARGSUSED */
 1867 int
 1868 execve(proc_t p, struct execve_args *uap, register_t *retval)
 1869 {
 1870         struct __mac_execve_args muap;
 1871         int err;
 1872 
 1873         muap.fname = uap->fname;
 1874         muap.argp = uap->argp;
 1875         muap.envp = uap->envp;
 1876         muap.mac_p = USER_ADDR_NULL;
 1877         err = __mac_execve(p, &muap, retval);
 1878 
 1879         return(err);
 1880 }
 1881 
 1882 /*
 1883  * __mac_execve
 1884  *
 1885  * Parameters:  uap->fname              File name to exec
 1886  *              uap->argp               Argument list
 1887  *              uap->envp               Environment list
 1888  *              uap->mac_p              MAC label supplied by caller
 1889  *
 1890  * Returns:     0                       Success
 1891  *              EINVAL                  Invalid argument
 1892  *              ENOTSUP                 Not supported
 1893  *              ENOEXEC                 Executable file format error
 1894  *      exec_activate_image:EINVAL      Invalid argument
 1895  *      exec_activate_image:EACCES      Permission denied
 1896  *      exec_activate_image:EINTR       Interrupted function
 1897  *      exec_activate_image:ENOMEM      Not enough space
 1898  *      exec_activate_image:EFAULT      Bad address
 1899  *      exec_activate_image:ENAMETOOLONG        Filename too long
 1900  *      exec_activate_image:ENOEXEC     Executable file format error
 1901  *      exec_activate_image:ETXTBSY     Text file busy [misuse of error code]
 1902  *      exec_activate_image:EBADEXEC    The executable is corrupt/unknown
 1903  *      exec_activate_image:???
 1904  *      mac_execve_enter:???
 1905  *
 1906  * TODO:        Dynamic linker header address on stack is copied via suword()
 1907  */
 1908 int
 1909 __mac_execve(proc_t p, struct __mac_execve_args *uap, register_t *retval)
 1910 {
 1911         struct image_params image_params, *imgp;
 1912         struct vnode_attr va;
 1913         struct vnode_attr origva;
 1914         struct uthread          *uthread;
 1915         int error;
 1916         task_t  task;
 1917         int numthreads;
 1918         char alt_p_comm[sizeof(p->p_comm)] = {0};       /* for PowerPC */
 1919         int is_64 = IS_64BIT_PROCESS(p);
 1920         struct vfs_context context;
 1921 
 1922         context.vc_thread = current_thread();
 1923         context.vc_ucred = kauth_cred_proc_ref(p);      /* XXX must NOT be kauth_cred_get() */
 1924 
 1925         imgp = &image_params;
 1926 
 1927         /* Initialize the common data in the image_params structure */
 1928         bzero(imgp, sizeof(*imgp));
 1929         imgp->ip_user_fname = uap->fname;
 1930         imgp->ip_user_argv = uap->argp;
 1931         imgp->ip_user_envv = uap->envp;
 1932         imgp->ip_vattr = &va;
 1933         imgp->ip_origvattr = &origva;
 1934         imgp->ip_vfs_context = &context;
 1935         imgp->ip_flags = (is_64 ? IMGPF_WAS_64BIT : IMGPF_NONE);
 1936         imgp->ip_p_comm = alt_p_comm;           /* for PowerPC */
 1937         imgp->ip_seg = (is_64 ? UIO_USERSPACE64 : UIO_USERSPACE32);
 1938 
 1939         /*
 1940          * XXXAUDIT: Currently, we only audit the pathname of the binary.
 1941          * There may also be poor interaction with dyld.
 1942          */
 1943 
 1944         task = current_task();
 1945         uthread = get_bsdthread_info(current_thread());
 1946 
 1947         /* If we're not in vfork, don't permit a mutithreaded task to exec */
 1948         if (!(uthread->uu_flag & UT_VFORK)) {
 1949                 if (task != kernel_task) { 
 1950                         proc_lock(p);
 1951                         numthreads = get_task_numacts(task);
 1952                         if (numthreads <= 0 ) {
 1953                                 proc_unlock(p);
 1954                                 kauth_cred_unref(&context.vc_ucred);
 1955                                 return(EINVAL);
 1956                         }
 1957                         if (numthreads > 1) {
 1958                                 proc_unlock(p);
 1959                                 kauth_cred_unref(&context.vc_ucred);
 1960                                 return(ENOTSUP);
 1961                         }
 1962                         proc_unlock(p);
 1963                 }
 1964         }
 1965 
 1966 #if CONFIG_MACF
 1967         if (uap->mac_p != USER_ADDR_NULL) {
 1968                 error = mac_execve_enter(uap->mac_p, imgp);
 1969                 if (error) {
 1970                         kauth_cred_unref(&context.vc_ucred);
 1971                         return (error);
 1972                 }
 1973         }
 1974 #endif
 1975 
 1976         proc_transstart(p, 0);
 1977         error = exec_activate_image(imgp);
 1978         proc_transend(p, 0);
 1979 
 1980         kauth_cred_unref(&context.vc_ucred);
 1981         
 1982         /* Image not claimed by any activator? */
 1983         if (error == -1)
 1984                 error = ENOEXEC;
 1985 
 1986         if (error == 0) {
 1987                 exec_resettextvp(p, imgp);
 1988         }       
 1989         if (imgp->ip_vp != NULLVP)
 1990                 vnode_put(imgp->ip_vp);
 1991         if (imgp->ip_strings)
 1992                 execargs_free(imgp);
 1993 #if CONFIG_MACF
 1994         if (imgp->ip_execlabelp)
 1995                 mac_cred_label_free(imgp->ip_execlabelp);
 1996         if (imgp->ip_scriptlabelp)
 1997                 mac_vnode_label_free(imgp->ip_scriptlabelp);
 1998 #endif
 1999         if (!error) {
 2000                 /*
 2001                  * Override inherited code signing flags with the
 2002                  * ones for the process that is being successfully
 2003                  * loaded
 2004                  */
 2005                 proc_lock(p);
 2006                 p->p_csflags = imgp->ip_csflags;
 2007                 proc_unlock(p);
 2008                 DTRACE_PROC(exec__success);
 2009 
 2010                 if (uthread->uu_flag & UT_VFORK) {
 2011                         vfork_return(p, retval, p->p_pid);
 2012                         (void)thread_resume(imgp->ip_vfork_thread);
 2013                 }
 2014         } else {
 2015                 DTRACE_PROC1(exec__failure, int, error);
 2016         }
 2017         
 2018         return(error);
 2019 }
 2020 
 2021 
 2022 /*
 2023  * copyinptr
 2024  *
 2025  * Description: Copy a pointer in from user space to a user_addr_t in kernel
 2026  *              space, based on 32/64 bitness of the user space
 2027  *
 2028  * Parameters:  froma                   User space address
 2029  *              toptr                   Address of kernel space user_addr_t
 2030  *              ptr_size                4/8, based on 'froma' address space
 2031  *
 2032  * Returns:     0                       Success
 2033  *              EFAULT                  Bad 'froma'
 2034  *
 2035  * Implicit returns:
 2036  *              *ptr_size               Modified
 2037  */
 2038 static int
 2039 copyinptr(user_addr_t froma, user_addr_t *toptr, int ptr_size)
 2040 {
 2041         int error;
 2042 
 2043         if (ptr_size == 4) {
 2044                 /* 64 bit value containing 32 bit address */
 2045                 unsigned int i;
 2046 
 2047                 error = copyin(froma, &i, 4);
 2048                 *toptr = CAST_USER_ADDR_T(i);   /* SAFE */
 2049         } else {
 2050                 error = copyin(froma, toptr, 8);
 2051         }
 2052         return (error);
 2053 }
 2054 
 2055 
 2056 /*
 2057  * copyoutptr
 2058  *
 2059  * Description: Copy a pointer out from a user_addr_t in kernel space to
 2060  *              user space, based on 32/64 bitness of the user space
 2061  *
 2062  * Parameters:  ua                      User space address to copy to
 2063  *              ptr                     Address of kernel space user_addr_t
 2064  *              ptr_size                4/8, based on 'ua' address space
 2065  *
 2066  * Returns:     0                       Success
 2067  *              EFAULT                  Bad 'ua'
 2068  *
 2069  * Implicit returns:
 2070  *              *ptr_size               Modified
 2071  */
 2072 static int
 2073 copyoutptr(user_addr_t ua, user_addr_t ptr, int ptr_size)
 2074 {
 2075         int error;
 2076 
 2077         if (ptr_size == 4) {
 2078                 /* 64 bit value containing 32 bit address */
 2079                 unsigned int i = CAST_DOWN(unsigned int,ua);    /* SAFE */
 2080 
 2081                 error = copyout(&i, ptr, 4);
 2082         } else {
 2083                 error = copyout(&ua, ptr, 8);
 2084         }
 2085         return (error);
 2086 }
 2087 
 2088 
 2089 /*
 2090  * exec_copyout_strings
 2091  *
 2092  * Copy out the strings segment to user space.  The strings segment is put
 2093  * on a preinitialized stack frame.
 2094  *
 2095  * Parameters:  struct image_params *   the image parameter block
 2096  *              int *                   a pointer to the stack offset variable
 2097  *
 2098  * Returns:     0                       Success
 2099  *              !0                      Faiure: errno
 2100  *
 2101  * Implicit returns:
 2102  *              (*stackp)               The stack offset, modified
 2103  *
 2104  * Note:        The strings segment layout is backward, from the beginning
 2105  *              of the top of the stack to consume the minimal amount of
 2106  *              space possible; the returned stack pointer points to the
 2107  *              end of the area consumed (stacks grow upward).
 2108  *
 2109  *              argc is an int; arg[i] are pointers; env[i] are pointers;
 2110  *              exec_path is a pointer; the 0's are (void *)NULL's
 2111  *
 2112  * The stack frame layout is:
 2113  *
 2114  *      +-------------+
 2115  * sp-> |     argc    |
 2116  *      +-------------+
 2117  *      |    arg[0]   |
 2118  *      +-------------+
 2119  *             :
 2120  *             :
 2121  *      +-------------+
 2122  *      | arg[argc-1] |
 2123  *      +-------------+
 2124  *      |      0      |
 2125  *      +-------------+
 2126  *      |    env[0]   |
 2127  *      +-------------+
 2128  *             :
 2129  *             :
 2130  *      +-------------+
 2131  *      |    env[n]   |
 2132  *      +-------------+
 2133  *      |      0      |
 2134  *      +-------------+
 2135  *      |  exec_path  | In MacOS X PR2 Beaker2E the path passed to exec() is
 2136  *      +-------------+ passed on the stack just after the trailing 0 of the
 2137  *      |      0      | the envp[] array as a pointer to a string.
 2138  *      +-------------+
 2139  *      |  PATH AREA  |
 2140  *      +-------------+
 2141  *      | STRING AREA |
 2142  *             :
 2143  *             :
 2144  *      |             | <- p->user_stack
 2145  *      +-------------+
 2146  *
 2147  * Although technically a part of the STRING AREA, we treat the PATH AREA as
 2148  * a separate entity.  This allows us to align the beginning of the PATH AREA
 2149  * to a pointer boundary so that the exec_path, env[i], and argv[i] pointers
 2150  * which preceed it on the stack are properly aligned.
 2151  *
 2152  * TODO:        argc copied with suword(), which takes a 64 bit address
 2153  */
 2154 static int
 2155 exec_copyout_strings(struct image_params *imgp, user_addr_t *stackp)
 2156 {
 2157         proc_t p = vfs_context_proc(imgp->ip_vfs_context);
 2158         int     ptr_size = (imgp->ip_flags & IMGPF_IS_64BIT) ? 8 : 4;
 2159         char    *argv = imgp->ip_argv;  /* modifiable copy of argv */
 2160         user_addr_t     string_area;    /* *argv[], *env[] */
 2161         user_addr_t     path_area;      /* package launch path */
 2162         user_addr_t     ptr_area;       /* argv[], env[], exec_path */
 2163         user_addr_t     stack;
 2164         int     stringc = imgp->ip_argc + imgp->ip_envc;
 2165         int len;
 2166         int error;
 2167         int strspace;
 2168 
 2169         stack = *stackp;
 2170 
 2171         unsigned patharea_len = imgp->ip_argv - imgp->ip_strings;
 2172         int envc_add = 0;
 2173         
 2174         /*
 2175          * Set up pointers to the beginning of the string area, the beginning
 2176          * of the path area, and the beginning of the pointer area (actually,
 2177          * the location of argc, an int, which may be smaller than a pointer,
 2178          * but we use ptr_size worth of space for it, for alignment).
 2179          */
 2180         string_area = stack - (((imgp->ip_strendp - imgp->ip_strings) + ptr_size-1) & ~(ptr_size-1)) - ptr_size;
 2181         path_area = string_area - ((patharea_len + ptr_size-1) & ~(ptr_size-1));
 2182         ptr_area = path_area - ((imgp->ip_argc + imgp->ip_envc + 4 + envc_add) * ptr_size) - ptr_size /*argc*/;
 2183 
 2184         /* Return the initial stack address: the location of argc */
 2185         *stackp = ptr_area;
 2186 
 2187         /*
 2188          * Record the size of the arguments area so that sysctl_procargs()
 2189          * can return the argument area without having to parse the arguments.
 2190          */
 2191         proc_lock(p);
 2192         p->p_argc = imgp->ip_argc;
 2193         p->p_argslen = (int)(stack - path_area);
 2194         proc_unlock(p);
 2195 
 2196 
 2197         /*
 2198          * Support for new app package launching for Mac OS X allocates
 2199          * the "path" at the begining of the imgp->ip_strings buffer.
 2200          * copy it just before the string area.
 2201          */
 2202         len = 0;
 2203         error = copyoutstr(imgp->ip_strings, path_area,
 2204                                                    patharea_len,
 2205                                 (size_t *)&len);
 2206         if (error)
 2207                 goto bad;
 2208 
 2209 
 2210         /* Save a NULL pointer below it */
 2211         (void)copyoutptr(0LL, path_area - ptr_size, ptr_size);
 2212 
 2213         /* Save the pointer to "path" just below it */
 2214         (void)copyoutptr(path_area, path_area - 2*ptr_size, ptr_size);
 2215 
 2216         /*
 2217          * ptr_size for 2 NULL one each ofter arg[argc -1] and env[n]
 2218          * ptr_size for argc
 2219          * skip over saved path, ptr_size for pointer to path,
 2220          * and ptr_size for the NULL after pointer to path.
 2221          */
 2222 
 2223         /* argc (int32, stored in a ptr_size area) */
 2224         (void)suword(ptr_area, imgp->ip_argc);
 2225         ptr_area += sizeof(int);
 2226         /* pad to ptr_size, if 64 bit image, to ensure user stack alignment */
 2227         if (imgp->ip_flags & IMGPF_IS_64BIT) {
 2228                 (void)suword(ptr_area, 0);      /* int, not long: ignored */
 2229                 ptr_area += sizeof(int);
 2230         }
 2231 
 2232 #if CONFIG_DTRACE
 2233         p->p_dtrace_argv = ptr_area; /* user_addr_t &argv[0] for dtrace convenience */
 2234 #endif /* CONFIG_DTRACE */
 2235 
 2236         /*
 2237          * We use (string_area - path_area) here rather than the more
 2238          * intuitive (imgp->ip_argv - imgp->ip_strings) because we are
 2239          * interested in the length of the PATH_AREA in user space,
 2240          * rather than the actual length of the execution path, since
 2241          * it includes alignment padding of the PATH_AREA + STRING_AREA
 2242          * to a ptr_size boundary.
 2243          */
 2244         strspace = SIZE_IMG_STRSPACE - (string_area - path_area);
 2245         for (;;) {
 2246                 if (stringc == imgp->ip_envc) {
 2247                         /* argv[n] = NULL */
 2248                         (void)copyoutptr(0LL, ptr_area, ptr_size);
 2249                         ptr_area += ptr_size;
 2250 #if CONFIG_DTRACE
 2251                         p->p_dtrace_envp = ptr_area; /* user_addr_t &env[0] for dtrace convenience */
 2252 #endif /* CONFIG_DTRACE */
 2253                 }
 2254                 if (--stringc < 0)
 2255                         break;
 2256 
 2257                 /* pointer: argv[n]/env[n] */
 2258                 (void)copyoutptr(string_area, ptr_area, ptr_size);
 2259 
 2260                 /* string : argv[n][]/env[n][] */
 2261                 do {
 2262                         if (strspace <= 0) {
 2263                                 error = E2BIG;
 2264                                 break;
 2265                         }
 2266                         error = copyoutstr(argv, string_area,
 2267                                                 (unsigned)strspace,
 2268                                                 (size_t *)&len);
 2269                         string_area += len;
 2270                         argv += len;
 2271                         strspace -= len;
 2272                 } while (error == ENAMETOOLONG);
 2273                 if (error == EFAULT || error == E2BIG)
 2274                         break;  /* bad stack - user's problem */
 2275                 ptr_area += ptr_size;
 2276         }
 2277         /* env[n] = NULL */
 2278         (void)copyoutptr(0LL, ptr_area, ptr_size);
 2279 
 2280 bad:
 2281         return(error);
 2282 }
 2283 
 2284 
 2285 /*
 2286  * exec_extract_strings
 2287  *
 2288  * Copy arguments and environment from user space into work area; we may
 2289  * have already copied some early arguments into the work area, and if
 2290  * so, any arguments opied in are appended to those already there.
 2291  *
 2292  * Parameters:  struct image_params *   the image parameter block
 2293  *
 2294  * Returns:     0                       Success
 2295  *              !0                      Failure: errno
 2296  *
 2297  * Implicit returns;
 2298  *              (imgp->ip_argc)         Count of arguments, updated
 2299  *              (imgp->ip_envc)         Count of environment strings, updated
 2300  *
 2301  *
 2302  * Note:        The argument and environment vectors are user space pointers
 2303  *              to arrays of user space pointers.
 2304  */
 2305 static int
 2306 exec_extract_strings(struct image_params *imgp)
 2307 {
 2308         int error = 0;
 2309         int     ptr_size = (imgp->ip_flags & IMGPF_WAS_64BIT) ? 8 : 4;
 2310         user_addr_t     argv = imgp->ip_user_argv;
 2311         user_addr_t     envv = imgp->ip_user_envv;
 2312 
 2313         /*
 2314          * If the argument vector is NULL, this is the system startup
 2315          * bootstrap from load_init_program(), and there's nothing to do
 2316          */
 2317         if (imgp->ip_user_argv == 0LL)
 2318                 goto bad;
 2319 
 2320         /* Now, get rest of arguments */
 2321 
 2322         /*
 2323          * If we are running an interpreter, replace the av[0] that was
 2324          * passed to execve() with the fully qualified path name that was
 2325          * passed to execve() for interpreters which do not use the PATH
 2326          * to locate their script arguments.
 2327          */
 2328         if((imgp->ip_flags & IMGPF_INTERPRET) != 0 && argv != 0LL) {
 2329                 user_addr_t     arg;
 2330 
 2331                 error = copyinptr(argv, &arg, ptr_size);
 2332                 if (error)
 2333                         goto bad;
 2334                 if (arg != 0LL && arg != (user_addr_t)-1) {
 2335                         argv += ptr_size;
 2336                         error = exec_add_string(imgp, imgp->ip_user_fname);
 2337                         if (error)
 2338                                 goto bad;
 2339                         imgp->ip_argc++;
 2340                 }
 2341         }
 2342 
 2343         while (argv != 0LL) {
 2344                 user_addr_t     arg;
 2345 
 2346                 error = copyinptr(argv, &arg, ptr_size);
 2347                 if (error)
 2348                         goto bad;
 2349 
 2350                 argv += ptr_size;
 2351                 if (arg == 0LL) {
 2352                         break;
 2353                 } else if (arg == (user_addr_t)-1) {
 2354                         /* Um... why would it be -1? */
 2355                         error = EFAULT;
 2356                         goto bad;
 2357                 }
 2358                 /*
 2359                 * av[n...] = arg[n]
 2360                 */
 2361                 error = exec_add_string(imgp, arg);
 2362                 if (error)
 2363                         goto bad;
 2364                 imgp->ip_argc++;
 2365         }        
 2366 
 2367         /* Now, get the environment */
 2368         while (envv != 0LL) {
 2369                 user_addr_t     env;
 2370 
 2371                 error = copyinptr(envv, &env, ptr_size);
 2372                 if (error)
 2373                         goto bad;
 2374 
 2375                 envv += ptr_size;
 2376                 if (env == 0LL) {
 2377                         break;
 2378                 } else if (env == (user_addr_t)-1) {
 2379                         error = EFAULT;
 2380                         goto bad;
 2381                 }
 2382                 /*
 2383                 * av[n...] = env[n]
 2384                 */
 2385                 error = exec_add_string(imgp, env);
 2386                 if (error)
 2387                         goto bad;
 2388                 imgp->ip_envc++;
 2389         }
 2390 bad:
 2391         return error;
 2392 }
 2393 
 2394 
 2395 #define unix_stack_size(p)      (p->p_rlimit[RLIMIT_STACK].rlim_cur)
 2396 
 2397 /*
 2398  * exec_check_permissions
 2399  *
 2400  * Decription:  Verify that the file that is being attempted to be executed
 2401  *              is in fact allowed to be executed based on it POSIX file
 2402  *              permissions and other access control criteria
 2403  *
 2404  * Parameters:  struct image_params *   the image parameter block
 2405  *
 2406  * Returns:     0                       Success
 2407  *              EACCES                  Permission denied
 2408  *              ENOEXEC                 Executable file format error
 2409  *              ETXTBSY                 Text file busy [misuse of error code]
 2410  *      vnode_getattr:???
 2411  *      vnode_authorize:???
 2412  */
 2413 static int
 2414 exec_check_permissions(struct image_params *imgp)
 2415 {
 2416         struct vnode *vp = imgp->ip_vp;
 2417         struct vnode_attr *vap = imgp->ip_vattr;
 2418         proc_t p = vfs_context_proc(imgp->ip_vfs_context);
 2419         int error;
 2420         kauth_action_t action;
 2421 
 2422         /* Only allow execution of regular files */
 2423         if (!vnode_isreg(vp))
 2424                 return (EACCES);
 2425         
 2426         /* Get the file attributes that we will be using here and elsewhere */
 2427         VATTR_INIT(vap);
 2428         VATTR_WANTED(vap, va_uid);
 2429         VATTR_WANTED(vap, va_gid);
 2430         VATTR_WANTED(vap, va_mode);
 2431         VATTR_WANTED(vap, va_fsid);
 2432         VATTR_WANTED(vap, va_fileid);
 2433         VATTR_WANTED(vap, va_data_size);
 2434         if ((error = vnode_getattr(vp, vap, imgp->ip_vfs_context)) != 0)
 2435                 return (error);
 2436 
 2437         /*
 2438          * Ensure that at least one execute bit is on - otherwise root
 2439          * will always succeed, and we don't want to happen unless the
 2440          * file really is executable.
 2441          */
 2442         if ((vap->va_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0)
 2443                 return (EACCES);
 2444 
 2445         /* Disallow zero length files */
 2446         if (vap->va_data_size == 0)
 2447                 return (ENOEXEC);
 2448 
 2449         imgp->ip_arch_offset = (user_size_t)0;
 2450         imgp->ip_arch_size = vap->va_data_size;
 2451 
 2452         /* Disable setuid-ness for traced programs or if MNT_NOSUID */
 2453         if ((vp->v_mount->mnt_flag & MNT_NOSUID) || (p->p_lflag & P_LTRACED)) {
 2454                 vap->va_mode &= ~(VSUID | VSGID);
 2455 #if CONFIG_MACF
 2456                 imgp->ip_no_trans = 1;
 2457 #endif
 2458         }
 2459 
 2460 #if CONFIG_MACF
 2461         error = mac_vnode_check_exec(imgp->ip_vfs_context, vp, imgp);
 2462         if (error)
 2463                 return (error);
 2464 #endif
 2465 
 2466         /* Check for execute permission */
 2467         action = KAUTH_VNODE_EXECUTE;
 2468         /* Traced images must also be readable */
 2469         if (p->p_lflag & P_LTRACED)
 2470                 action |= KAUTH_VNODE_READ_DATA;
 2471         if ((error = vnode_authorize(vp, NULL, action, imgp->ip_vfs_context)) != 0)
 2472                 return (error);
 2473 
 2474 #if 0
 2475         /* Don't let it run if anyone had it open for writing */
 2476         vnode_lock(vp);
 2477         if (vp->v_writecount) {
 2478                 panic("going to return ETXTBSY %x", vp);
 2479                 vnode_unlock(vp);
 2480                 return (ETXTBSY);
 2481         }
 2482         vnode_unlock(vp);
 2483 #endif
 2484 
 2485 
 2486 #ifdef IMGPF_POWERPC
 2487         /*
 2488          * If the file we are about to attempt to load is the exec_handler_ppc,
 2489          * which is determined by matching the vattr fields against previously
 2490          * cached values, then we set the PowerPC environment flag.
 2491          */
 2492         if (vap->va_fsid == exec_archhandler_ppc.fsid &&
 2493                 vap->va_fileid == (uint64_t)((u_long)exec_archhandler_ppc.fileid)) {
 2494                 imgp->ip_flags |= IMGPF_POWERPC;
 2495         }
 2496 #endif  /* IMGPF_POWERPC */
 2497 
 2498         /* XXX May want to indicate to underlying FS that vnode is open */
 2499 
 2500         return (error);
 2501 }
 2502 
 2503 
 2504 /*
 2505  * exec_handle_sugid
 2506  *
 2507  * Initially clear the P_SUGID in the process flags; if an SUGID process is
 2508  * exec'ing a non-SUGID image, then  this is the point of no return.
 2509  *
 2510  * If the image being activated is SUGID, then replace the credential with a
 2511  * copy, disable tracing (unless the tracing process is root), reset the
 2512  * mach task port to revoke it, set the P_SUGID bit,
 2513  *
 2514  * If the saved user and group ID will be changing, then make sure it happens
 2515  * to a new credential, rather than a shared one.
 2516  *
 2517  * Set the security token (this is probably obsolete, given that the token
 2518  * should not technically be separate from the credential itself).
 2519  *
 2520  * Parameters:  struct image_params *   the image parameter block
 2521  *
 2522  * Returns:     void                    No failure indication
 2523  *
 2524  * Implicit returns:
 2525  *              <process credential>    Potentially modified/replaced
 2526  *              <task port>             Potentially revoked
 2527  *              <process flags>         P_SUGID bit potentially modified
 2528  *              <security token>        Potentially modified
 2529  */
 2530 static int
 2531 exec_handle_sugid(struct image_params *imgp)
 2532 {
 2533         kauth_cred_t            cred = vfs_context_ucred(imgp->ip_vfs_context);
 2534         proc_t                  p = vfs_context_proc(imgp->ip_vfs_context);
 2535         int                     i;
 2536         int                     is_member = 0;
 2537         int                     error = 0;
 2538         struct vnode    *dev_null = NULLVP;
 2539 #if CONFIG_MACF
 2540         kauth_cred_t    my_cred;
 2541 #endif
 2542 
 2543 #if CONFIG_MACF
 2544         int                     mac_transition;
 2545         mac_transition = mac_cred_check_label_update_execve(imgp->ip_vfs_context, imgp->ip_vp,
 2546             imgp->ip_scriptlabelp, imgp->ip_execlabelp, p);
 2547 #endif
 2548 
 2549         OSBitAndAtomic(~((uint32_t)P_SUGID), (UInt32 *)&p->p_flag);
 2550 
 2551         /*
 2552          * Order of the following is important; group checks must go last,
 2553          * as we use the success of the 'is_member' check combined with the
 2554          * failure of the explicit match to indicate that we will be setting
 2555          * the egid of the process even though the new process did not
 2556          * require VSUID/VSGID bits in order for it to set the new group as
 2557          * its egid.
 2558          *
 2559          * Note:        Technically, by this we are implying a call to
 2560          *              setegid() in the new process, rather than implying
 2561          *              it used its VSGID bit to set the effective group,
 2562          *              even though there is no code in that process to make
 2563          *              such a call.
 2564          */
 2565         if (((imgp->ip_origvattr->va_mode & VSUID) != 0 &&
 2566              kauth_cred_getuid(cred) != imgp->ip_origvattr->va_uid) ||
 2567 #if CONFIG_MACF
 2568                 mac_transition ||       /* A policy wants to transition */
 2569 #endif
 2570             ((imgp->ip_origvattr->va_mode & VSGID) != 0 &&
 2571                  ((kauth_cred_ismember_gid(cred, imgp->ip_origvattr->va_gid, &is_member) || !is_member) ||
 2572                  (cred->cr_gid != imgp->ip_origvattr->va_gid)))) {
 2573 
 2574                 /*
 2575                  * Replace the credential with a copy of itself if euid or
 2576                  * egid change.
 2577                  *
 2578                  * Note:        setuid binaries will automatically opt out of
 2579                  *              group resolver participation as a side effect
 2580                  *              of this operation.  This is an intentional
 2581                  *              part of the security model, which requires a
 2582                  *              participating credential be established by
 2583                  *              escalating privilege, setting up all other
 2584                  *              aspects of the credential including whether
 2585                  *              or not to participate in external group
 2586                  *              membership resolution, then dropping their
 2587                  *              effective privilege to that of the desired
 2588                  *              final credential state.
 2589                  */
 2590                 if (imgp->ip_origvattr->va_mode & VSUID) {
 2591                         p->p_ucred  = kauth_cred_setresuid(p->p_ucred, KAUTH_UID_NONE, imgp->ip_origvattr->va_uid, imgp->ip_origvattr->va_uid, KAUTH_UID_NONE);
 2592                 }
 2593                 if (imgp->ip_origvattr->va_mode & VSGID) {
 2594                         p->p_ucred = kauth_cred_setresgid(p->p_ucred, KAUTH_GID_NONE, imgp->ip_origvattr->va_gid, imgp->ip_origvattr->va_gid);
 2595                 }
 2596 
 2597 #if CONFIG_MACF
 2598                 /* 
 2599                  * XXXMAC: In FreeBSD, we set P_SUGID on a MAC transition
 2600                  * to protect against debuggers being attached by an 
 2601                  * insufficiently privileged process onto the result of
 2602                  * a transition to a more privileged credential.  This is
 2603                  * too conservative on FreeBSD, but we need to do
 2604                  * something similar here, or risk vulnerability.
 2605                  *
 2606                  * Before we make the call into the MAC policies, get a new
 2607                  * duplicate credential, so they can modify it without
 2608                  * modifying any others sharing it.
 2609                  */
 2610                 if (mac_transition && !imgp->ip_no_trans) { 
 2611                         kauth_proc_label_update_execve(p,
 2612                                 imgp->ip_vfs_context,
 2613                                 imgp->ip_vp, 
 2614                                 imgp->ip_scriptlabelp, imgp->ip_execlabelp);
 2615 
 2616                         my_cred = kauth_cred_proc_ref(p);
 2617                         mac_task_label_update_cred(my_cred, p->task);
 2618                         kauth_cred_unref(&my_cred);
 2619                 }
 2620 #endif
 2621                 /*
 2622                  * Have mach reset the task and thread ports.
 2623                  * We don't want anyone who had the ports before
 2624                  * a setuid exec to be able to access/control the
 2625                  * task/thread after.
 2626                  */
 2627                 if (current_task() == p->task) {
 2628                         ipc_task_reset(p->task);
 2629                         ipc_thread_reset(current_thread());
 2630                 }
 2631 
 2632                 /*
 2633                  * If 'is_member' is non-zero, then we passed the VSUID and
 2634                  * MACF checks, and successfully determined that the previous
 2635                  * cred was a member of the VSGID group, but that it was not
 2636                  * the default at the time of the execve.  So we don't set the
 2637                  * P_SUGID on the basis of simply running this code.
 2638                  */
 2639                 if (!is_member)
 2640                         OSBitOrAtomic(P_SUGID, (UInt32 *)&p->p_flag);
 2641 
 2642                 /* Cache the vnode for /dev/null the first time around */
 2643                 if (dev_null == NULLVP) {
 2644                         struct nameidata nd1;
 2645 
 2646                         NDINIT(&nd1, LOOKUP, FOLLOW, UIO_SYSSPACE32,
 2647                             CAST_USER_ADDR_T("/dev/null"),
 2648                             imgp->ip_vfs_context);
 2649 
 2650                         if ((error = vn_open(&nd1, FREAD, 0)) == 0) {
 2651                                 dev_null = nd1.ni_vp;
 2652                                 /*
 2653                                  * vn_open returns with both a use_count
 2654                                  * and an io_count on the found vnode
 2655                                  * drop the io_count, but keep the use_count
 2656                                  */
 2657                                 vnode_put(nd1.ni_vp);
 2658                         }
 2659                 }
 2660 
 2661                 /* Radar 2261856; setuid security hole fix */
 2662                 /* Patch from OpenBSD: A. Ramesh */
 2663                 /*
 2664                  * XXX For setuid processes, attempt to ensure that
 2665                  * stdin, stdout, and stderr are already allocated.
 2666                  * We do not want userland to accidentally allocate
 2667                  * descriptors in this range which has implied meaning
 2668                  * to libc.
 2669                  */
 2670                 if (dev_null != NULLVP) {
 2671                         for (i = 0; i < 3; i++) {
 2672                                 struct fileproc *fp;
 2673                                 int indx;
 2674 
 2675                                 if (p->p_fd->fd_ofiles[i] != NULL)
 2676                                         continue;
 2677 
 2678                                 if ((error = falloc(p, &fp, &indx, imgp->ip_vfs_context)) != 0)
 2679                                         continue;
 2680 
 2681                                 if ((error = vnode_ref_ext(dev_null, FREAD)) != 0) {
 2682                                         fp_free(p, indx, fp);
 2683                                         break;
 2684                                 }
 2685 
 2686                                 fp->f_fglob->fg_flag = FREAD;
 2687                                 fp->f_fglob->fg_type = DTYPE_VNODE;
 2688                                 fp->f_fglob->fg_ops = &vnops;
 2689                                 fp->f_fglob->fg_data = (caddr_t)dev_null;
 2690                                 
 2691                                 proc_fdlock(p);
 2692                                 procfdtbl_releasefd(p, indx, NULL);
 2693                                 fp_drop(p, indx, fp, 1);
 2694                                 proc_fdunlock(p);
 2695                         }
 2696                         /*
 2697                          * for now we need to drop the reference immediately
 2698                          * since we don't have any mechanism in place to
 2699                          * release it before starting to unmount "/dev"
 2700                          * during a reboot/shutdown
 2701                          */
 2702                         vnode_rele(dev_null);
 2703                         dev_null = NULLVP;
 2704                 }
 2705         }
 2706 
 2707         /*
 2708          * Implement the semantic where the effective user and group become
 2709          * the saved user and group in exec'ed programs.
 2710          */
 2711         p->p_ucred = kauth_cred_setsvuidgid(p->p_ucred, kauth_cred_getuid(p->p_ucred),  p->p_ucred->cr_gid);
 2712         
 2713         /* XXX Obsolete; security token should not be separate from cred */
 2714         set_security_token(p);
 2715 
 2716         return(error);
 2717 }
 2718 
 2719 
 2720 /*
 2721  * create_unix_stack
 2722  *
 2723  * Description: Set the user stack address for the process to the provided
 2724  *              address.  If a custom stack was not set as a result of the
 2725  *              load process (i.e. as specified by the image file for the
 2726  *              executable), then allocate the stack in the provided map and
 2727  *              set up appropriate guard pages for enforcing administrative
 2728  *              limits on stack growth, if they end up being needed.
 2729  *
 2730  * Parameters:  p                       Process to set stack on
 2731  *              user_stack              Address to set stack for process to
 2732  *              customstack             FALSE if no custom stack in binary
 2733  *              map                     Address map in which to allocate the
 2734  *                                      new stack, if 'customstack' is FALSE
 2735  *
 2736  * Returns:     KERN_SUCCESS            Stack successfully created
 2737  *              !KERN_SUCCESS           Mach failure code
 2738  */
 2739 static kern_return_t
 2740 create_unix_stack(vm_map_t map, user_addr_t user_stack, int customstack,
 2741                         proc_t p)
 2742 {
 2743         mach_vm_size_t          size, prot_size;
 2744         mach_vm_offset_t        addr, prot_addr;
 2745         kern_return_t           kr;
 2746 
 2747         proc_lock(p);
 2748         p->user_stack = user_stack;
 2749         proc_unlock(p);
 2750 
 2751         if (!customstack) {
 2752                 /*
 2753                  * Allocate enough space for the maximum stack size we
 2754                  * will ever authorize and an extra page to act as
 2755                  * a guard page for stack overflows.
 2756                  */
 2757                 size = mach_vm_round_page(MAXSSIZ);
 2758 #if STACK_GROWTH_UP
 2759                 addr = mach_vm_trunc_page(user_stack);
 2760 #else   /* STACK_GROWTH_UP */
 2761                 addr = mach_vm_trunc_page(user_stack - size);
 2762 #endif  /* STACK_GROWTH_UP */
 2763                 kr = mach_vm_allocate(map, &addr, size,
 2764                                         VM_MAKE_TAG(VM_MEMORY_STACK) |
 2765                                       VM_FLAGS_FIXED);
 2766                 if (kr != KERN_SUCCESS) {
 2767                         return kr;
 2768                 }
 2769                 /*
 2770                  * And prevent access to what's above the current stack
 2771                  * size limit for this process.
 2772                  */
 2773                 prot_addr = addr;
 2774 #if STACK_GROWTH_UP
 2775                 prot_addr += unix_stack_size(p);
 2776 #endif /* STACK_GROWTH_UP */
 2777                 prot_addr = mach_vm_round_page(prot_addr);
 2778                 prot_size = mach_vm_trunc_page(size - unix_stack_size(p));
 2779                 kr = mach_vm_protect(map,
 2780                                      prot_addr,
 2781                                      prot_size,
 2782                                      FALSE,
 2783                                      VM_PROT_NONE);
 2784                 if (kr != KERN_SUCCESS) {
 2785                         (void) mach_vm_deallocate(map, addr, size);
 2786                         return kr;
 2787                 }
 2788         }
 2789         return KERN_SUCCESS;
 2790 }
 2791 
 2792 #include <sys/reboot.h>
 2793 
 2794 static char             init_program_name[128] = "/sbin/launchd";
 2795 
 2796 struct execve_args      init_exec_args;
 2797 
 2798 /*
 2799  * load_init_program
 2800  *
 2801  * Description: Load the "init" program; in most cases, this will be "launchd"
 2802  *
 2803  * Parameters:  p                       Process to call execve() to create
 2804  *                                      the "init" program
 2805  *
 2806  * Returns:     (void)
 2807  *
 2808  * Notes:       The process that is passed in is the first manufactured
 2809  *              process on the system, and gets here via bsd_ast() firing
 2810  *              for the first time.  This is done to ensure that bsd_init()
 2811  *              has run to completion.
 2812  */
 2813 void
 2814 load_init_program(proc_t p)
 2815 {
 2816         vm_offset_t     init_addr;
 2817         int             argc = 0;
 2818         char            *argv[3];
 2819         int                     error;
 2820         register_t      retval[2];
 2821 
 2822         /*
 2823          * Copy out program name.
 2824          */
 2825 
 2826         init_addr = VM_MIN_ADDRESS;
 2827         (void) vm_allocate(current_map(), &init_addr, PAGE_SIZE,
 2828                                 VM_FLAGS_ANYWHERE);
 2829         if (init_addr == 0)
 2830                 init_addr++;
 2831 
 2832         (void) copyout((caddr_t) init_program_name, CAST_USER_ADDR_T(init_addr),
 2833                         (unsigned) sizeof(init_program_name)+1);
 2834 
 2835         argv[argc++] = (char *) init_addr;
 2836         init_addr += sizeof(init_program_name);
 2837         init_addr = (vm_offset_t)ROUND_PTR(char, init_addr);
 2838 
 2839         /*
 2840          * Put out first (and only) argument, similarly.
 2841          * Assumes everything fits in a page as allocated
 2842          * above.
 2843          */
 2844         if (boothowto & RB_SINGLE) {
 2845                 const char *init_args = "-s";
 2846 
 2847                 copyout(init_args, CAST_USER_ADDR_T(init_addr),
 2848                         strlen(init_args));
 2849 
 2850                 argv[argc++] = (char *)init_addr;
 2851                 init_addr += strlen(init_args);
 2852                 init_addr = (vm_offset_t)ROUND_PTR(char, init_addr);
 2853 
 2854         }
 2855 
 2856         /*
 2857          * Null-end the argument list
 2858          */
 2859         argv[argc] = NULL;
 2860         
 2861         /*
 2862          * Copy out the argument list.
 2863          */
 2864         
 2865         (void) copyout((caddr_t) argv, CAST_USER_ADDR_T(init_addr),
 2866                         (unsigned) sizeof(argv));
 2867 
 2868         /*
 2869          * Set up argument block for fake call to execve.
 2870          */
 2871 
 2872         init_exec_args.fname = CAST_USER_ADDR_T(argv[0]);
 2873         init_exec_args.argp = CAST_USER_ADDR_T((char **)init_addr);
 2874         init_exec_args.envp = CAST_USER_ADDR_T(0);
 2875         
 2876         /*
 2877          * So that mach_init task is set with uid,gid 0 token 
 2878          */
 2879         set_security_token(p);
 2880 
 2881         error = execve(p,&init_exec_args,retval);
 2882         if (error)
 2883                 panic("Process 1 exec of %s failed, errno %d\n",
 2884                       init_program_name, error);
 2885 }
 2886 
 2887 /*
 2888  * load_return_to_errno
 2889  *
 2890  * Description: Convert a load_return_t (Mach error) to an errno (BSD error)
 2891  *
 2892  * Parameters:  lrtn                    Mach error number
 2893  *
 2894  * Returns:     (int)                   BSD error number
 2895  *              0                       Success
 2896  *              EBADARCH                Bad architecture
 2897  *              EBADMACHO               Bad Mach object file
 2898  *              ESHLIBVERS              Bad shared library version
 2899  *              ENOMEM                  Out of memory/resource shortage
 2900  *              EACCES                  Access denied
 2901  *              ENOENT                  Entry not found (usually "file does
 2902  *                                      does not exist")
 2903  *              EIO                     An I/O error occurred
 2904  *              EBADEXEC                The executable is corrupt/unknown
 2905  */
 2906 static int 
 2907 load_return_to_errno(load_return_t lrtn)
 2908 {
 2909         switch (lrtn) {
 2910         case LOAD_SUCCESS:
 2911                 return 0;
 2912         case LOAD_BADARCH:
 2913                 return EBADARCH;
 2914         case LOAD_BADMACHO:
 2915                 return EBADMACHO;
 2916         case LOAD_SHLIB:
 2917                 return ESHLIBVERS;
 2918         case LOAD_NOSPACE:
 2919         case LOAD_RESOURCE:
 2920                 return ENOMEM;
 2921         case LOAD_PROTECT:
 2922                 return EACCES;
 2923         case LOAD_ENOENT:
 2924                 return ENOENT;
 2925         case LOAD_IOERROR:
 2926                 return EIO;
 2927         case LOAD_FAILURE:
 2928         default:
 2929                 return EBADEXEC;
 2930         }
 2931 }
 2932 
 2933 #include <mach/mach_types.h>
 2934 #include <mach/vm_prot.h>
 2935 #include <mach/semaphore.h>
 2936 #include <mach/sync_policy.h>
 2937 #include <kern/clock.h>
 2938 #include <mach/kern_return.h>
 2939 
 2940 extern semaphore_t execve_semaphore;
 2941 
 2942 /*
 2943  * execargs_alloc
 2944  *
 2945  * Description: Allocate the block of memory used by the execve arguments.
 2946  *              At the same time, we allocate a page so that we can read in
 2947  *              the first page of the image.
 2948  *
 2949  * Parameters:  struct image_params *   the image parameter block
 2950  *
 2951  * Returns:     0                       Success
 2952  *              EINVAL                  Invalid argument
 2953  *              EACCES                  Permission denied
 2954  *              EINTR                   Interrupted function
 2955  *              ENOMEM                  Not enough space
 2956  *
 2957  * Notes:       This is a temporary allocation into the kernel address space
 2958  *              to enable us to copy arguments in from user space.  This is
 2959  *              necessitated by not mapping the process calling execve() into
 2960  *              the kernel address space during the execve() system call.
 2961  *
 2962  *              We assemble the argument and environment, etc., into this
 2963  *              region before copying it as a single block into the child
 2964  *              process address space (at the top or bottom of the stack,
 2965  *              depending on which way the stack grows; see the function
 2966  *              exec_copyout_strings() for details).
 2967  *
 2968  *              This ends up with a second (possibly unnecessary) copy compared
 2969  *              with assembing the data directly into the child address space,
 2970  *              instead, but since we cannot be guaranteed that the parent has
 2971  *              not modified its environment, we can't really know that it's
 2972  *              really a block there as well.
 2973  */
 2974 static int
 2975 execargs_alloc(struct image_params *imgp)
 2976 {
 2977         kern_return_t kret;
 2978 
 2979         kret = semaphore_wait(execve_semaphore);
 2980         if (kret != KERN_SUCCESS)
 2981                 switch (kret) {
 2982                 default:
 2983                         return (EINVAL);
 2984                 case KERN_INVALID_ADDRESS:
 2985                 case KERN_PROTECTION_FAILURE:
 2986                         return (EACCES);
 2987                 case KERN_ABORTED:
 2988                 case KERN_OPERATION_TIMED_OUT:
 2989                         return (EINTR);
 2990                 }
 2991 
 2992         kret = kmem_alloc_pageable(bsd_pageable_map, (vm_offset_t *)&imgp->ip_strings, NCARGS + PAGE_SIZE);
 2993         imgp->ip_vdata = imgp->ip_strings + NCARGS;
 2994         if (kret != KERN_SUCCESS) {
 2995                 semaphore_signal(execve_semaphore);
 2996                 return (ENOMEM);
 2997         }
 2998         return (0);
 2999 }
 3000 
 3001 /*
 3002  * execargs_free
 3003  *
 3004  * Description: Free the block of memory used by the execve arguments and the
 3005  *              first page of the executable by a previous call to the function
 3006  *              execargs_alloc().
 3007  *
 3008  * Parameters:  struct image_params *   the image parameter block
 3009  *
 3010  * Returns:     0                       Success
 3011  *              EINVAL                  Invalid argument
 3012  *              EINTR                   Oeration interrupted
 3013  */
 3014 static int
 3015 execargs_free(struct image_params *imgp)
 3016 {
 3017         kern_return_t kret;
 3018 
 3019         kmem_free(bsd_pageable_map, (vm_offset_t)imgp->ip_strings, NCARGS + PAGE_SIZE);
 3020         imgp->ip_strings = NULL;
 3021 
 3022         kret = semaphore_signal(execve_semaphore);
 3023         switch (kret) { 
 3024         case KERN_INVALID_ADDRESS:
 3025         case KERN_PROTECTION_FAILURE:
 3026                 return (EINVAL);
 3027         case KERN_ABORTED:
 3028         case KERN_OPERATION_TIMED_OUT:
 3029                 return (EINTR);
 3030         case KERN_SUCCESS:
 3031                 return(0);
 3032         default:
 3033                 return (EINVAL);
 3034         }
 3035 }
 3036 
 3037 static void
 3038 exec_resettextvp(proc_t p, struct image_params *imgp)
 3039 {
 3040         vnode_t vp;
 3041         off_t offset;
 3042         vnode_t tvp  = p->p_textvp;
 3043         int ret;
 3044 
 3045         vp = imgp->ip_vp;
 3046         offset = imgp->ip_arch_offset;
 3047 
 3048         if (vp == NULLVP)
 3049                 panic("exec_resettextvp: expected valid vp");
 3050 
 3051         ret = vnode_ref(vp);
 3052         proc_lock(p);
 3053         if (ret == 0) {
 3054                 p->p_textvp = vp;
 3055                 p->p_textoff = offset;
 3056         } else {
 3057                 p->p_textvp = NULLVP;   /* this is paranoia */
 3058                 p->p_textoff = 0;
 3059         }
 3060         proc_unlock(p);
 3061 
 3062         if ( tvp != NULLVP) {
 3063                 if (vnode_getwithref(tvp) == 0) {
 3064                         vnode_rele(tvp);
 3065                         vnode_put(tvp);
 3066                 }
 3067         }       
 3068 
 3069 }
 3070 

Cache object: c416dd00013712ccf6b90e7c6c661825


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