]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/kern_exec.c
1db47973a1063ca3a72e037f642a77b746d9844e
[apple/xnu.git] / bsd / kern / kern_exec.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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.
11 *
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
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
23 /*
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.
28 */
29
30 #include <cputypes.h>
31
32 /*-
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.
40 *
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
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.
56 *
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
67 * SUCH DAMAGE.
68 *
69 * from: @(#)kern_exec.c 8.1 (Berkeley) 6/10/93
70 */
71 #include <machine/reg.h>
72
73 #include <sys/param.h>
74 #include <sys/systm.h>
75 #include <sys/filedesc.h>
76 #include <sys/kernel.h>
77 #include <sys/proc.h>
78 #include <sys/user.h>
79 #include <sys/buf.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>
85 #include <sys/file.h>
86 #include <sys/stat.h>
87 #include <sys/uio.h>
88 #include <sys/acct.h>
89 #include <sys/exec.h>
90 #include <sys/kdebug.h>
91 #include <sys/signal.h>
92
93 #include <mach/vm_param.h>
94
95 #include <vm/vm_map.h>
96 #include <vm/vm_kern.h>
97
98 #include <kern/thread.h>
99 #include <kern/task.h>
100
101 #include <kern/ast.h>
102 #include <kern/mach_loader.h>
103 #include <mach-o/fat.h>
104 #include <mach-o/loader.h>
105 #include <machine/vmparam.h>
106
107 extern vm_map_t bsd_pageable_map;
108
109 #define ROUND_PTR(type, addr) \
110 (type *)( ( (unsigned)(addr) + 16 - 1) \
111 & ~(16 - 1) )
112
113 static int load_return_to_errno(load_return_t lrtn);
114 int execve(struct proc *p, struct execve_args *uap, register_t *retval);
115
116 int
117 execv(p, args, retval)
118 struct proc *p;
119 void *args;
120 int *retval;
121 {
122 ((struct execve_args *)args)->envp = NULL;
123 return (execve(p, args, retval));
124 }
125
126 /* ARGSUSED */
127 int
128 execve(p, uap, retval)
129 register struct proc *p;
130 register struct execve_args *uap;
131 register_t *retval;
132 {
133 register struct ucred *cred = p->p_ucred;
134 register struct filedesc *fdp = p->p_fd;
135 register nc;
136 register char *cp;
137 int na, ne, ucp, ap, cc;
138 unsigned len;
139 int indir;
140 char *sharg;
141 char *execnamep;
142 struct vnode *vp;
143 struct vattr vattr;
144 struct vattr origvattr;
145 vm_offset_t execargs;
146 struct nameidata nd;
147 struct ps_strings ps;
148 #define SHSIZE 512
149 char cfarg[SHSIZE];
150 boolean_t is_fat;
151 kern_return_t ret;
152 struct mach_header *mach_header;
153 struct fat_header *fat_header;
154 struct fat_arch fat_arch;
155 load_return_t lret;
156 load_result_t load_result;
157 struct uthread *uthread;
158 int i;
159 union {
160 /* #! and name of interpreter */
161 char ex_shell[SHSIZE];
162 /* Mach-O executable */
163 struct mach_header mach_header;
164 /* Fat executable */
165 struct fat_header fat_header;
166 char pad[512];
167 } exdata;
168 int resid, error;
169 char *savedpath;
170 int savedpathlen = 0;
171 vm_offset_t *execargsp;
172 char *cpnospace;
173 task_t tsk;
174 int numthreads;
175
176 tsk = current_task();
177
178
179 if(tsk != kernel_task) {
180 numthreads = get_task_numacts(tsk);
181 if (numthreads <= 0 )
182 return(EINVAL);
183 if (numthreads > 1) {
184 return(EOPNOTSUPP);
185 }
186 }
187
188 ret = kmem_alloc_pageable(bsd_pageable_map, &execargs, NCARGS);
189 if (ret != KERN_SUCCESS)
190 return(ENOMEM);
191
192 uthread = get_bsdthread_info(current_act());
193
194 savedpath = execargs;
195
196 /*
197 * To support new app package launching for Mac OS X, the dyld
198 * needs the first argument to execve() stored on the user stack.
199 * Copyin the "path" at the begining of the "execargs" buffer
200 * allocated above.
201 *
202 * We have to do this before namei() because in case of
203 * symbolic links, namei() would overwrite the original "path".
204 * In case the last symbolic link resolved was a relative pathname
205 * we would loose the original "path", which could be an
206 * absolute pathname. This might be unacceptable for dyld.
207 */
208 /* XXX We could optimize to avoid copyinstr in the namei() */
209
210 error = copyinstr(uap->fname, savedpath, MAXPATHLEN, &savedpathlen);
211 if (error)
212 return (error);
213 /*
214 * copyinstr will put in savedpathlen, the count of
215 * characters (including NULL) in the path.
216 */
217
218 /* Save the name aside for future use */
219 execargsp = (vm_offset_t *)((char *)(execargs) + savedpathlen);
220
221 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | SAVENAME,
222 UIO_USERSPACE, uap->fname, p);
223 if ((error = namei(&nd)))
224 goto bad1;
225 vp = nd.ni_vp;
226 VOP_LEASE(vp, p, p->p_ucred, LEASE_READ);
227
228 if ((error = VOP_GETATTR(vp, &origvattr, p->p_ucred, p)))
229 goto bad;
230
231 /* Check mount point */
232 if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
233 error = EACCES;
234 goto bad;
235 }
236
237 indir = 0;
238 if ((vp->v_mount->mnt_flag & MNT_NOSUID) || (p->p_flag & P_TRACED))
239 origvattr.va_mode &= ~(VSUID | VSGID);
240
241 *(&vattr) = *(&origvattr);
242
243 again:
244 error = check_exec_access(p, vp, &vattr);
245 if (error)
246 goto bad;
247
248 /*
249 * Read in first few bytes of file for segment sizes, magic number:
250 * 407 = plain executable
251 * 410 = RO text
252 * 413 = demand paged RO text
253 * Also an ASCII line beginning with #! is
254 * the file name of a ``shell'' and arguments may be prepended
255 * to the argument list if given here.
256 *
257 * SHELL NAMES ARE LIMITED IN LENGTH.
258 *
259 * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM
260 * THE ASCII LINE.
261 */
262
263 exdata.ex_shell[0] = '\0'; /* for zero length files */
264
265 error = vn_rdwr(UIO_READ, vp, (caddr_t)&exdata, sizeof (exdata), 0,
266 UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
267
268 if (error)
269 goto bad;
270
271 #ifndef lint
272 if (resid > sizeof(exdata) - min(sizeof(exdata.mach_header),
273 sizeof(exdata.fat_header))
274 && exdata.ex_shell[0] != '#') {
275 error = ENOEXEC;
276 goto bad;
277 }
278 #endif /* lint */
279 mach_header = &exdata.mach_header;
280 fat_header = &exdata.fat_header;
281 if (mach_header->magic == MH_MAGIC)
282 is_fat = FALSE;
283 else if (fat_header->magic == FAT_MAGIC ||
284 fat_header->magic == FAT_CIGAM)
285 is_fat = TRUE;
286 else if (mach_header->magic == MH_CIGAM) {
287 error = EBADARCH;
288 goto bad;
289 } else {
290 if (exdata.ex_shell[0] != '#' ||
291 exdata.ex_shell[1] != '!' ||
292 indir) {
293 error = ENOEXEC;
294 goto bad;
295 }
296 cp = &exdata.ex_shell[2]; /* skip "#!" */
297 while (cp < &exdata.ex_shell[SHSIZE]) {
298 if (*cp == '\t')
299 *cp = ' ';
300 else if (*cp == '\n') {
301 *cp = '\0';
302 break;
303 }
304 cp++;
305 }
306 if (*cp != '\0') {
307 error = ENOEXEC;
308 goto bad;
309 }
310 cp = &exdata.ex_shell[2];
311 while (*cp == ' ')
312 cp++;
313 execnamep = cp;
314 while (*cp && *cp != ' ')
315 cp++;
316 cfarg[0] = '\0';
317 cpnospace = cp;
318 if (*cp) {
319 *cp++ = '\0';
320 while (*cp == ' ')
321 cp++;
322 if (*cp)
323 bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE);
324 }
325
326 /*
327 * Support for new app package launching for Mac OS X.
328 * We are about to retry the execve() by changing the path to the
329 * interpreter name. Need to re-initialize the savedpath and
330 * savedpathlen. +1 for NULL.
331 */
332 savedpathlen = (cpnospace - execnamep + 1);
333 error = copystr(execnamep, savedpath, savedpathlen, &savedpathlen);
334 if (error)
335 goto bad;
336
337 /* Save the name aside for future use */
338 execargsp = (vm_offset_t *)((char *)(execargs) + savedpathlen);
339
340 indir = 1;
341 vput(vp);
342 nd.ni_cnd.cn_nameiop = LOOKUP;
343 nd.ni_cnd.cn_flags = (nd.ni_cnd.cn_flags & HASBUF) |
344 (FOLLOW | LOCKLEAF | SAVENAME);
345 nd.ni_segflg = UIO_SYSSPACE;
346 nd.ni_dirp = execnamep;
347 if ((error = namei(&nd)))
348 goto bad1;
349 vp = nd.ni_vp;
350 VOP_LEASE(vp, p, cred, LEASE_READ);
351 if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)))
352 goto bad;
353 goto again;
354 }
355
356 /*
357 * Collect arguments on "file" in swap space.
358 */
359 na = 0;
360 ne = 0;
361 nc = 0;
362 cc = 0;
363 /*
364 * Support for new app package launching for Mac OS X allocates
365 * the "path" at the begining.
366 * execargs get allocated after that
367 */
368 cp = (char *) execargsp; /* running pointer for copy */
369 /*
370 * size of execargs less sizeof "path",
371 * a pointer to "path" and a NULL poiter
372 */
373 cc = NCARGS - savedpathlen - 2*NBPW;
374 /*
375 * Copy arguments into file in argdev area.
376 */
377 if (uap->argp) for (;;) {
378 ap = NULL;
379 sharg = NULL;
380 if (indir && na == 0) {
381 sharg = nd.ni_cnd.cn_nameptr;
382 ap = (int)sharg;
383 uap->argp++; /* ignore argv[0] */
384 } else if (indir && (na == 1 && cfarg[0])) {
385 sharg = cfarg;
386 ap = (int)sharg;
387 } else if (indir && (na == 1 || (na == 2 && cfarg[0])))
388 ap = (int)uap->fname;
389 else if (uap->argp) {
390 ap = fuword((caddr_t)uap->argp);
391 uap->argp++;
392 }
393 if (ap == NULL && uap->envp) {
394 uap->argp = NULL;
395 if ((ap = fuword((caddr_t)uap->envp)) != NULL)
396 uap->envp++, ne++;
397 }
398 if (ap == NULL)
399 break;
400 na++;
401 if (ap == -1) {
402 error = EFAULT;
403 break;
404 }
405 do {
406 if (nc >= (NCARGS - savedpathlen - 2*NBPW -1)) {
407 error = E2BIG;
408 break;
409 }
410 if (sharg) {
411 error = copystr(sharg, cp, (unsigned)cc, &len);
412 sharg += len;
413 } else {
414 error = copyinstr((caddr_t)ap, cp, (unsigned)cc,
415 &len);
416 ap += len;
417 }
418 cp += len;
419 nc += len;
420 cc -= len;
421 } while (error == ENAMETOOLONG);
422 if (error) {
423 goto bad;
424 }
425 }
426 nc = (nc + NBPW-1) & ~(NBPW-1);
427
428 /*
429 * If we have a fat file, find "our" executable.
430 */
431 if (is_fat) {
432 /*
433 * Look up our architecture in the fat file.
434 */
435 lret = fatfile_getarch(vp, (vm_offset_t)fat_header, &fat_arch);
436 if (lret != LOAD_SUCCESS) {
437 error = load_return_to_errno(lret);
438 goto bad;
439 }
440 /* Read the Mach-O header out of it */
441 error = vn_rdwr(UIO_READ, vp, (caddr_t)&exdata.mach_header,
442 sizeof (exdata.mach_header),
443 fat_arch.offset,
444 UIO_SYSSPACE, (IO_UNIT|IO_NODELOCKED), cred, &resid, p);
445
446 if (error) {
447 goto bad;
448 }
449
450 /* Did we read a complete header? */
451 if (resid) {
452 error = EBADEXEC;
453 goto bad;
454 }
455
456 /* Is what we found a Mach-O executable */
457 if (mach_header->magic != MH_MAGIC) {
458 error = ENOEXEC;
459 goto bad;
460 }
461
462 /*
463 * Load the Mach-O file.
464 */
465 VOP_UNLOCK(vp, 0, p);
466 lret = load_machfile(vp, mach_header, fat_arch.offset,
467 fat_arch.size, &load_result);
468 } else {
469 /*
470 * Load the Mach-O file.
471 */
472 VOP_UNLOCK(vp, 0, p);
473 lret = load_machfile(vp, mach_header, 0,
474 (u_long)vattr.va_size, &load_result);
475 }
476
477 if (lret != LOAD_SUCCESS) {
478 error = load_return_to_errno(lret);
479 goto bad;
480 }
481
482 /* load_machfile() maps the vnode */
483 ubc_map(vp);
484
485 /*
486 * deal with set[ug]id.
487 */
488 p->p_flag &= ~P_SUGID;
489 if (((origvattr.va_mode & VSUID) != 0 &&
490 p->p_ucred->cr_uid != origvattr.va_uid)
491 || (origvattr.va_mode & VSGID) != 0 &&
492 p->p_ucred->cr_gid != origvattr.va_gid) {
493 p->p_ucred = crcopy(cred);
494 #if KTRACE
495 /*
496 * If process is being ktraced, turn off - unless
497 * root set it.
498 */
499 if (p->p_tracep && !(p->p_traceflag & KTRFAC_ROOT)) {
500 vrele(p->p_tracep);
501 p->p_tracep = NULL;
502 p->p_traceflag = 0;
503 }
504 #endif
505 if (origvattr.va_mode & VSUID)
506 p->p_ucred->cr_uid = origvattr.va_uid;
507 if (origvattr.va_mode & VSGID)
508 p->p_ucred->cr_gid = origvattr.va_gid;
509
510 set_security_token(p);
511 p->p_flag |= P_SUGID;
512
513 /* Radar 2261856; setuid security hole fix */
514 /* Patch from OpenBSD: A. Ramesh */
515 /*
516 * XXX For setuid processes, attempt to ensure that
517 * stdin, stdout, and stderr are already allocated.
518 * We do not want userland to accidentally allocate
519 * descriptors in this range which has implied meaning
520 * to libc.
521 */
522 for (i = 0; i < 3; i++) {
523 extern struct fileops vnops;
524 struct nameidata nd1;
525 struct file *fp;
526 int indx;
527
528 if (p->p_fd->fd_ofiles[i] == NULL) {
529 if ((error = falloc(p, &fp, &indx)) != 0)
530 continue;
531 NDINIT(&nd1, LOOKUP, FOLLOW, UIO_SYSSPACE,
532 "/dev/null", p);
533 if ((error = vn_open(&nd1, FREAD, 0)) != 0) {
534 ffree(fp);
535 p->p_fd->fd_ofiles[indx] = NULL;
536 break;
537 }
538 fp->f_flag = FREAD;
539 fp->f_type = DTYPE_VNODE;
540 fp->f_ops = &vnops;
541 fp->f_data = (caddr_t)nd1.ni_vp;
542 VOP_UNLOCK(nd1.ni_vp, 0, p);
543 }
544 }
545 }
546 p->p_cred->p_svuid = p->p_ucred->cr_uid;
547 p->p_cred->p_svgid = p->p_ucred->cr_gid;
548
549 if (p->p_flag & P_TRACED) {
550 psignal(p, SIGTRAP);
551 #ifdef BSD_USE_APC
552 thread_apc_set(current_act(), bsd_ast);
553 #else
554 ast_on(AST_BSD);
555 #endif
556 }
557
558 if (error) {
559 goto bad;
560 }
561 VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY, p);
562 vput(vp);
563 vp = NULL;
564
565 if (load_result.unixproc &&
566 create_unix_stack(current_map(),
567 load_result.user_stack, p)) {
568 error = load_return_to_errno(LOAD_NOSPACE);
569 goto bad;
570 }
571
572 /*
573 * Copy back arglist if necessary.
574 */
575
576 ucp = p->user_stack;
577 if (load_result.unixproc) {
578 int pathptr;
579
580 ucp = ucp - nc - NBPW; /* begining of the STRING AREA */
581
582 /*
583 * Support for new app package launching for Mac OS X allocates
584 * the "path" at the begining of the execargs buffer.
585 * copy it just before the string area.
586 */
587 savedpathlen = (savedpathlen + NBPW-1) & ~(NBPW-1);
588 len = 0;
589 pathptr = ucp - savedpathlen;
590 error = copyoutstr(savedpath, (caddr_t)pathptr,
591 (unsigned)savedpathlen, &len);
592 if (error)
593 goto bad;
594
595 /* Save a NULL pointer below it */
596 (void) suword((caddr_t)(pathptr - NBPW), 0);
597
598 /* Save the pointer to "path" just below it */
599 (void) suword((caddr_t)(pathptr - 2*NBPW), pathptr);
600
601 /*
602 * na includes arg[] and env[].
603 * NBPW for 2 NULL one each ofter arg[argc -1] and env[n]
604 * NBPW for argc
605 * skip over saved path, NBPW for pointer to path,
606 * and NBPW for the NULL after pointer to path.
607 */
608 ap = ucp - na*NBPW - 3*NBPW - savedpathlen - 2*NBPW;
609 uthread->uu_ar0[SP] = ap;
610 (void) suword((caddr_t)ap, na-ne); /* argc */
611 nc = 0;
612 cc = 0;
613
614 cp = (char *) execargsp;
615 cc = NCARGS - savedpathlen - 2*NBPW;
616 ps.ps_argvstr = (char *)ucp; /* first argv string */
617 ps.ps_nargvstr = na - ne; /* argc */
618 for (;;) {
619 ap += NBPW;
620 if (na == ne) {
621 (void) suword((caddr_t)ap, 0);
622 ap += NBPW;
623 ps.ps_envstr = (char *)ucp;
624 ps.ps_nenvstr = ne;
625 }
626 if (--na < 0)
627 break;
628 (void) suword((caddr_t)ap, ucp);
629 do {
630 error = copyoutstr(cp, (caddr_t)ucp,
631 (unsigned)cc, &len);
632 ucp += len;
633 cp += len;
634 nc += len;
635 cc -= len;
636 } while (error == ENAMETOOLONG);
637 if (error == EFAULT)
638 break; /* bad stack - user's problem */
639 }
640 (void) suword((caddr_t)ap, 0);
641 }
642
643 if (load_result.dynlinker) {
644 ap = uthread->uu_ar0[SP] -= 4;
645 (void) suword((caddr_t)ap, load_result.mach_header);
646 }
647
648 #if defined(i386) || defined(ppc)
649 uthread->uu_ar0[PC] = load_result.entry_point;
650 #else
651 #error architecture not implemented!
652 #endif
653
654 /* Stop profiling */
655 stopprofclock(p);
656
657 /*
658 * Reset signal state.
659 */
660 execsigs(p);
661
662 /*
663 * Close file descriptors
664 * which specify close-on-exec.
665 */
666 fdexec(p);
667 /* FIXME: Till vmspace inherit is fixed: */
668 if (p->vm_shm)
669 shmexit(p);
670
671 /*
672 * Remember file name for accounting.
673 */
674 p->p_acflag &= ~AFORK;
675 if (nd.ni_cnd.cn_namelen > MAXCOMLEN)
676 nd.ni_cnd.cn_namelen = MAXCOMLEN;
677 bcopy((caddr_t)nd.ni_cnd.cn_nameptr, (caddr_t)p->p_comm,
678 (unsigned)nd.ni_cnd.cn_namelen);
679 p->p_comm[nd.ni_cnd.cn_namelen] = '\0';
680
681 {
682 /* This is for kdebug */
683 long dbg_arg1, dbg_arg2, dbg_arg3, dbg_arg4;
684
685 /* Collect the pathname for tracing */
686 kdbg_trace_string(p, &dbg_arg1, &dbg_arg2, &dbg_arg3, &dbg_arg4);
687 KERNEL_DEBUG_CONSTANT((TRACEDBG_CODE(DBG_TRACE_STRING, 2)) | DBG_FUNC_NONE,
688 dbg_arg1, dbg_arg2, dbg_arg3, dbg_arg4, 0);
689 }
690
691 /*
692 * mark as execed, wakeup the process that vforked (if any) and tell
693 * it that it now has it's own resources back
694 */
695 p->p_flag |= P_EXEC;
696 if (p->p_pptr && (p->p_flag & P_PPWAIT)) {
697 p->p_flag &= ~P_PPWAIT;
698 wakeup((caddr_t)p->p_pptr);
699 }
700
701 bad:
702 FREE_ZONE(nd.ni_cnd.cn_pnbuf, nd.ni_cnd.cn_pnlen, M_NAMEI);
703 if (vp)
704 vput(vp);
705 bad1:
706 #if FIXME /* [ */
707 if (execargs)
708 kmem_free_wakeup(bsd_pageable_map, execargs, NCARGS);
709 #else /* FIXME ][ */
710 if (execargs)
711 kmem_free(bsd_pageable_map, execargs, NCARGS);
712 #endif /* FIXME ] */
713 return(error);
714 }
715
716
717 #define unix_stack_size(p) (p->p_rlimit[RLIMIT_STACK].rlim_cur)
718
719 kern_return_t
720 create_unix_stack(map, user_stack, p)
721 vm_map_t map;
722 vm_offset_t user_stack;
723 struct proc *p;
724 {
725 vm_size_t size;
726 vm_offset_t addr;
727
728 p->user_stack = user_stack;
729 size = round_page(unix_stack_size(p));
730 #if STACK_GROWTH_UP
731 /* stack always points to first address for stacks */
732 addr = user_stack;
733 #else STACK_GROWTH_UP
734 addr = trunc_page(user_stack - size);
735 #endif /* STACK_GROWTH_UP */
736 return (vm_allocate(map,&addr, size, FALSE));
737 }
738
739 #include <sys/reboot.h>
740
741 char init_program_name[128] = "/sbin/mach_init\0";
742
743 char init_args[128] = "";
744
745 struct execve_args init_exec_args;
746 int init_attempts = 0;
747
748
749 void
750 load_init_program(p)
751 struct proc *p;
752 {
753 vm_offset_t init_addr;
754 int *old_ap;
755 char *argv[3];
756 int error;
757 register_t retval[2];
758 struct uthread * ut;
759
760 unix_master();
761
762 error = 0;
763
764 /* init_args are copied in string form directly from bootstrap */
765
766 do {
767 if (boothowto & RB_INITNAME) {
768 printf("init program? ");
769 #if FIXME /* [ */
770 gets(init_program_name, init_program_name);
771 #endif /* FIXME ] */
772 }
773
774 if (error && ((boothowto & RB_INITNAME) == 0) &&
775 (init_attempts == 1)) {
776 static char other_init[] = "/etc/mach_init";
777 printf("Load of %s, errno %d, trying %s\n",
778 init_program_name, error, other_init);
779 error = 0;
780 bcopy(other_init, init_program_name,
781 sizeof(other_init));
782 }
783
784 init_attempts++;
785
786 if (error) {
787 printf("Load of %s failed, errno %d\n",
788 init_program_name, error);
789 error = 0;
790 boothowto |= RB_INITNAME;
791 continue;
792 }
793
794 /*
795 * Copy out program name.
796 */
797
798 init_addr = VM_MIN_ADDRESS;
799 (void) vm_allocate(current_map(), &init_addr,
800 PAGE_SIZE, TRUE);
801 if (init_addr == 0)
802 init_addr++;
803 (void) copyout((caddr_t) init_program_name,
804 (caddr_t) (init_addr),
805 (unsigned) sizeof(init_program_name)+1);
806
807 argv[0] = (char *) init_addr;
808 init_addr += sizeof(init_program_name);
809 init_addr = (vm_offset_t)ROUND_PTR(char, init_addr);
810
811 /*
812 * Put out first (and only) argument, similarly.
813 * Assumes everything fits in a page as allocated
814 * above.
815 */
816
817 (void) copyout((caddr_t) init_args,
818 (caddr_t) (init_addr),
819 (unsigned) sizeof(init_args));
820
821 argv[1] = (char *) init_addr;
822 init_addr += sizeof(init_args);
823 init_addr = (vm_offset_t)ROUND_PTR(char, init_addr);
824
825 /*
826 * Null-end the argument list
827 */
828
829 argv[2] = (char *) 0;
830
831 /*
832 * Copy out the argument list.
833 */
834
835 (void) copyout((caddr_t) argv,
836 (caddr_t) (init_addr),
837 (unsigned) sizeof(argv));
838
839 /*
840 * Set up argument block for fake call to execve.
841 */
842
843 init_exec_args.fname = argv[0];
844 init_exec_args.argp = (char **) init_addr;
845 init_exec_args.envp = 0;
846
847 /* So that mach_init task
848 * is set with uid,gid 0 token
849 */
850 set_security_token(p);
851
852 error = execve(p,&init_exec_args,retval);
853 } while (error);
854
855 unix_release();
856 }
857
858 /*
859 * Convert a load_return_t to an errno.
860 */
861 static int
862 load_return_to_errno(load_return_t lrtn)
863 {
864 switch (lrtn) {
865 case LOAD_SUCCESS:
866 return 0;
867 case LOAD_BADARCH:
868 return EBADARCH;
869 case LOAD_BADMACHO:
870 return EBADMACHO;
871 case LOAD_SHLIB:
872 return ESHLIBVERS;
873 case LOAD_NOSPACE:
874 return ENOMEM;
875 case LOAD_PROTECT:
876 return EACCES;
877 case LOAD_RESOURCE:
878 case LOAD_FAILURE:
879 default:
880 return EBADEXEC;
881 }
882 }
883
884 /*
885 * exec_check_access()
886 */
887 int
888 check_exec_access(p, vp, vap)
889 struct proc *p;
890 struct vnode *vp;
891 struct vattr *vap;
892 {
893 int flag;
894 int error;
895
896 if (error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p))
897 return (error);
898 flag = p->p_flag;
899 if (flag & P_TRACED) {
900 if (error = VOP_ACCESS(vp, VREAD, p->p_ucred, p))
901 return (error);
902 }
903 if (vp->v_type != VREG ||
904 (vap->va_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0)
905 return (EACCES);
906 return (0);
907 }
908