2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
24 * Mach Operating System
25 * Copyright (c) 1987 Carnegie-Mellon University
26 * All rights reserved. The CMU software License Agreement specifies
27 * the terms and conditions for use and redistribution.
33 * Copyright (c) 1982, 1986, 1991, 1993
34 * The Regents of the University of California. All rights reserved.
35 * (c) UNIX System Laboratories, Inc.
36 * All or some portions of this file are derived from material licensed
37 * to the University of California by American Telephone and Telegraph
38 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
39 * the permission of UNIX System Laboratories, Inc.
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. All advertising materials mentioning features or use of this software
50 * must display the following acknowledgement:
51 * This product includes software developed by the University of
52 * California, Berkeley and its contributors.
53 * 4. Neither the name of the University nor the names of its contributors
54 * may be used to endorse or promote products derived from this software
55 * without specific prior written permission.
57 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
58 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
59 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
60 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
61 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
62 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
63 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
64 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
65 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * from: @(#)kern_exec.c 8.1 (Berkeley) 6/10/93
71 #include <machine/reg.h>
73 #include <sys/param.h>
74 #include <sys/systm.h>
75 #include <sys/filedesc.h>
76 #include <sys/kernel.h>
80 #include <sys/socketvar.h>
81 #include <sys/malloc.h>
82 #include <sys/namei.h>
83 #include <sys/mount.h>
84 #include <sys/vnode.h>
90 #include <sys/kdebug.h>
91 #include <sys/signal.h>
92 #include <sys/aio_kern.h>
94 #include <bsm/audit_kernel.h>
96 #include <mach/vm_param.h>
98 #include <vm/vm_map.h>
100 extern vm_map_t
vm_map_switch(vm_map_t map
); /* XXX */
102 #include <vm/vm_kern.h>
103 #include <vm/vm_shared_memory_server.h>
105 #include <kern/thread.h>
106 #include <kern/task.h>
108 #include <kern/ast.h>
109 #include <kern/mach_loader.h>
110 #include <mach-o/fat.h>
111 #include <mach-o/loader.h>
112 #include <machine/vmparam.h>
114 #include <sys/ktrace.h>
120 extern vm_map_t bsd_pageable_map
;
122 #define ROUND_PTR(type, addr) \
123 (type *)( ( (unsigned)(addr) + 16 - 1) \
126 static int load_return_to_errno(load_return_t lrtn
);
127 int execve(struct proc
*p
, struct execve_args
*uap
, register_t
*retval
);
128 static int execargs_alloc(vm_offset_t
*addrp
);
129 static int execargs_free(vm_offset_t addr
);
132 execv(p
, args
, retval
)
137 ((struct execve_args
*)args
)->envp
= NULL
;
138 return (execve(p
, args
, retval
));
141 extern char classichandler
[32];
142 extern long classichandler_fsid
;
143 extern long classichandler_fileid
;
146 * Helper routine to get rid of a loop in execve. Given a pointer to
147 * something for the arg list (which might be in kernel space or in user
148 * space), copy it into the kernel buffer at the currentWritePt. This code
149 * does the proper thing to get the data transferred.
150 * bytesWritten, currentWritePt, and bytesLeft are kept up-to-date.
153 static int copyArgument(char *argument
, int pointerInKernel
,
154 int *bytesWritten
,char **currentWritePt
,
159 if (*bytesLeft
<= 0) {
163 if (pointerInKernel
== UIO_SYSSPACE
) {
164 error
= copystr(argument
, *currentWritePt
, (unsigned)*bytesLeft
, &len
);
167 * pointer in kernel == UIO_USERSPACE
168 * Copy in from user space.
170 error
= copyinstr((caddr_t
)argument
, *currentWritePt
, (unsigned)*bytesLeft
,
173 *currentWritePt
+= len
;
174 *bytesWritten
+= len
;
176 } while (error
== ENAMETOOLONG
);
182 execve(p
, uap
, retval
)
183 register struct proc
*p
;
184 register struct execve_args
*uap
;
187 register struct ucred
*cred
= p
->p_ucred
;
188 register struct filedesc
*fdp
= p
->p_fd
;
191 int na
, ne
, ucp
, ap
, cc
;
193 int executingInterpreter
=0;
195 int executingClassic
=0;
196 char binaryWithClassicName
[sizeof(p
->p_comm
)] = {0};
200 struct vattr origvattr
;
201 vm_offset_t execargs
;
203 struct ps_strings ps
;
205 /* Argument(s) to an interpreter. If we're executing a shell
206 * script, the name (#!/bin/csh) is allowed to be followed by
207 * arguments. cfarg holds these arguments.
212 struct mach_header
*mach_header
;
213 struct fat_header
*fat_header
;
214 struct fat_arch fat_arch
;
216 load_result_t load_result
;
217 struct uthread
*uthread
;
221 boolean_t clean_regions
= FALSE
;
222 shared_region_mapping_t shared_region
= NULL
;
223 shared_region_mapping_t initial_region
= NULL
;
226 /* #! and name of interpreter */
227 char ex_shell
[SHSIZE
];
228 /* Mach-O executable */
229 struct mach_header mach_header
;
231 struct fat_header fat_header
;
236 int savedpathlen
= 0;
237 vm_offset_t
*execargsp
;
241 thread_act_t thr_act
;
244 unsigned long arch_offset
=0;
245 unsigned long arch_size
= 0;
246 char *ws_cache_name
= NULL
; /* used for pre-heat */
249 * XXXAUDIT: Currently, we only audit the pathname of the binary.
250 * There may also be poor interaction with dyld.
253 cfarg
[0] = '\0'; /* initialize to null value. */
254 task
= current_task();
255 thr_act
= current_act();
256 uthread
= get_bsdthread_info(thr_act
);
258 if (uthread
->uu_flag
& P_VFORK
) {
259 vfexec
= 1; /* Mark in exec */
261 if (task
!= kernel_task
) {
262 numthreads
= get_task_numacts(task
);
263 if (numthreads
<= 0 )
265 if (numthreads
> 1) {
271 error
= execargs_alloc(&execargs
);
275 savedpath
= (char *)execargs
;
278 * To support new app package launching for Mac OS X, the dyld
279 * needs the first argument to execve() stored on the user stack.
280 * Copyin the "path" at the begining of the "execargs" buffer
283 * We have to do this before namei() because in case of
284 * symbolic links, namei() would overwrite the original "path".
285 * In case the last symbolic link resolved was a relative pathname
286 * we would lose the original "path", which could be an
287 * absolute pathname. This might be unacceptable for dyld.
289 /* XXX We could optimize to avoid copyinstr in the namei() */
292 * XXXAUDIT: Note: the double copyin introduces an audit
293 * race. To correct this race, we must use a single
297 error
= copyinstr(uap
->fname
, savedpath
,
298 MAXPATHLEN
, (size_t *)&savedpathlen
);
300 execargs_free(execargs
);
304 * copyinstr will put in savedpathlen, the count of
305 * characters (including NULL) in the path.
306 * No app profiles under chroot
309 if((fdp
->fd_rdir
== NULLVP
) && (app_profile
!= 0)) {
311 /* grab the name of the file out of its path */
312 /* we will need this for lookup within the */
314 ws_cache_name
= savedpath
+ savedpathlen
;
315 while (ws_cache_name
[0] != '/') {
316 if(ws_cache_name
== savedpath
) {
325 /* Save the name aside for future use */
326 execargsp
= (vm_offset_t
*)((char *)(execargs
) + savedpathlen
);
328 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
| SAVENAME
| AUDITVNPATH1
,
329 UIO_USERSPACE
, uap
->fname
, p
);
334 VOP_LEASE(vp
, p
, p
->p_ucred
, LEASE_READ
);
336 if ((error
= VOP_GETATTR(vp
, &origvattr
, p
->p_ucred
, p
)))
339 /* Check mount point */
340 if (vp
->v_mount
->mnt_flag
& MNT_NOEXEC
) {
345 if ((vp
->v_mount
->mnt_flag
& MNT_NOSUID
) || (p
->p_flag
& P_TRACED
))
346 origvattr
.va_mode
&= ~(VSUID
| VSGID
);
348 *(&vattr
) = *(&origvattr
);
351 error
= check_exec_access(p
, vp
, &vattr
);
356 * Read in first few bytes of file for segment sizes, magic number:
357 * 407 = plain executable
359 * 413 = demand paged RO text
360 * Also an ASCII line beginning with #! is
361 * the file name of a ``shell'' and arguments may be prepended
362 * to the argument list if given here.
364 * SHELL NAMES ARE LIMITED IN LENGTH.
366 * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM
370 exdata
.ex_shell
[0] = '\0'; /* for zero length files */
372 error
= vn_rdwr(UIO_READ
, vp
, (caddr_t
)&exdata
, sizeof (exdata
), 0,
373 UIO_SYSSPACE
, IO_NODELOCKED
, p
->p_ucred
, &resid
, p
);
379 if (resid
> sizeof(exdata
) - min(sizeof(exdata
.mach_header
),
380 sizeof(exdata
.fat_header
))
381 && exdata
.ex_shell
[0] != '#') {
386 mach_header
= &exdata
.mach_header
;
387 fat_header
= &exdata
.fat_header
;
388 if ((mach_header
->magic
== MH_CIGAM
) &&
389 (classichandler
[0] == 0)) {
392 } else if ((mach_header
->magic
== MH_MAGIC
) ||
393 (mach_header
->magic
== MH_CIGAM
)) {
395 } else if ((fat_header
->magic
== FAT_MAGIC
) ||
396 (fat_header
->magic
== FAT_CIGAM
)) {
399 /* If we've already redirected once from an interpreted file
400 * to an interpreter, don't permit the second time.
402 if (exdata
.ex_shell
[0] != '#' ||
403 exdata
.ex_shell
[1] != '!' ||
404 executingInterpreter
) {
408 if (executingClassic
== 1) {
412 cp
= &exdata
.ex_shell
[2]; /* skip "#!" */
413 while (cp
< &exdata
.ex_shell
[SHSIZE
]) {
414 if (*cp
== '\t') /* convert all tabs to spaces */
416 else if (*cp
== '\n' || *cp
== '#') {
417 *cp
= '\0'; /* trunc the line at nl or comment */
419 /* go back and remove the spaces before the /n or # */
420 /* todo: do we have to do this if we fix the passing of args to shells ? */
421 if ( cp
!= &exdata
.ex_shell
[2] ) {
426 } while ( cp
!= &exdata
.ex_shell
[2] );
436 cp
= &exdata
.ex_shell
[2];
440 while (*cp
&& *cp
!= ' ')
449 bcopy((caddr_t
)cp
, (caddr_t
)cfarg
, SHSIZE
);
453 * Support for new app package launching for Mac OS X.
454 * We are about to retry the execve() by changing the path to the
455 * interpreter name. Need to re-initialize the savedpath and
456 * savedpathlen. +1 for NULL.
458 savedpathlen
= (cpnospace
- execnamep
+ 1);
459 error
= copystr(execnamep
, savedpath
,
460 savedpathlen
, (size_t *)&savedpathlen
);
464 /* Save the name aside for future use */
465 execargsp
= (vm_offset_t
*)((char *)(execargs
) + savedpathlen
);
467 executingInterpreter
= 1;
469 nd
.ni_cnd
.cn_nameiop
= LOOKUP
;
470 nd
.ni_cnd
.cn_flags
= (nd
.ni_cnd
.cn_flags
& HASBUF
) |
471 (FOLLOW
| LOCKLEAF
| SAVENAME
);
472 nd
.ni_segflg
= UIO_SYSSPACE
;
473 nd
.ni_dirp
= execnamep
;
474 if ((error
= namei(&nd
)))
477 VOP_LEASE(vp
, p
, cred
, LEASE_READ
);
478 if ((error
= VOP_GETATTR(vp
, &vattr
, p
->p_ucred
, p
)))
484 * Collect arguments on "file" in swap space.
491 * Support for new app package launching for Mac OS X allocates
492 * the "path" at the begining.
493 * execargs get allocated after that
495 cp
= (char *) execargsp
; /* running pointer for copy */
497 * size of execargs less sizeof "path",
498 * a pointer to "path" and a NULL poiter
500 cc
= NCARGS
- savedpathlen
- 2*NBPW
;
502 * Copy arguments into file in argdev area.
507 * If we have a fat file, find "our" executable.
511 * Look up our architecture in the fat file.
513 lret
= fatfile_getarch_affinity(vp
,(vm_offset_t
)fat_header
, &fat_arch
,
514 (p
->p_flag
& P_AFFINITY
));
515 if (lret
!= LOAD_SUCCESS
) {
516 error
= load_return_to_errno(lret
);
519 /* Read the Mach-O header out of it */
520 error
= vn_rdwr(UIO_READ
, vp
, (caddr_t
)&exdata
.mach_header
,
521 sizeof (exdata
.mach_header
),
523 UIO_SYSSPACE
, (IO_UNIT
|IO_NODELOCKED
), cred
, &resid
, p
);
529 /* Did we read a complete header? */
535 /* Is what we found a Mach-O executable */
536 if ((mach_header
->magic
!= MH_MAGIC
) &&
537 (mach_header
->magic
!= MH_CIGAM
)) {
542 arch_offset
= fat_arch
.offset
;
543 arch_size
= fat_arch
.size
;
546 * Load the Mach-O file.
549 arch_size
= (u_long
)vattr
.va_size
;
552 if ( ! check_cpu_subtype(mach_header
->cpusubtype
) ) {
557 if (mach_header
->magic
== MH_CIGAM
) {
559 int classicBinaryLen
= nd
.ni_cnd
.cn_namelen
;
560 if (classicBinaryLen
> MAXCOMLEN
)
561 classicBinaryLen
= MAXCOMLEN
;
562 bcopy((caddr_t
)nd
.ni_cnd
.cn_nameptr
,
563 (caddr_t
)binaryWithClassicName
,
564 (unsigned)classicBinaryLen
);
565 binaryWithClassicName
[classicBinaryLen
] = '\0';
566 executingClassic
= 1;
568 vput(vp
); /* cleanup? */
569 nd
.ni_cnd
.cn_nameiop
= LOOKUP
;
571 nd
.ni_cnd
.cn_flags
= (nd
.ni_cnd
.cn_flags
& HASBUF
) |
572 /* (FOLLOW | LOCKLEAF | SAVENAME) */
573 (LOCKLEAF
| SAVENAME
);
574 nd
.ni_segflg
= UIO_SYSSPACE
;
576 nd
.ni_dirp
= classichandler
;
577 if ((error
= namei(&nd
)) != 0) {
583 VOP_LEASE(vp
,p
,cred
,LEASE_READ
);
584 if ((error
= VOP_GETATTR(vp
,&vattr
,p
->p_ucred
,p
))) {
590 if (uap
->argp
!= NULL
) {
591 /* geez -- why would argp ever be NULL, and why would we proceed? */
593 /* First, handle any argument massaging */
594 if (executingInterpreter
&& executingClassic
) {
595 error
= copyArgument(classichandler
,UIO_SYSSPACE
,&nc
,&cp
,&cc
);
599 /* Now name the interpreter. */
600 error
= copyArgument(savedpath
,UIO_SYSSPACE
,&nc
,&cp
,&cc
);
605 * if we're running an interpreter, as we'd be passing the
606 * command line executable as an argument to the interpreter already.
607 * Doing "execve("myShellScript","bogusName",arg1,arg2,...)
608 * probably shouldn't ever let bogusName be seen by the shell
613 error
= copyArgument(cfarg
,UIO_SYSSPACE
,&nc
,&cp
,&cc
);
618 char* originalExecutable
= uap
->fname
;
619 error
= copyArgument(originalExecutable
,UIO_USERSPACE
,&nc
,&cp
,&cc
);
621 /* remove argv[0] b/c we've already placed it at */
626 /* and continue with rest of the arguments. */
627 } else if (executingClassic
) {
628 error
= copyArgument(classichandler
,UIO_SYSSPACE
,&nc
,&cp
,&cc
);
632 char* originalExecutable
= uap
->fname
;
633 error
= copyArgument(originalExecutable
,UIO_USERSPACE
,&nc
,&cp
,&cc
);
638 /* and rest of arguments continue as before. */
639 } else if (executingInterpreter
) {
640 char *actualExecutable
= nd
.ni_cnd
.cn_nameptr
;
641 error
= copyArgument(actualExecutable
,UIO_SYSSPACE
,&nc
,&cp
,&cc
);
643 /* remove argv[0] b/c we just placed it in the arg list. */
646 /* Copy the argument in the interpreter first line if there
650 error
= copyArgument(cfarg
,UIO_SYSSPACE
,&nc
,&cp
,&cc
);
655 /* copy the name of the file being interpreted, gotten from
656 * the structures passed in to execve.
658 error
= copyArgument(uap
->fname
,UIO_USERSPACE
,&nc
,&cp
,&cc
);
661 /* Now, get rest of arguments */
662 while (uap
->argp
!= NULL
) {
663 char* userArgument
= (char*)fuword((caddr_t
) uap
->argp
);
665 if (userArgument
== NULL
) {
667 } else if ((int)userArgument
== -1) {
668 /* Um... why would it be -1? */
672 error
= copyArgument(userArgument
, UIO_USERSPACE
,&nc
,&cp
,&cc
);
676 /* Now, get the environment */
677 while (uap
->envp
!= NULL
) {
678 char *userEnv
= (char*) fuword((caddr_t
) uap
->envp
);
680 if (userEnv
== NULL
) {
682 } else if ((int)userEnv
== -1) {
686 error
= copyArgument(userEnv
,UIO_USERSPACE
,&nc
,&cp
,&cc
);
693 /* make sure there are nulls are the end!! */
702 /* and round up count of bytes written to next word. */
703 nc
= (nc
+ NBPW
-1) & ~(NBPW
-1);
705 if (vattr
.va_fsid
== classichandler_fsid
&&
706 vattr
.va_fileid
== classichandler_fileid
) {
707 executingClassic
= 1;
711 kern_return_t result
;
713 result
= task_create_internal(task
, FALSE
, &new_task
);
714 if (result
!= KERN_SUCCESS
)
715 printf("execve: task_create failed. Code: 0x%x\n", result
);
717 set_bsdtask_info(new_task
, p
);
721 map
= get_task_map(new_task
);
722 result
= thread_create(new_task
, &thr_act
);
723 if (result
!= KERN_SUCCESS
)
724 printf("execve: thread_create failed. Code: 0x%x\n", result
);
725 uthread
= get_bsdthread_info(thr_act
);
731 * Load the Mach-O file.
733 VOP_UNLOCK(vp
, 0, p
); /* XXX */
735 tws_handle_startup_file(task
, cred
->cr_uid
,
736 ws_cache_name
, vp
, &clean_regions
);
739 vm_get_shared_region(task
, &initial_region
);
740 int parentIsClassic
= (p
->p_flag
& P_CLASSIC
);
741 struct vnode
*rootDir
= p
->p_fd
->fd_rdir
;
743 if ((parentIsClassic
&& !executingClassic
) ||
744 (!parentIsClassic
&& executingClassic
)) {
745 shared_region
= lookup_default_shared_region(
749 machine_slot
[cpu_number()].cpu_type
));
750 if (shared_region
== NULL
) {
751 shared_region_mapping_t old_region
;
752 shared_region_mapping_t new_region
;
753 vm_get_shared_region(current_task(), &old_region
);
754 /* grrrr... this sets current_task(), not task
755 * -- they're different (usually)
757 shared_file_boot_time_init(
761 machine_slot
[cpu_number()].cpu_type
));
762 if ( current_task() != task
) {
763 vm_get_shared_region(current_task(),&new_region
);
764 vm_set_shared_region(task
,new_region
);
765 vm_set_shared_region(current_task(),old_region
);
768 vm_set_shared_region(task
, shared_region
);
770 shared_region_mapping_dealloc(initial_region
);
773 lret
= load_machfile(vp
, mach_header
, arch_offset
,
774 arch_size
, &load_result
, thr_act
, map
, clean_regions
);
776 if (lret
!= LOAD_SUCCESS
) {
777 error
= load_return_to_errno(lret
);
783 /* load_machfile() maps the vnode */
787 * deal with set[ug]id.
789 p
->p_flag
&= ~P_SUGID
;
790 if (((origvattr
.va_mode
& VSUID
) != 0 &&
791 p
->p_ucred
->cr_uid
!= origvattr
.va_uid
)
792 || (origvattr
.va_mode
& VSGID
) != 0 &&
793 p
->p_ucred
->cr_gid
!= origvattr
.va_gid
) {
794 p
->p_ucred
= crcopy(cred
);
797 * If process is being ktraced, turn off - unless
800 if (p
->p_tracep
&& !(p
->p_traceflag
& KTRFAC_ROOT
)) {
801 struct vnode
*tvp
= p
->p_tracep
;
805 if (UBCINFOEXISTS(tvp
))
810 if (origvattr
.va_mode
& VSUID
)
811 p
->p_ucred
->cr_uid
= origvattr
.va_uid
;
812 if (origvattr
.va_mode
& VSGID
)
813 p
->p_ucred
->cr_gid
= origvattr
.va_gid
;
816 * Have mach reset the task port. We don't want
817 * anyone who had the task port before a setuid
818 * exec to be able to access/control the task
821 ipc_task_reset(task
);
823 p
->p_flag
|= P_SUGID
;
825 /* Radar 2261856; setuid security hole fix */
826 /* Patch from OpenBSD: A. Ramesh */
828 * XXX For setuid processes, attempt to ensure that
829 * stdin, stdout, and stderr are already allocated.
830 * We do not want userland to accidentally allocate
831 * descriptors in this range which has implied meaning
834 for (i
= 0; i
< 3; i
++) {
835 extern struct fileops vnops
;
836 struct nameidata nd1
;
840 if (p
->p_fd
->fd_ofiles
[i
] == NULL
) {
841 if ((error
= falloc(p
, &fp
, &indx
)) != 0)
843 NDINIT(&nd1
, LOOKUP
, FOLLOW
, UIO_SYSSPACE
,
845 if ((error
= vn_open(&nd1
, FREAD
, 0)) != 0) {
847 p
->p_fd
->fd_ofiles
[indx
] = NULL
;
851 fp
->f_type
= DTYPE_VNODE
;
853 fp
->f_data
= (caddr_t
)nd1
.ni_vp
;
854 VOP_UNLOCK(nd1
.ni_vp
, 0, p
);
858 p
->p_cred
->p_svuid
= p
->p_ucred
->cr_uid
;
859 p
->p_cred
->p_svgid
= p
->p_ucred
->cr_gid
;
860 set_security_token(p
);
862 KNOTE(&p
->p_klist
, NOTE_EXEC
);
864 if (!vfexec
&& (p
->p_flag
& P_TRACED
))
872 VOP_LOCK(vp
, LK_EXCLUSIVE
| LK_RETRY
, p
); /* XXX */
876 if (load_result
.unixproc
&&
877 create_unix_stack(get_task_map(task
),
878 load_result
.user_stack
, load_result
.customstack
, p
)) {
879 error
= load_return_to_errno(LOAD_NOSPACE
);
884 uthread
->uu_ar0
= (void *)get_user_regs(thr_act
);
888 * Copy back arglist if necessary.
892 ucp
= (int)p
->user_stack
;
894 old_map
= vm_map_switch(get_task_map(task
));
896 if (load_result
.unixproc
) {
899 ucp
= ucp
- nc
- NBPW
; /* begining of the STRING AREA */
902 * Support for new app package launching for Mac OS X allocates
903 * the "path" at the begining of the execargs buffer.
904 * copy it just before the string area.
907 pathptr
= ucp
- ((savedpathlen
+ NBPW
-1) & ~(NBPW
-1));
908 error
= copyoutstr(savedpath
, (caddr_t
)pathptr
,
909 (unsigned)savedpathlen
, (size_t *)&len
);
910 savedpathlen
= (savedpathlen
+ NBPW
-1) & ~(NBPW
-1);
914 vm_map_switch(old_map
);
919 * Record the size of the arguments area so that
920 * sysctl_procargs() can return the argument area without having
921 * to parse the arguments.
923 p
->p_argslen
= (int)p
->user_stack
- pathptr
;
924 p
->p_argc
= na
- ne
; /* save argc for sysctl_procargs() */
926 /* Save a NULL pointer below it */
927 (void) suword((caddr_t
)(pathptr
- NBPW
), 0);
929 /* Save the pointer to "path" just below it */
930 (void) suword((caddr_t
)(pathptr
- 2*NBPW
), pathptr
);
933 * na includes arg[] and env[].
934 * NBPW for 2 NULL one each ofter arg[argc -1] and env[n]
936 * skip over saved path, NBPW for pointer to path,
937 * and NBPW for the NULL after pointer to path.
939 ap
= ucp
- na
*NBPW
- 3*NBPW
- savedpathlen
- 2*NBPW
;
941 thread_setuserstack(thr_act
, ap
); /* Set the stack */
943 uthread
->uu_ar0
[SP
] = ap
;
945 (void) suword((caddr_t
)ap
, na
-ne
); /* argc */
949 cp
= (char *) execargsp
;
950 cc
= NCARGS
- savedpathlen
- 2*NBPW
;
951 ps
.ps_argvstr
= (char *)ucp
; /* first argv string */
952 ps
.ps_nargvstr
= na
- ne
; /* argc */
956 (void) suword((caddr_t
)ap
, 0);
958 ps
.ps_envstr
= (char *)ucp
;
963 (void) suword((caddr_t
)ap
, ucp
);
965 error
= copyoutstr(cp
, (caddr_t
)ucp
,
966 (unsigned)cc
, (size_t *)&len
);
971 } while (error
== ENAMETOOLONG
);
973 break; /* bad stack - user's problem */
975 (void) suword((caddr_t
)ap
, 0);
978 if (load_result
.dynlinker
) {
980 ap
= thread_adjuserstack(thr_act
, -4); /* Adjust the stack */
982 ap
= uthread
->uu_ar0
[SP
] -= 4;
984 (void) suword((caddr_t
)ap
, load_result
.mach_header
);
988 vm_map_switch(old_map
);
991 thread_setentrypoint(thr_act
, load_result
.entry_point
); /* Set the entry point */
993 uthread
->uu_ar0
[PC
] = load_result
.entry_point
;
995 #error architecture not implemented!
1002 * Reset signal state.
1004 execsigs(p
, thr_act
);
1007 * Close file descriptors
1008 * which specify close-on-exec.
1013 * need to cancel async IO requests that can be cancelled and wait for those
1014 * already active. MAY BLOCK!
1018 /* FIXME: Till vmspace inherit is fixed: */
1019 if (!vfexec
&& p
->vm_shm
)
1021 /* Clean up the semaphores */
1025 * Remember file name for accounting.
1027 p
->p_acflag
&= ~AFORK
;
1028 /* If the translated name isn't NULL, then we want to use
1029 * that translated name as the name we show as the "real" name.
1030 * Otherwise, use the name passed into exec.
1032 if (0 != binaryWithClassicName
[0]) {
1033 bcopy((caddr_t
)binaryWithClassicName
, (caddr_t
)p
->p_comm
,
1034 sizeof(binaryWithClassicName
));
1036 if (nd
.ni_cnd
.cn_namelen
> MAXCOMLEN
)
1037 nd
.ni_cnd
.cn_namelen
= MAXCOMLEN
;
1038 bcopy((caddr_t
)nd
.ni_cnd
.cn_nameptr
, (caddr_t
)p
->p_comm
,
1039 (unsigned)nd
.ni_cnd
.cn_namelen
);
1040 p
->p_comm
[nd
.ni_cnd
.cn_namelen
] = '\0';
1044 /* This is for kdebug */
1045 long dbg_arg1
, dbg_arg2
, dbg_arg3
, dbg_arg4
;
1047 /* Collect the pathname for tracing */
1048 kdbg_trace_string(p
, &dbg_arg1
, &dbg_arg2
, &dbg_arg3
, &dbg_arg4
);
1054 KERNEL_DEBUG_CONSTANT1((TRACEDBG_CODE(DBG_TRACE_DATA
, 2)) | DBG_FUNC_NONE
,
1055 p
->p_pid
,0,0,0, (unsigned int)thr_act
);
1056 KERNEL_DEBUG_CONSTANT1((TRACEDBG_CODE(DBG_TRACE_STRING
, 2)) | DBG_FUNC_NONE
,
1057 dbg_arg1
, dbg_arg2
, dbg_arg3
, dbg_arg4
, (unsigned int)thr_act
);
1061 KERNEL_DEBUG_CONSTANT((TRACEDBG_CODE(DBG_TRACE_DATA
, 2)) | DBG_FUNC_NONE
,
1063 KERNEL_DEBUG_CONSTANT((TRACEDBG_CODE(DBG_TRACE_STRING
, 2)) | DBG_FUNC_NONE
,
1064 dbg_arg1
, dbg_arg2
, dbg_arg3
, dbg_arg4
, 0);
1068 if (executingClassic
)
1069 p
->p_flag
|= P_CLASSIC
| P_AFFINITY
;
1071 p
->p_flag
&= ~P_CLASSIC
;
1074 * mark as execed, wakeup the process that vforked (if any) and tell
1075 * it that it now has it's own resources back
1077 p
->p_flag
|= P_EXEC
;
1078 if (p
->p_pptr
&& (p
->p_flag
& P_PPWAIT
)) {
1079 p
->p_flag
&= ~P_PPWAIT
;
1080 wakeup((caddr_t
)p
->p_pptr
);
1083 if (vfexec
&& (p
->p_flag
& P_TRACED
)) {
1084 psignal_vfork(p
, new_task
, thr_act
, SIGTRAP
);
1089 task_deallocate(new_task
);
1090 act_deallocate(thr_act
);
1095 FREE_ZONE(nd
.ni_cnd
.cn_pnbuf
, nd
.ni_cnd
.cn_pnlen
, M_NAMEI
);
1100 execargs_free(execargs
);
1101 if (!error
&& vfexec
) {
1102 vfork_return(current_act(), p
->p_pptr
, p
, retval
);
1103 (void) thread_resume(thr_act
);
1110 #define unix_stack_size(p) (p->p_rlimit[RLIMIT_STACK].rlim_cur)
1113 create_unix_stack(map
, user_stack
, customstack
, p
)
1115 vm_offset_t user_stack
;
1122 p
->user_stack
= (caddr_t
)user_stack
;
1124 size
= round_page_64(unix_stack_size(p
));
1125 addr
= trunc_page_32(user_stack
- size
);
1126 return (vm_allocate(map
, &addr
, size
,
1127 VM_MAKE_TAG(VM_MEMORY_STACK
) | FALSE
));
1129 return(KERN_SUCCESS
);
1132 #include <sys/reboot.h>
1134 char init_program_name
[128] = "/sbin/mach_init\0";
1136 char init_args
[128] = "";
1138 struct execve_args init_exec_args
;
1139 int init_attempts
= 0;
1143 load_init_program(p
)
1146 vm_offset_t init_addr
;
1150 register_t retval
[2];
1151 struct uthread
* ut
;
1155 /* init_args are copied in string form directly from bootstrap */
1158 if (boothowto
& RB_INITNAME
) {
1159 printf("init program? ");
1161 gets(init_program_name
, init_program_name
);
1162 #endif /* FIXME ] */
1165 if (error
&& ((boothowto
& RB_INITNAME
) == 0) &&
1166 (init_attempts
== 1)) {
1167 static char other_init
[] = "/etc/mach_init";
1168 printf("Load of %s, errno %d, trying %s\n",
1169 init_program_name
, error
, other_init
);
1171 bcopy(other_init
, init_program_name
,
1172 sizeof(other_init
));
1178 printf("Load of %s failed, errno %d\n",
1179 init_program_name
, error
);
1181 boothowto
|= RB_INITNAME
;
1186 * Copy out program name.
1189 init_addr
= VM_MIN_ADDRESS
;
1190 (void) vm_allocate(current_map(), &init_addr
,
1194 (void) copyout((caddr_t
) init_program_name
,
1195 (caddr_t
) (init_addr
),
1196 (unsigned) sizeof(init_program_name
)+1);
1198 argv
[0] = (char *) init_addr
;
1199 init_addr
+= sizeof(init_program_name
);
1200 init_addr
= (vm_offset_t
)ROUND_PTR(char, init_addr
);
1203 * Put out first (and only) argument, similarly.
1204 * Assumes everything fits in a page as allocated
1208 (void) copyout((caddr_t
) init_args
,
1209 (caddr_t
) (init_addr
),
1210 (unsigned) sizeof(init_args
));
1212 argv
[1] = (char *) init_addr
;
1213 init_addr
+= sizeof(init_args
);
1214 init_addr
= (vm_offset_t
)ROUND_PTR(char, init_addr
);
1217 * Null-end the argument list
1220 argv
[2] = (char *) 0;
1223 * Copy out the argument list.
1226 (void) copyout((caddr_t
) argv
,
1227 (caddr_t
) (init_addr
),
1228 (unsigned) sizeof(argv
));
1231 * Set up argument block for fake call to execve.
1234 init_exec_args
.fname
= argv
[0];
1235 init_exec_args
.argp
= (char **) init_addr
;
1236 init_exec_args
.envp
= 0;
1238 /* So that mach_init task
1239 * is set with uid,gid 0 token
1241 set_security_token(p
);
1243 error
= execve(p
,&init_exec_args
,retval
);
1248 * Convert a load_return_t to an errno.
1251 load_return_to_errno(load_return_t lrtn
)
1278 * exec_check_access()
1281 check_exec_access(p
, vp
, vap
)
1289 if (error
= VOP_ACCESS(vp
, VEXEC
, p
->p_ucred
, p
))
1292 if (flag
& P_TRACED
) {
1293 if (error
= VOP_ACCESS(vp
, VREAD
, p
->p_ucred
, p
))
1296 if (vp
->v_type
!= VREG
||
1297 (vap
->va_mode
& (S_IXUSR
| S_IXGRP
| S_IXOTH
)) == 0)
1302 #include <mach/mach_types.h>
1303 #include <mach/vm_prot.h>
1304 #include <mach/semaphore.h>
1305 #include <mach/sync_policy.h>
1306 #include <kern/clock.h>
1307 #include <mach/kern_return.h>
1309 extern semaphore_t execve_semaphore
;
1312 execargs_alloc(addrp
)
1317 kret
= semaphore_wait(execve_semaphore
);
1318 if (kret
!= KERN_SUCCESS
)
1322 case KERN_INVALID_ADDRESS
:
1323 case KERN_PROTECTION_FAILURE
:
1326 case KERN_OPERATION_TIMED_OUT
:
1330 kret
= kmem_alloc_pageable(bsd_pageable_map
, addrp
, NCARGS
);
1331 if (kret
!= KERN_SUCCESS
) {
1332 semaphore_signal(execve_semaphore
);
1344 kmem_free(bsd_pageable_map
, addr
, NCARGS
);
1346 kret
= semaphore_signal(execve_semaphore
);
1348 case KERN_INVALID_ADDRESS
:
1349 case KERN_PROTECTION_FAILURE
:
1352 case KERN_OPERATION_TIMED_OUT
: