|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
26: /*
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.
31: */
32: /*
33: * HISTORY
34: * 11 Dec 1997 Umesh Vaishampayan ([email protected])
35: * Modified execve() to do the allocation for arguments before locking the inode. Cleaned up
36: * warnings.
37: *
38: * 20 Jun 1995 Mac Gillon (mgillon) at NeXT
39: * 4.4 based version
40: *
41: * 18 May 1992 ? at NeXT
42: * Expanded fat file support to handle little endian machines.
43: *
44: * 6-Dec-91 Peter King (king) at NeXT
45: * NeXT: Fat file support.
46: *
47: * 7-Nov-90 Gregg Kellogg (gk) at NeXT
48: * NeXT: reset signal interrupt bits on exec.
49: *
50: * 25-Sep-89 Morris Meyer (mmeyer) at NeXT
51: * NFS 4.0 Changes: Changed SPAGI to SPAGV. Removed #include dir.h.
52: *
53: * 24-Oct-88 Steve Stone (steve) at NeXT
54: * Added Attach trace support.
55: *
56: * 22-Jul-88 Avadis Tevanian, Jr. (avie) at NeXT
57: * Support for Mach-O files.
58: *
59: * 19-Apr-88 Avadis Tevanian, Jr. (avie) at NeXT
60: * Removed old history, purged lots of dead code.
61: */
62:
63: #include <cputypes.h>
64:
65: /*-
66: * Copyright (c) 1982, 1986, 1991, 1993
67: * The Regents of the University of California. All rights reserved.
68: * (c) UNIX System Laboratories, Inc.
69: * All or some portions of this file are derived from material licensed
70: * to the University of California by American Telephone and Telegraph
71: * Co. or Unix System Laboratories, Inc. and are reproduced herein with
72: * the permission of UNIX System Laboratories, Inc.
73: *
74: * Redistribution and use in source and binary forms, with or without
75: * modification, are permitted provided that the following conditions
76: * are met:
77: * 1. Redistributions of source code must retain the above copyright
78: * notice, this list of conditions and the following disclaimer.
79: * 2. Redistributions in binary form must reproduce the above copyright
80: * notice, this list of conditions and the following disclaimer in the
81: * documentation and/or other materials provided with the distribution.
82: * 3. All advertising materials mentioning features or use of this software
83: * must display the following acknowledgement:
84: * This product includes software developed by the University of
85: * California, Berkeley and its contributors.
86: * 4. Neither the name of the University nor the names of its contributors
87: * may be used to endorse or promote products derived from this software
88: * without specific prior written permission.
89: *
90: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
91: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
92: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
93: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
94: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
95: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
96: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
97: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
98: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
99: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
100: * SUCH DAMAGE.
101: *
102: * from: @(#)kern_exec.c 8.1 (Berkeley) 6/10/93
103: */
104: #include <mach_nbc.h>
105: #include <machine/reg.h>
106:
107: #include <sys/param.h>
108: #include <sys/systm.h>
109: #include <sys/filedesc.h>
110: #include <sys/kernel.h>
111: #include <sys/proc.h>
112: #include <sys/user.h>
113: #include <sys/buf.h>
114: #include <sys/socketvar.h>
115: #include <sys/malloc.h>
116: #include <sys/namei.h>
117: #include <sys/mount.h>
118: #include <sys/vnode.h>
119: #include <sys/file.h>
120: #include <sys/stat.h>
121: #include <sys/uio.h>
122: #include <sys/acct.h>
123: #include <sys/exec.h>
124: #include <mach/exception.h>
125:
126: #include <sys/signal.h>
127: #include <kern/task.h>
128: #include <kern/thread.h>
129:
130: #include <mach/vm_param.h>
131: #include <vm/vm_map.h>
132: #include <vm/vm_object.h>
133: #include <vm/vnode_pager.h>
134: #include <vm/vm_kern.h>
135: #include <vm/vm_user.h>
136: #include <kern/mapfs.h>
137: #include <kern/zalloc.h>
138:
139: #include <kern/parallel.h>
140: #include <kern/mach_loader.h>
141:
142: #include <mach-o/fat.h>
143: #include <mach-o/loader.h>
144:
145: #include <machine/vmparam.h>
146: #include <kernserv/c_utils.h>
147:
148: static int load_return_to_errno(load_return_t lrtn);
149: int execve(struct proc *p, struct execve_args *uap, register_t *retval);
150:
151: int
152: execv(p, args, retval)
153: struct proc *p;
154: void *args;
155: int *retval;
156: {
157: ((struct execve_args *)args)->envp = NULL;
158: return (execve(p, args, retval));
159: }
160:
161: /* ARGSUSED */
162: int
163: execve(p, uap, retval)
164: register struct proc *p;
165: register struct execve_args *uap;
166: register_t *retval;
167: {
168: register struct ucred *cred = p->p_ucred;
169: register struct filedesc *fdp = p->p_fd;
170: register nc;
171: register char *cp;
172: int na, ne, ucp, ap, cc;
173: unsigned len;
174: int indir;
175: char *sharg;
176: char *execnamep;
177: struct vnode *vp;
178: struct vattr vattr;
179: struct vattr origvattr;
180: vm_offset_t execargs;
181: struct nameidata nd;
182: struct ps_strings ps;
183: #define SHSIZE 512
184: char cfarg[SHSIZE];
185: boolean_t is_fat;
186: struct mach_header *mach_header;
187: struct fat_header *fat_header;
188: struct fat_arch fat_arch;
189: load_return_t lret;
190: load_result_t load_result;
191: struct uthread *uthread;
192: int i;
193: union {
194: /* #! and name of interpreter */
195: char ex_shell[SHSIZE];
196: /* Mach-O executable */
197: struct mach_header mach_header;
198: /* Fat executable */
199: struct fat_header fat_header;
200: char pad[512];
201: } exdata;
202: int resid, error;
203:
204: /* Start with an allocation */
205: execargs = kmem_alloc_wait(kernel_pageable_map, NCARGS);
206:
207: uthread = current_thread()->_uthread;
208: NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | SAVENAME,
209: UIO_USERSPACE, uap->fname, p);
210: if ((error = namei(&nd)))
211: goto bad1;
212: vp = nd.ni_vp;
213: VOP_LEASE(vp, p, p->p_ucred, LEASE_READ);
214:
215: if ((error = VOP_GETATTR(vp, &origvattr, p->p_ucred, p)))
216: goto bad;
217:
218: /* Check mount point */
219: if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
220: error = EACCES;
221: goto bad;
222: }
223:
224: indir = 0;
225: if ((vp->v_mount->mnt_flag & MNT_NOSUID) || (p->p_flag & P_TRACED))
226: origvattr.va_mode &= ~(VSUID | VSGID);
227:
228: *(&vattr) = *(&origvattr);
229:
230: again:
231: error = check_exec_access(p, vp, &vattr);
232: if (error)
233: goto bad;
234:
235: /*
236: * Read in first few bytes of file for segment sizes, magic number:
237: * 407 = plain executable
238: * 410 = RO text
239: * 413 = demand paged RO text
240: * Also an ASCII line beginning with #! is
241: * the file name of a ``shell'' and arguments may be prepended
242: * to the argument list if given here.
243: *
244: * SHELL NAMES ARE LIMITED IN LENGTH.
245: *
246: * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM
247: * THE ASCII LINE.
248: */
249: #if MACH_NBC
250: /*
251: * Can't hold an excluisve lock that was returned by namei as
252: * we depend on pageins to fill the data; there is no need to
253: * hold the lock on LEAF anymore
254: */
255: VOP_UNLOCK(vp, 0, p);
256: #endif /* MACH_NBC */
257:
258: exdata.ex_shell[0] = '\0'; /* for zero length files */
259: #if MACH_NBC
260: /* Should not pass with IO_NODELOCKED; but
261: * the check is ignored in vn_rdwr() if MACH_NBC is on
262: * Also if we pass with IO_NODELOCKED turned off
263: * vn_rdwr would try to take lock, which is incorrect
264: */
265:
266: /*
267: * because exec doesn't go through open and close
268: * we need to map the vnode for proper coherency
269: * and then unmap it to release the kernel map
270: */
271: map_vnode(vp, p);
272: #endif /* MACH_NBC */
273:
274: error = vn_rdwr(UIO_READ, vp, (caddr_t)&exdata, sizeof (exdata), 0,
275: UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
276: #if MACH_NBC
277: unmap_vnode(vp, p);
278: #endif /* MACH_NBC */
279:
280: if (error)
281: goto bad;
282:
283: #ifndef lint
284: if (resid > sizeof(exdata) - min(sizeof(exdata.mach_header),
285: sizeof(exdata.fat_header))
286: && exdata.ex_shell[0] != '#') {
287: error = ENOEXEC;
288: goto bad;
289: }
290: #endif /* lint */
291: mach_header = &exdata.mach_header;
292: fat_header = &exdata.fat_header;
293: if (mach_header->magic == MH_MAGIC)
294: is_fat = FALSE;
295: else if (fat_header->magic == FAT_MAGIC ||
296: fat_header->magic == FAT_CIGAM)
297: is_fat = TRUE;
298: else if (mach_header->magic == MH_CIGAM) {
299: error = EBADARCH;
300: goto bad;
301: } else {
302: if (exdata.ex_shell[0] != '#' ||
303: exdata.ex_shell[1] != '!' ||
304: indir) {
305: error = ENOEXEC;
306: goto bad;
307: }
308: cp = &exdata.ex_shell[2]; /* skip "#!" */
309: while (cp < &exdata.ex_shell[SHSIZE]) {
310: if (*cp == '\t')
311: *cp = ' ';
312: else if (*cp == '\n') {
313: *cp = '\0';
314: break;
315: }
316: cp++;
317: }
318: if (*cp != '\0') {
319: error = ENOEXEC;
320: goto bad;
321: }
322: cp = &exdata.ex_shell[2];
323: while (*cp == ' ')
324: cp++;
325: execnamep = cp;
326: while (*cp && *cp != ' ')
327: cp++;
328: cfarg[0] = '\0';
329: if (*cp) {
330: *cp++ = '\0';
331: while (*cp == ' ')
332: cp++;
333: if (*cp)
334: bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE);
335: }
336: indir = 1;
337: vput(vp);
338: nd.ni_cnd.cn_nameiop = LOOKUP;
339: nd.ni_cnd.cn_flags = (nd.ni_cnd.cn_flags & HASBUF) |
340: (FOLLOW | LOCKLEAF | SAVENAME);
341: nd.ni_segflg = UIO_SYSSPACE;
342: nd.ni_dirp = execnamep;
343: if ((error = namei(&nd)))
344: goto bad1;
345: vp = nd.ni_vp;
346: VOP_LEASE(vp, p, cred, LEASE_READ);
347: if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)))
348: goto bad;
349: goto again;
350: }
351:
352: /*
353: * Collect arguments on "file" in swap space.
354: */
355: na = 0;
356: ne = 0;
357: nc = 0;
358: cc = 0;
359: /* execargs gets allocated at the begining */
360: cp = (char *) execargs; /* running pointer for copy */
361: cc = NCARGS; /* size of execargs */
362: /*
363: * Copy arguments into file in argdev area.
364: */
365: if (uap->argp) for (;;) {
366: ap = NULL;
367: sharg = NULL;
368: if (indir && na == 0) {
369: sharg = nd.ni_cnd.cn_nameptr;
370: ap = (int)sharg;
371: uap->argp++; /* ignore argv[0] */
372: } else if (indir && (na == 1 && cfarg[0])) {
373: sharg = cfarg;
374: ap = (int)sharg;
375: } else if (indir && (na == 1 || (na == 2 && cfarg[0])))
376: ap = (int)uap->fname;
377: else if (uap->argp) {
378: ap = fuword((caddr_t)uap->argp);
379: uap->argp++;
380: }
381: if (ap == NULL && uap->envp) {
382: uap->argp = NULL;
383: if ((ap = fuword((caddr_t)uap->envp)) != NULL)
384: uap->envp++, ne++;
385: }
386: if (ap == NULL)
387: break;
388: na++;
389: if (ap == -1) {
390: error = EFAULT;
391: break;
392: }
393: do {
394: if (nc >= NCARGS-1) {
395: error = E2BIG;
396: break;
397: }
398: if (sharg) {
399: error = copystr(sharg, cp, (unsigned)cc, &len);
400: sharg += len;
401: } else {
402: error = copyinstr((caddr_t)ap, cp, (unsigned)cc,
403: &len);
404: ap += len;
405: }
406: cp += len;
407: nc += len;
408: cc -= len;
409: } while (error == ENAMETOOLONG);
410: if (error) {
411: goto bad;
412: }
413: }
414: nc = (nc + NBPW-1) & ~(NBPW-1);
415:
416: /*
417: * If we have a fat file, find "our" executable.
418: */
419: if (is_fat) {
420: /*
421: * Look up our architecture in the fat file.
422: */
423: lret = fatfile_getarch(vp, (vm_offset_t)fat_header, &fat_arch);
424: if (lret != LOAD_SUCCESS) {
425: error = load_return_to_errno(lret);
426: goto bad;
427: }
428: /* Read the Mach-O header out of it */
429: #if MACH_NBC
430: /*
431: * because exec doesn't go through open and close
432: * we need to map the vnode for proper coherency
433: * and then unmap it to release the kernel map
434: */
435: map_vnode(vp, p);
436: #endif /* MACH_NBC */
437: error = vn_rdwr(UIO_READ, vp, (caddr_t)&exdata.mach_header,
438: sizeof (exdata.mach_header),
439: fat_arch.offset,
440: UIO_SYSSPACE, (IO_UNIT|IO_NODELOCKED), cred, &resid, p);
441: #if MACH_NBC
442: unmap_vnode(vp, p);
443: #endif /* MACH_NBC */
444:
445: if (error) {
446: goto bad;
447: }
448:
449: /* Did we read a complete header? */
450: if (resid) {
451: error = EBADEXEC;
452: goto bad;
453: }
454:
455: /* Is what we found a Mach-O executable */
456: if (mach_header->magic != MH_MAGIC) {
457: error = ENOEXEC;
458: goto bad;
459: }
460:
461: /*
462: * Load the Mach-O file.
463: */
464: #if !MACH_NBC
465: VOP_UNLOCK(vp, 0, p);
466: #endif /* !MACH_NBC */
467: lret = load_machfile(vp, mach_header, fat_arch.offset,
468: fat_arch.size, &load_result);
469: } else {
470: /*
471: * Load the Mach-O file.
472: */
473: #if !MACH_NBC
474: VOP_UNLOCK(vp, 0, p);
475: #endif /* !MACH_NBC */
476: lret = load_machfile(vp, mach_header, 0,
477: (u_long)vattr.va_size, &load_result);
478: }
479:
480: if (lret != LOAD_SUCCESS) {
481: error = load_return_to_errno(lret);
482: goto bad;
483: }
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: p->p_flag |= P_SUGID;
510: /* Radar 2261856; setuid security hole fix */
511: /* Patch from OpenBSD: A. Ramesh */
512: /*
513: * XXX For setuid processes, attempt to ensure that
514: * stdin, stdout, and stderr are already allocated.
515: * We do not want userland to accidentally allocate
516: * descriptors in this range which has implied meaning
517: * to libc.
518: */
519: for (i = 0; i < 3; i++) {
520: extern struct fileops vnops;
521: struct nameidata nd1;
522: struct file *fp;
523: int indx;
524:
525: if (p->p_fd->fd_ofiles[i] == NULL) {
526: if ((error = falloc(p, &fp, &indx)) != 0)
527: continue;
528: NDINIT(&nd1, LOOKUP, FOLLOW, UIO_SYSSPACE,
529: "/dev/null", p);
530: if ((error = vn_open(&nd1, FREAD, 0)) != 0) {
531: ffree(fp);
532: p->p_fd->fd_ofiles[indx] = NULL;
533: break;
534: }
535: fp->f_flag = FREAD;
536: fp->f_type = DTYPE_VNODE;
537: fp->f_ops = &vnops;
538: fp->f_data = (caddr_t)nd1.ni_vp;
539: VOP_UNLOCK(nd1.ni_vp, 0, p);
540: }
541: }
542:
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: exception_from_kernel(EXC_BREAKPOINT, 0, 0);
551:
552: /*
553: * Temp hack until ld changes... allocate page 0 if its not
554: * already allocated.
555: *
556: * FIXME: ld has changed, can we remove this yet? -PK
557: */
558: {
559: vm_offset_t addr = 0;
560: kern_return_t ret;
561:
562: ret = vm_allocate(current_task()->map, &addr, PAGE_SIZE,
563: FALSE);
564: if (ret == KERN_SUCCESS) {
565: (void)vm_protect(current_task()->map, 0, PAGE_SIZE,
566: FALSE, VM_PROT_NONE);
567: }
568: }
569: if (error) {
570: /*
571: * NOTE: to prevent a race condition, getxfile had
572: * to temporarily unlock the inode. If new code needs to
573: * be inserted here before the iput below, and it needs
574: * to deal with the inode, keep this in mind.
575: */
576: goto bad;
577: }
578: VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY, p);
579: vput(vp);
580: vp = NULL;
581:
582: if (load_result.unixproc &&
583: create_unix_stack(current_task()->map,
584: load_result.user_stack, p)) {
585: error = load_return_to_errno(LOAD_NOSPACE);
586: goto bad;
587: }
588:
589: /*
590: * Copy back arglist if necessary.
591: */
592:
593: ucp = p->user_stack;
594: if (load_result.unixproc) {
595: #if STACK_GROWTH_UP
596: /* for stacks that grow up we:
597: * place storage for the ps_strings stuff
598: * put a pointer to the end of the string area at
599: * the beginning of the stack (used by table()),
600: * put a pointer to the arg area where we start the
601: * process stack pointer.
602: */
603: ap = ucp + NBPW; // leave word for string ptr
604: (void) suword((caddr_t)ap, load_result.mach_header); // dyld
605: ap += NBPW;
606: ucp = ap + na*NBPW + 3*NBPW;
607: (void) suword((caddr_t)(ap - 2 * NBPW), ucp + nc);
608: uthread->uu_ar0[SP] = ucp + nc;
609: (void) suword((caddr_t)uthread->uu_ar0[SP], 0);
610: uthread->uu_ar0[SP] += NBPW;
611: (void) suword((caddr_t)uthread->uu_ar0[SP], ap);
612: #else STACK_GROWTH_UP
613: ucp = ucp - nc - NBPW;
614: ap = ucp - na*NBPW - 3*NBPW;
615: uthread->uu_ar0[SP] = ap;
616: #endif /* STACK_GROWTH_UP */
617: (void) suword((caddr_t)ap, na-ne);
618: nc = 0;
619: cc = 0;
620: cp = (char *) execargs;
621: cc = NCARGS;
622: ps.ps_argvstr = (char *)ucp; /* first argv string */
623: ps.ps_nargvstr = na - ne; /* argc */
624: for (;;) {
625: ap += NBPW;
626: if (na == ne) {
627: (void) suword((caddr_t)ap, 0);
628: ap += NBPW;
629: ps.ps_envstr = (char *)ucp;
630: ps.ps_nenvstr = ne;
631: }
632: if (--na < 0)
633: break;
634: (void) suword((caddr_t)ap, ucp);
635: do {
636: error = copyoutstr(cp, (caddr_t)ucp,
637: (unsigned)cc, &len);
638: ucp += len;
639: cp += len;
640: nc += len;
641: cc -= len;
642: } while (error == ENOENT);
643: if (error == EFAULT)
644: break; /* bad stack - user's problem */
645: }
646: (void) suword((caddr_t)ap, 0);
647: // (void) copyout((caddr_t)&ps, (caddr_t)PS_STRINGS, sizeof(ps));
648: }
649:
650: #if STACK_GROWTH_UP
651: #else STACK_GROWTH_UP
652: if (load_result.dynlinker) {
653: ap = uthread->uu_ar0[SP] -= 4;
654: (void) suword((caddr_t)ap, load_result.mach_header);
655: }
656: #endif /* STACK_GROWTH_UP */
657:
658: /*
659: * This is GROSS XXX FIXME
660: */
661: #if defined(i386) || defined(ppc)
662: uthread->uu_ar0[PC] = load_result.entry_point;
663: #else
664: #error architecture not implemented!
665: #endif
666:
667: /*
668: * Reset signal state.
669: */
670: execsigs(p);
671:
672: /*
673: * Close file descriptors
674: * which specify close-on-exec.
675: */
676: fdexec(p);
677:
678: /*
679: * Remember file name for accounting.
680: */
681: p->p_acflag &= ~AFORK;
682: if (nd.ni_cnd.cn_namelen > MAXCOMLEN)
683: nd.ni_cnd.cn_namelen = MAXCOMLEN;
684: bcopy((caddr_t)nd.ni_cnd.cn_nameptr, (caddr_t)p->p_comm,
685: (unsigned)nd.ni_cnd.cn_namelen);
686: p->p_comm[nd.ni_cnd.cn_namelen] = '\0';
687:
688: /*
689: * mark as execed, wakeup the process that vforked (if any) and tell
690: * it that it now has it's own resources back
691: */
692: p->p_flag |= P_EXEC;
693: if (p->p_pptr && (p->p_flag & P_PPWAIT)) {
694: p->p_flag &= ~P_PPWAIT;
695: wakeup((caddr_t)p->p_pptr);
696: }
697:
698: bad:
699: FREE_ZONE(nd.ni_cnd.cn_pnbuf, nd.ni_cnd.cn_pnlen, M_NAMEI);
700: if (vp)
701: vput(vp);
702: bad1:
703: if (execargs)
704: kmem_free_wakeup(kernel_pageable_map, execargs, NCARGS);
705: return(error);
706: }
707:
708:
709: #define unix_stack_size(p) (p->p_rlimit[RLIMIT_STACK].rlim_cur)
710:
711: kern_return_t create_unix_stack(map, user_stack, p)
712: vm_map_t map;
713: vm_offset_t user_stack;
714: struct proc *p;
715: {
716: vm_size_t size;
717: vm_offset_t addr;
718:
719: p->user_stack = user_stack;
720: size = round_page(unix_stack_size(p));
721: #if STACK_GROWTH_UP
722: // stack always points to first address for stacks
723: addr = user_stack;
724: #else STACK_GROWTH_UP
725: addr = trunc_page(user_stack - size);
726: #endif /* STACK_GROWTH_UP */
727: return(vm_map_find(map, VM_OBJECT_NULL, (vm_offset_t) 0,
728: &addr, size, FALSE));
729: }
730:
731: #include <sys/reboot.h>
732:
733: char init_program_name[128] = "/sbin/mach_init\0";
734:
735: char init_args[128] = "-D\0";
736:
737: struct execve_args init_exec_args;
738: int init_attempts = 0;
739:
740:
741: void load_init_program(p)
742: struct proc *p;
743: {
744: vm_offset_t init_addr;
745: int *old_ap;
746: char *argv[3];
747: int error;
748: register_t retval[2];
749:
750:
751: unix_master();
752:
753: error = 0;
754:
755: /* init_args are copied in string form directly from bootstrap */
756:
757: do {
758: if (boothowto & RB_INITNAME) {
759: printf("init program? ");
760: gets(init_program_name, init_program_name);
761: }
762:
763: if (error && ((boothowto & RB_INITNAME) == 0) &&
764: (init_attempts == 1)) {
765: static char other_init[] = "/etc/mach_init";
766: printf("Load of %s, errno %d, trying %s\n",
767: init_program_name, error, other_init);
768: error = 0;
769: bcopy(other_init, init_program_name,
770: sizeof(other_init));
771: }
772:
773: init_attempts++;
774:
775: if (error) {
776: printf("Load of %s failed, errno %d\n",
777: init_program_name, error);
778: error = 0;
779: boothowto |= RB_INITNAME;
780: continue;
781: }
782:
783: /*
784: * Copy out program name.
785: */
786:
787: init_addr = VM_MIN_ADDRESS;
788: (void) vm_allocate(current_task()->map, &init_addr,
789: PAGE_SIZE, TRUE);
790: if (init_addr == 0)
791: init_addr++;
792: (void) copyout((caddr_t) init_program_name,
793: (caddr_t) (init_addr),
794: (unsigned) sizeof(init_program_name)+1);
795:
796: argv[0] = (char *) init_addr;
797: init_addr += sizeof(init_program_name);
798: init_addr = (vm_offset_t)ROUND_PTR(char, init_addr);
799:
800: /*
801: * Put out first (and only) argument, similarly.
802: * Assumes everything fits in a page as allocated
803: * above.
804: */
805:
806: (void) copyout((caddr_t) init_args,
807: (caddr_t) (init_addr),
808: (unsigned) sizeof(init_args));
809:
810: argv[1] = (char *) init_addr;
811: init_addr += sizeof(init_args);
812: init_addr = (vm_offset_t)ROUND_PTR(char, init_addr);
813:
814: /*
815: * Null-end the argument list
816: */
817:
818: argv[2] = (char *) 0;
819:
820: /*
821: * Copy out the argument list.
822: */
823:
824: (void) copyout((caddr_t) argv,
825: (caddr_t) (init_addr),
826: (unsigned) sizeof(argv));
827:
828: /*
829: * Set up argument block for fake call to execve.
830: */
831:
832: init_exec_args.fname = argv[0];
833: init_exec_args.argp = (char **) init_addr;
834: init_exec_args.envp = 0;
835:
836: old_ap = current_thread()->_uthread->uu_ap;
837: current_thread()->_uthread->uu_ap = (int *) &init_exec_args;
838: error = execve(p,&init_exec_args,retval);
839: current_thread()->_uthread->uu_ap = old_ap;
840: } while (error);
841:
842: unix_release();
843: }
844:
845: /*
846: * Convert a load_return_t to an errno.
847: */
848: static int load_return_to_errno(load_return_t lrtn)
849: {
850: switch (lrtn) {
851: case LOAD_SUCCESS:
852: return 0;
853: case LOAD_BADARCH:
854: return EBADARCH;
855: case LOAD_BADMACHO:
856: return EBADMACHO;
857: case LOAD_SHLIB:
858: return ESHLIBVERS;
859: case LOAD_NOSPACE:
860: return ENOMEM;
861: case LOAD_PROTECT:
862: return EACCES;
863: case LOAD_RESOURCE:
864: case LOAD_FAILURE:
865: default:
866: return EBADEXEC;
867: }
868: }
869:
870: /*
871: * exec_check_access()
872: */
873: int
874: check_exec_access(p, vp, vap)
875: struct proc *p;
876: struct vnode *vp;
877: struct vattr *vap;
878: {
879: int flag;
880: int error;
881:
882: if (error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p))
883: return (error);
884: flag = p->p_flag;
885: if (flag & P_TRACED) {
886: if (error = VOP_ACCESS(vp, VREAD, p->p_ucred, p))
887: return (error);
888: }
889: if (vp->v_type != VREG ||
890: (vap->va_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0)
891: return (EACCES);
892: return (0);
893: }
894:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.