2 * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
25 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
27 * Mach Operating System
28 * Copyright (c) 1987 Carnegie-Mellon University
29 * All rights reserved. The CMU software License Agreement specifies
30 * the terms and conditions for use and redistribution.
36 * Copyright (c) 1982, 1986, 1991, 1993
37 * The Regents of the University of California. All rights reserved.
38 * (c) UNIX System Laboratories, Inc.
39 * All or some portions of this file are derived from material licensed
40 * to the University of California by American Telephone and Telegraph
41 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
42 * the permission of UNIX System Laboratories, Inc.
44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions
47 * 1. Redistributions of source code must retain the above copyright
48 * notice, this list of conditions and the following disclaimer.
49 * 2. Redistributions in binary form must reproduce the above copyright
50 * notice, this list of conditions and the following disclaimer in the
51 * documentation and/or other materials provided with the distribution.
52 * 3. All advertising materials mentioning features or use of this software
53 * must display the following acknowledgement:
54 * This product includes software developed by the University of
55 * California, Berkeley and its contributors.
56 * 4. Neither the name of the University nor the names of its contributors
57 * may be used to endorse or promote products derived from this software
58 * without specific prior written permission.
60 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
61 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
62 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
63 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
64 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
65 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
66 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
67 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
68 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
69 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72 * from: @(#)kern_exec.c 8.1 (Berkeley) 6/10/93
74 #include <machine/reg.h>
76 #include <sys/param.h>
77 #include <sys/systm.h>
78 #include <sys/filedesc.h>
79 #include <sys/kernel.h>
83 #include <sys/socketvar.h>
84 #include <sys/malloc.h>
85 #include <sys/namei.h>
86 #include <sys/mount.h>
87 #include <sys/vnode.h>
93 #include <sys/kdebug.h>
94 #include <sys/signal.h>
96 #include <mach/vm_param.h>
98 #include <vm/vm_map.h>
99 #include <vm/vm_kern.h>
100 #include <vm/vm_shared_memory_server.h>
102 #include <kern/thread.h>
103 #include <kern/task.h>
105 #include <kern/ast.h>
106 #include <kern/mach_loader.h>
107 #include <mach-o/fat.h>
108 #include <mach-o/loader.h>
109 #include <machine/vmparam.h>
111 #include <sys/ktrace.h>
116 extern vm_map_t bsd_pageable_map
;
118 #define ROUND_PTR(type, addr) \
119 (type *)( ( (unsigned)(addr) + 16 - 1) \
122 static int load_return_to_errno(load_return_t lrtn
);
123 int execve(struct proc
*p
, struct execve_args
*uap
, register_t
*retval
);
124 static int execargs_alloc(vm_offset_t
*addrp
);
125 static int execargs_free(vm_offset_t addr
);
128 execv(p
, args
, retval
)
133 ((struct execve_args
*)args
)->envp
= NULL
;
134 return (execve(p
, args
, retval
));
139 execve(p
, uap
, retval
)
140 register struct proc
*p
;
141 register struct execve_args
*uap
;
144 register struct ucred
*cred
= p
->p_ucred
;
145 register struct filedesc
*fdp
= p
->p_fd
;
148 int na
, ne
, ucp
, ap
, cc
;
155 struct vattr origvattr
;
156 vm_offset_t execargs
;
158 struct ps_strings ps
;
163 struct mach_header
*mach_header
;
164 struct fat_header
*fat_header
;
165 struct fat_arch fat_arch
;
167 load_result_t load_result
;
168 struct uthread
*uthread
;
172 boolean_t new_shared_regions
= FALSE
;
174 /* #! and name of interpreter */
175 char ex_shell
[SHSIZE
];
176 /* Mach-O executable */
177 struct mach_header mach_header
;
179 struct fat_header fat_header
;
184 int savedpathlen
= 0;
185 vm_offset_t
*execargsp
;
189 thread_act_t thr_act
;
192 unsigned long arch_offset
=0;
193 unsigned long arch_size
= 0;
194 char *ws_cache_name
= NULL
; /* used for pre-heat */
196 task
= current_task();
197 thr_act
= current_act();
198 uthread
= get_bsdthread_info(thr_act
);
200 if (uthread
->uu_flag
& P_VFORK
) {
201 vfexec
= 1; /* Mark in exec */
203 if (task
!= kernel_task
) {
204 numthreads
= get_task_numacts(task
);
205 if (numthreads
<= 0 )
207 if (numthreads
> 1) {
213 error
= execargs_alloc(&execargs
);
217 savedpath
= execargs
;
220 * To support new app package launching for Mac OS X, the dyld
221 * needs the first argument to execve() stored on the user stack.
222 * Copyin the "path" at the begining of the "execargs" buffer
225 * We have to do this before namei() because in case of
226 * symbolic links, namei() would overwrite the original "path".
227 * In case the last symbolic link resolved was a relative pathname
228 * we would lose the original "path", which could be an
229 * absolute pathname. This might be unacceptable for dyld.
231 /* XXX We could optimize to avoid copyinstr in the namei() */
233 error
= copyinstr(uap
->fname
, savedpath
, MAXPATHLEN
, &savedpathlen
);
237 * copyinstr will put in savedpathlen, the count of
238 * characters (including NULL) in the path.
241 if(app_profile
!= 0) {
243 /* grab the name of the file out of its path */
244 /* we will need this for lookup within the */
246 ws_cache_name
= savedpath
+ savedpathlen
;
247 while (ws_cache_name
[0] != '/') {
248 if(ws_cache_name
== savedpath
) {
257 /* Save the name aside for future use */
258 execargsp
= (vm_offset_t
*)((char *)(execargs
) + savedpathlen
);
260 NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
| SAVENAME
,
261 UIO_USERSPACE
, uap
->fname
, p
);
262 if ((error
= namei(&nd
)))
265 VOP_LEASE(vp
, p
, p
->p_ucred
, LEASE_READ
);
267 if ((error
= VOP_GETATTR(vp
, &origvattr
, p
->p_ucred
, p
)))
270 /* Check mount point */
271 if (vp
->v_mount
->mnt_flag
& MNT_NOEXEC
) {
277 if ((vp
->v_mount
->mnt_flag
& MNT_NOSUID
) || (p
->p_flag
& P_TRACED
))
278 origvattr
.va_mode
&= ~(VSUID
| VSGID
);
280 *(&vattr
) = *(&origvattr
);
283 error
= check_exec_access(p
, vp
, &vattr
);
288 * Read in first few bytes of file for segment sizes, magic number:
289 * 407 = plain executable
291 * 413 = demand paged RO text
292 * Also an ASCII line beginning with #! is
293 * the file name of a ``shell'' and arguments may be prepended
294 * to the argument list if given here.
296 * SHELL NAMES ARE LIMITED IN LENGTH.
298 * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM
302 exdata
.ex_shell
[0] = '\0'; /* for zero length files */
304 error
= vn_rdwr(UIO_READ
, vp
, (caddr_t
)&exdata
, sizeof (exdata
), 0,
305 UIO_SYSSPACE
, IO_NODELOCKED
, p
->p_ucred
, &resid
, p
);
311 if (resid
> sizeof(exdata
) - min(sizeof(exdata
.mach_header
),
312 sizeof(exdata
.fat_header
))
313 && exdata
.ex_shell
[0] != '#') {
318 mach_header
= &exdata
.mach_header
;
319 fat_header
= &exdata
.fat_header
;
320 if (mach_header
->magic
== MH_MAGIC
)
322 else if (fat_header
->magic
== FAT_MAGIC
||
323 fat_header
->magic
== FAT_CIGAM
)
325 else if (mach_header
->magic
== MH_CIGAM
) {
329 if (exdata
.ex_shell
[0] != '#' ||
330 exdata
.ex_shell
[1] != '!' ||
335 cp
= &exdata
.ex_shell
[2]; /* skip "#!" */
336 while (cp
< &exdata
.ex_shell
[SHSIZE
]) {
339 else if (*cp
== '\n') {
349 cp
= &exdata
.ex_shell
[2];
353 while (*cp
&& *cp
!= ' ')
362 bcopy((caddr_t
)cp
, (caddr_t
)cfarg
, SHSIZE
);
366 * Support for new app package launching for Mac OS X.
367 * We are about to retry the execve() by changing the path to the
368 * interpreter name. Need to re-initialize the savedpath and
369 * savedpathlen. +1 for NULL.
371 savedpathlen
= (cpnospace
- execnamep
+ 1);
372 error
= copystr(execnamep
, savedpath
, savedpathlen
, &savedpathlen
);
376 /* Save the name aside for future use */
377 execargsp
= (vm_offset_t
*)((char *)(execargs
) + savedpathlen
);
381 nd
.ni_cnd
.cn_nameiop
= LOOKUP
;
382 nd
.ni_cnd
.cn_flags
= (nd
.ni_cnd
.cn_flags
& HASBUF
) |
383 (FOLLOW
| LOCKLEAF
| SAVENAME
);
384 nd
.ni_segflg
= UIO_SYSSPACE
;
385 nd
.ni_dirp
= execnamep
;
386 if ((error
= namei(&nd
)))
389 VOP_LEASE(vp
, p
, cred
, LEASE_READ
);
390 if ((error
= VOP_GETATTR(vp
, &vattr
, p
->p_ucred
, p
)))
396 * Collect arguments on "file" in swap space.
403 * Support for new app package launching for Mac OS X allocates
404 * the "path" at the begining.
405 * execargs get allocated after that
407 cp
= (char *) execargsp
; /* running pointer for copy */
409 * size of execargs less sizeof "path",
410 * a pointer to "path" and a NULL poiter
412 cc
= NCARGS
- savedpathlen
- 2*NBPW
;
414 * Copy arguments into file in argdev area.
416 if (uap
->argp
) for (;;) {
419 if (indir
&& na
== 0) {
420 sharg
= nd
.ni_cnd
.cn_nameptr
;
422 uap
->argp
++; /* ignore argv[0] */
423 } else if (indir
&& (na
== 1 && cfarg
[0])) {
426 } else if (indir
&& (na
== 1 || (na
== 2 && cfarg
[0])))
427 ap
= (int)uap
->fname
;
428 else if (uap
->argp
) {
429 ap
= fuword((caddr_t
)uap
->argp
);
432 if (ap
== NULL
&& uap
->envp
) {
434 if ((ap
= fuword((caddr_t
)uap
->envp
)) != NULL
)
445 if (nc
>= (NCARGS
- savedpathlen
- 2*NBPW
-1)) {
450 error
= copystr(sharg
, cp
, (unsigned)cc
, &len
);
453 error
= copyinstr((caddr_t
)ap
, cp
, (unsigned)cc
,
460 } while (error
== ENAMETOOLONG
);
465 nc
= (nc
+ NBPW
-1) & ~(NBPW
-1);
468 * If we have a fat file, find "our" executable.
472 * Look up our architecture in the fat file.
474 lret
= fatfile_getarch(vp
, (vm_offset_t
)fat_header
, &fat_arch
);
475 if (lret
!= LOAD_SUCCESS
) {
476 error
= load_return_to_errno(lret
);
479 /* Read the Mach-O header out of it */
480 error
= vn_rdwr(UIO_READ
, vp
, (caddr_t
)&exdata
.mach_header
,
481 sizeof (exdata
.mach_header
),
483 UIO_SYSSPACE
, (IO_UNIT
|IO_NODELOCKED
), cred
, &resid
, p
);
489 /* Did we read a complete header? */
495 /* Is what we found a Mach-O executable */
496 if (mach_header
->magic
!= MH_MAGIC
) {
501 arch_offset
= fat_arch
.offset
;
502 arch_size
= fat_arch
.size
;
505 * Load the Mach-O file.
508 arch_size
= (u_long
)vattr
.va_size
;
512 kern_return_t result
;
514 result
= task_create_local(task
, FALSE
, FALSE
, &new_task
);
515 if (result
!= KERN_SUCCESS
)
516 printf("execve: task_create failed. Code: 0x%x\n", result
);
518 set_bsdtask_info(new_task
, p
);
522 map
= get_task_map(new_task
);
523 result
= thread_create(new_task
, &thr_act
);
524 if (result
!= KERN_SUCCESS
)
525 printf("execve: thread_create failed. Code: 0x%x\n", result
);
526 uthread
= get_bsdthread_info(thr_act
);
533 * Load the Mach-O file.
535 VOP_UNLOCK(vp
, 0, p
);
537 tws_handle_startup_file(task
, cred
->cr_uid
,
538 ws_cache_name
, vp
, &new_shared_regions
);
540 if (new_shared_regions
) {
541 shared_region_mapping_t new_shared_region
;
542 shared_region_mapping_t old_shared_region
;
544 if (shared_file_create_system_region(&new_shared_region
))
545 panic("couldn't create system_shared_region\n");
547 vm_get_shared_region(task
, &old_shared_region
);
548 vm_set_shared_region(task
, new_shared_region
);
550 shared_region_mapping_dealloc(old_shared_region
);
553 lret
= load_machfile(vp
, mach_header
, arch_offset
,
554 arch_size
, &load_result
, thr_act
, map
);
556 if (lret
!= LOAD_SUCCESS
) {
557 error
= load_return_to_errno(lret
);
561 /* load_machfile() maps the vnode */
565 * deal with set[ug]id.
567 p
->p_flag
&= ~P_SUGID
;
568 if (((origvattr
.va_mode
& VSUID
) != 0 &&
569 p
->p_ucred
->cr_uid
!= origvattr
.va_uid
)
570 || (origvattr
.va_mode
& VSGID
) != 0 &&
571 p
->p_ucred
->cr_gid
!= origvattr
.va_gid
) {
572 p
->p_ucred
= crcopy(cred
);
575 * If process is being ktraced, turn off - unless
578 if (p
->p_tracep
&& !(p
->p_traceflag
& KTRFAC_ROOT
)) {
579 struct vnode
*tvp
= p
->p_tracep
;
585 if (origvattr
.va_mode
& VSUID
)
586 p
->p_ucred
->cr_uid
= origvattr
.va_uid
;
587 if (origvattr
.va_mode
& VSGID
)
588 p
->p_ucred
->cr_gid
= origvattr
.va_gid
;
590 set_security_token(p
);
591 p
->p_flag
|= P_SUGID
;
593 /* Radar 2261856; setuid security hole fix */
594 /* Patch from OpenBSD: A. Ramesh */
596 * XXX For setuid processes, attempt to ensure that
597 * stdin, stdout, and stderr are already allocated.
598 * We do not want userland to accidentally allocate
599 * descriptors in this range which has implied meaning
602 for (i
= 0; i
< 3; i
++) {
603 extern struct fileops vnops
;
604 struct nameidata nd1
;
608 if (p
->p_fd
->fd_ofiles
[i
] == NULL
) {
609 if ((error
= falloc(p
, &fp
, &indx
)) != 0)
611 NDINIT(&nd1
, LOOKUP
, FOLLOW
, UIO_SYSSPACE
,
613 if ((error
= vn_open(&nd1
, FREAD
, 0)) != 0) {
615 p
->p_fd
->fd_ofiles
[indx
] = NULL
;
619 fp
->f_type
= DTYPE_VNODE
;
621 fp
->f_data
= (caddr_t
)nd1
.ni_vp
;
622 VOP_UNLOCK(nd1
.ni_vp
, 0, p
);
626 p
->p_cred
->p_svuid
= p
->p_ucred
->cr_uid
;
627 p
->p_cred
->p_svgid
= p
->p_ucred
->cr_gid
;
629 if (!vfexec
&& (p
->p_flag
& P_TRACED
))
635 VOP_LOCK(vp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
639 if (load_result
.unixproc
&&
640 create_unix_stack(get_task_map(task
),
641 load_result
.user_stack
, load_result
.customstack
, p
)) {
642 error
= load_return_to_errno(LOAD_NOSPACE
);
647 uthread
->uu_ar0
= (void *)get_user_regs(thr_act
);
651 * Copy back arglist if necessary.
657 old_map
= vm_map_switch(get_task_map(task
));
659 if (load_result
.unixproc
) {
662 ucp
= ucp
- nc
- NBPW
; /* begining of the STRING AREA */
665 * Support for new app package launching for Mac OS X allocates
666 * the "path" at the begining of the execargs buffer.
667 * copy it just before the string area.
669 savedpathlen
= (savedpathlen
+ NBPW
-1) & ~(NBPW
-1);
671 pathptr
= ucp
- savedpathlen
;
672 error
= copyoutstr(savedpath
, (caddr_t
)pathptr
,
673 (unsigned)savedpathlen
, &len
);
676 vm_map_switch(old_map
);
680 /* Save a NULL pointer below it */
681 (void) suword((caddr_t
)(pathptr
- NBPW
), 0);
683 /* Save the pointer to "path" just below it */
684 (void) suword((caddr_t
)(pathptr
- 2*NBPW
), pathptr
);
687 * na includes arg[] and env[].
688 * NBPW for 2 NULL one each ofter arg[argc -1] and env[n]
690 * skip over saved path, NBPW for pointer to path,
691 * and NBPW for the NULL after pointer to path.
693 ap
= ucp
- na
*NBPW
- 3*NBPW
- savedpathlen
- 2*NBPW
;
695 thread_setuserstack(thr_act
, ap
); /* Set the stack */
697 uthread
->uu_ar0
[SP
] = ap
;
699 (void) suword((caddr_t
)ap
, na
-ne
); /* argc */
703 cp
= (char *) execargsp
;
704 cc
= NCARGS
- savedpathlen
- 2*NBPW
;
705 ps
.ps_argvstr
= (char *)ucp
; /* first argv string */
706 ps
.ps_nargvstr
= na
- ne
; /* argc */
710 (void) suword((caddr_t
)ap
, 0);
712 ps
.ps_envstr
= (char *)ucp
;
717 (void) suword((caddr_t
)ap
, ucp
);
719 error
= copyoutstr(cp
, (caddr_t
)ucp
,
725 } while (error
== ENAMETOOLONG
);
727 break; /* bad stack - user's problem */
729 (void) suword((caddr_t
)ap
, 0);
732 if (load_result
.dynlinker
) {
734 ap
= thread_adjuserstack(thr_act
, -4); /* Adjust the stack */
736 ap
= uthread
->uu_ar0
[SP
] -= 4;
738 (void) suword((caddr_t
)ap
, load_result
.mach_header
);
742 vm_map_switch(old_map
);
745 thread_setentrypoint(thr_act
, load_result
.entry_point
); /* Set the entry point */
747 uthread
->uu_ar0
[PC
] = load_result
.entry_point
;
749 #error architecture not implemented!
756 * Reset signal state.
758 execsigs(p
, thr_act
);
761 * Close file descriptors
762 * which specify close-on-exec.
765 /* FIXME: Till vmspace inherit is fixed: */
766 if (!vfexec
&& p
->vm_shm
)
768 /* Clean up the semaphores */
772 * Remember file name for accounting.
774 p
->p_acflag
&= ~AFORK
;
775 if (nd
.ni_cnd
.cn_namelen
> MAXCOMLEN
)
776 nd
.ni_cnd
.cn_namelen
= MAXCOMLEN
;
777 bcopy((caddr_t
)nd
.ni_cnd
.cn_nameptr
, (caddr_t
)p
->p_comm
,
778 (unsigned)nd
.ni_cnd
.cn_namelen
);
779 p
->p_comm
[nd
.ni_cnd
.cn_namelen
] = '\0';
782 /* This is for kdebug */
783 long dbg_arg1
, dbg_arg2
, dbg_arg3
, dbg_arg4
;
785 /* Collect the pathname for tracing */
786 kdbg_trace_string(p
, &dbg_arg1
, &dbg_arg2
, &dbg_arg3
, &dbg_arg4
);
789 KERNEL_DEBUG_CONSTANT1((TRACEDBG_CODE(DBG_TRACE_STRING
, 2)) | DBG_FUNC_NONE
,
790 dbg_arg1
, dbg_arg2
, dbg_arg3
, dbg_arg4
, getshuttle_thread(thr_act
));
792 KERNEL_DEBUG_CONSTANT((TRACEDBG_CODE(DBG_TRACE_STRING
, 2)) | DBG_FUNC_NONE
,
793 dbg_arg1
, dbg_arg2
, dbg_arg3
, dbg_arg4
, 0);
797 * mark as execed, wakeup the process that vforked (if any) and tell
798 * it that it now has it's own resources back
801 if (p
->p_pptr
&& (p
->p_flag
& P_PPWAIT
)) {
802 p
->p_flag
&= ~P_PPWAIT
;
803 wakeup((caddr_t
)p
->p_pptr
);
806 if (vfexec
&& (p
->p_flag
& P_TRACED
)) {
807 psignal_vfork(p
, new_task
, thr_act
, SIGTRAP
);
812 task_deallocate(new_task
);
813 act_deallocate(thr_act
);
818 FREE_ZONE(nd
.ni_cnd
.cn_pnbuf
, nd
.ni_cnd
.cn_pnlen
, M_NAMEI
);
823 execargs_free(execargs
);
824 if (!error
&& vfexec
) {
825 vfork_return(current_act(), p
->p_pptr
, p
, retval
);
826 (void) thread_resume(thr_act
);
833 #define unix_stack_size(p) (p->p_rlimit[RLIMIT_STACK].rlim_cur)
836 create_unix_stack(map
, user_stack
, customstack
, p
)
838 vm_offset_t user_stack
;
845 p
->user_stack
= user_stack
;
847 size
= round_page(unix_stack_size(p
));
848 addr
= trunc_page(user_stack
- size
);
849 return (vm_allocate(map
,&addr
, size
, FALSE
));
851 return(KERN_SUCCESS
);
854 #include <sys/reboot.h>
856 char init_program_name
[128] = "/sbin/mach_init\0";
858 char init_args
[128] = "";
860 struct execve_args init_exec_args
;
861 int init_attempts
= 0;
868 vm_offset_t init_addr
;
872 register_t retval
[2];
877 /* init_args are copied in string form directly from bootstrap */
880 if (boothowto
& RB_INITNAME
) {
881 printf("init program? ");
883 gets(init_program_name
, init_program_name
);
887 if (error
&& ((boothowto
& RB_INITNAME
) == 0) &&
888 (init_attempts
== 1)) {
889 static char other_init
[] = "/etc/mach_init";
890 printf("Load of %s, errno %d, trying %s\n",
891 init_program_name
, error
, other_init
);
893 bcopy(other_init
, init_program_name
,
900 printf("Load of %s failed, errno %d\n",
901 init_program_name
, error
);
903 boothowto
|= RB_INITNAME
;
908 * Copy out program name.
911 init_addr
= VM_MIN_ADDRESS
;
912 (void) vm_allocate(current_map(), &init_addr
,
916 (void) copyout((caddr_t
) init_program_name
,
917 (caddr_t
) (init_addr
),
918 (unsigned) sizeof(init_program_name
)+1);
920 argv
[0] = (char *) init_addr
;
921 init_addr
+= sizeof(init_program_name
);
922 init_addr
= (vm_offset_t
)ROUND_PTR(char, init_addr
);
925 * Put out first (and only) argument, similarly.
926 * Assumes everything fits in a page as allocated
930 (void) copyout((caddr_t
) init_args
,
931 (caddr_t
) (init_addr
),
932 (unsigned) sizeof(init_args
));
934 argv
[1] = (char *) init_addr
;
935 init_addr
+= sizeof(init_args
);
936 init_addr
= (vm_offset_t
)ROUND_PTR(char, init_addr
);
939 * Null-end the argument list
942 argv
[2] = (char *) 0;
945 * Copy out the argument list.
948 (void) copyout((caddr_t
) argv
,
949 (caddr_t
) (init_addr
),
950 (unsigned) sizeof(argv
));
953 * Set up argument block for fake call to execve.
956 init_exec_args
.fname
= argv
[0];
957 init_exec_args
.argp
= (char **) init_addr
;
958 init_exec_args
.envp
= 0;
960 /* So that mach_init task
961 * is set with uid,gid 0 token
963 set_security_token(p
);
965 error
= execve(p
,&init_exec_args
,retval
);
970 * Convert a load_return_t to an errno.
973 load_return_to_errno(load_return_t lrtn
)
996 * exec_check_access()
999 check_exec_access(p
, vp
, vap
)
1007 if (error
= VOP_ACCESS(vp
, VEXEC
, p
->p_ucred
, p
))
1010 if (flag
& P_TRACED
) {
1011 if (error
= VOP_ACCESS(vp
, VREAD
, p
->p_ucred
, p
))
1014 if (vp
->v_type
!= VREG
||
1015 (vap
->va_mode
& (S_IXUSR
| S_IXGRP
| S_IXOTH
)) == 0)
1020 #include <mach/mach_types.h>
1021 #include <mach/vm_prot.h>
1022 #include <mach/semaphore.h>
1023 #include <mach/sync_policy.h>
1024 #include <kern/clock.h>
1025 #include <mach/kern_return.h>
1027 extern semaphore_t execve_semaphore
;
1030 execargs_alloc(addrp
)
1035 kret
= semaphore_wait(execve_semaphore
);
1036 if (kret
!= KERN_SUCCESS
)
1040 case KERN_INVALID_ADDRESS
:
1041 case KERN_PROTECTION_FAILURE
:
1044 case KERN_OPERATION_TIMED_OUT
:
1048 kret
= kmem_alloc_pageable(bsd_pageable_map
, addrp
, NCARGS
);
1049 if (kret
!= KERN_SUCCESS
)
1061 kmem_free(bsd_pageable_map
, addr
, NCARGS
);
1063 kret
= semaphore_signal(execve_semaphore
);
1065 case KERN_INVALID_ADDRESS
:
1066 case KERN_PROTECTION_FAILURE
:
1069 case KERN_OPERATION_TIMED_OUT
: