|
|
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>
1.1.1.2 ! root 124:
! 125: #if KTRACE
! 126: #include <sys/ktrace.h>
! 127: #endif
! 128:
1.1 root 129: #include <mach/exception.h>
130:
131: #include <sys/signal.h>
132: #include <kern/task.h>
133: #include <kern/thread.h>
134:
135: #include <mach/vm_param.h>
136: #include <vm/vm_map.h>
137: #include <vm/vm_object.h>
138: #include <vm/vnode_pager.h>
139: #include <vm/vm_kern.h>
140: #include <vm/vm_user.h>
141: #include <kern/mapfs.h>
142: #include <kern/zalloc.h>
143:
144: #include <kern/parallel.h>
145: #include <kern/mach_loader.h>
146:
147: #include <mach-o/fat.h>
148: #include <mach-o/loader.h>
149:
150: #include <machine/vmparam.h>
151: #include <kernserv/c_utils.h>
152:
153: static int load_return_to_errno(load_return_t lrtn);
154: int execve(struct proc *p, struct execve_args *uap, register_t *retval);
155:
156: int
157: execv(p, args, retval)
158: struct proc *p;
159: void *args;
160: int *retval;
161: {
162: ((struct execve_args *)args)->envp = NULL;
163: return (execve(p, args, retval));
164: }
165:
166: /* ARGSUSED */
167: int
168: execve(p, uap, retval)
169: register struct proc *p;
170: register struct execve_args *uap;
171: register_t *retval;
172: {
173: register struct ucred *cred = p->p_ucred;
174: register struct filedesc *fdp = p->p_fd;
175: register nc;
176: register char *cp;
177: int na, ne, ucp, ap, cc;
178: unsigned len;
179: int indir;
180: char *sharg;
181: char *execnamep;
182: struct vnode *vp;
183: struct vattr vattr;
184: struct vattr origvattr;
185: vm_offset_t execargs;
186: struct nameidata nd;
187: struct ps_strings ps;
188: #define SHSIZE 512
189: char cfarg[SHSIZE];
190: boolean_t is_fat;
191: struct mach_header *mach_header;
192: struct fat_header *fat_header;
193: struct fat_arch fat_arch;
194: load_return_t lret;
195: load_result_t load_result;
196: struct uthread *uthread;
197: int i;
198: union {
199: /* #! and name of interpreter */
200: char ex_shell[SHSIZE];
201: /* Mach-O executable */
202: struct mach_header mach_header;
203: /* Fat executable */
204: struct fat_header fat_header;
205: char pad[512];
206: } exdata;
207: int resid, error;
208:
209: /* Start with an allocation */
210: execargs = kmem_alloc_wait(kernel_pageable_map, NCARGS);
211:
212: uthread = current_thread()->_uthread;
213: NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | SAVENAME,
214: UIO_USERSPACE, uap->fname, p);
215: if ((error = namei(&nd)))
216: goto bad1;
217: vp = nd.ni_vp;
218: VOP_LEASE(vp, p, p->p_ucred, LEASE_READ);
219:
220: if ((error = VOP_GETATTR(vp, &origvattr, p->p_ucred, p)))
221: goto bad;
222:
223: /* Check mount point */
224: if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
225: error = EACCES;
226: goto bad;
227: }
228:
229: indir = 0;
230: if ((vp->v_mount->mnt_flag & MNT_NOSUID) || (p->p_flag & P_TRACED))
231: origvattr.va_mode &= ~(VSUID | VSGID);
232:
233: *(&vattr) = *(&origvattr);
234:
235: again:
236: error = check_exec_access(p, vp, &vattr);
237: if (error)
238: goto bad;
239:
240: /*
241: * Read in first few bytes of file for segment sizes, magic number:
242: * 407 = plain executable
243: * 410 = RO text
244: * 413 = demand paged RO text
245: * Also an ASCII line beginning with #! is
246: * the file name of a ``shell'' and arguments may be prepended
247: * to the argument list if given here.
248: *
249: * SHELL NAMES ARE LIMITED IN LENGTH.
250: *
251: * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM
252: * THE ASCII LINE.
253: */
254: #if MACH_NBC
255: /*
256: * Can't hold an excluisve lock that was returned by namei as
257: * we depend on pageins to fill the data; there is no need to
258: * hold the lock on LEAF anymore
259: */
260: VOP_UNLOCK(vp, 0, p);
261: #endif /* MACH_NBC */
262:
263: exdata.ex_shell[0] = '\0'; /* for zero length files */
264: #if MACH_NBC
265: /* Should not pass with IO_NODELOCKED; but
266: * the check is ignored in vn_rdwr() if MACH_NBC is on
267: * Also if we pass with IO_NODELOCKED turned off
268: * vn_rdwr would try to take lock, which is incorrect
269: */
270:
271: /*
272: * because exec doesn't go through open and close
273: * we need to map the vnode for proper coherency
274: * and then unmap it to release the kernel map
275: */
276: map_vnode(vp, p);
277: #endif /* MACH_NBC */
278:
279: error = vn_rdwr(UIO_READ, vp, (caddr_t)&exdata, sizeof (exdata), 0,
280: UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
281: #if MACH_NBC
282: unmap_vnode(vp, p);
283: #endif /* MACH_NBC */
284:
285: if (error)
286: goto bad;
287:
288: #ifndef lint
289: if (resid > sizeof(exdata) - min(sizeof(exdata.mach_header),
290: sizeof(exdata.fat_header))
291: && exdata.ex_shell[0] != '#') {
292: error = ENOEXEC;
293: goto bad;
294: }
295: #endif /* lint */
296: mach_header = &exdata.mach_header;
297: fat_header = &exdata.fat_header;
298: if (mach_header->magic == MH_MAGIC)
299: is_fat = FALSE;
300: else if (fat_header->magic == FAT_MAGIC ||
301: fat_header->magic == FAT_CIGAM)
302: is_fat = TRUE;
303: else if (mach_header->magic == MH_CIGAM) {
304: error = EBADARCH;
305: goto bad;
306: } else {
307: if (exdata.ex_shell[0] != '#' ||
308: exdata.ex_shell[1] != '!' ||
309: indir) {
310: error = ENOEXEC;
311: goto bad;
312: }
313: cp = &exdata.ex_shell[2]; /* skip "#!" */
314: while (cp < &exdata.ex_shell[SHSIZE]) {
315: if (*cp == '\t')
316: *cp = ' ';
317: else if (*cp == '\n') {
318: *cp = '\0';
319: break;
320: }
321: cp++;
322: }
323: if (*cp != '\0') {
324: error = ENOEXEC;
325: goto bad;
326: }
327: cp = &exdata.ex_shell[2];
328: while (*cp == ' ')
329: cp++;
330: execnamep = cp;
331: while (*cp && *cp != ' ')
332: cp++;
333: cfarg[0] = '\0';
334: if (*cp) {
335: *cp++ = '\0';
336: while (*cp == ' ')
337: cp++;
338: if (*cp)
339: bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE);
340: }
341: indir = 1;
342: vput(vp);
343: nd.ni_cnd.cn_nameiop = LOOKUP;
344: nd.ni_cnd.cn_flags = (nd.ni_cnd.cn_flags & HASBUF) |
345: (FOLLOW | LOCKLEAF | SAVENAME);
346: nd.ni_segflg = UIO_SYSSPACE;
347: nd.ni_dirp = execnamep;
348: if ((error = namei(&nd)))
349: goto bad1;
350: vp = nd.ni_vp;
351: VOP_LEASE(vp, p, cred, LEASE_READ);
352: if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)))
353: goto bad;
354: goto again;
355: }
356:
357: /*
358: * Collect arguments on "file" in swap space.
359: */
360: na = 0;
361: ne = 0;
362: nc = 0;
363: cc = 0;
364: /* execargs gets allocated at the begining */
365: cp = (char *) execargs; /* running pointer for copy */
366: cc = NCARGS; /* size of execargs */
367: /*
368: * Copy arguments into file in argdev area.
369: */
370: if (uap->argp) for (;;) {
371: ap = NULL;
372: sharg = NULL;
373: if (indir && na == 0) {
374: sharg = nd.ni_cnd.cn_nameptr;
375: ap = (int)sharg;
376: uap->argp++; /* ignore argv[0] */
377: } else if (indir && (na == 1 && cfarg[0])) {
378: sharg = cfarg;
379: ap = (int)sharg;
380: } else if (indir && (na == 1 || (na == 2 && cfarg[0])))
381: ap = (int)uap->fname;
382: else if (uap->argp) {
383: ap = fuword((caddr_t)uap->argp);
384: uap->argp++;
385: }
386: if (ap == NULL && uap->envp) {
387: uap->argp = NULL;
388: if ((ap = fuword((caddr_t)uap->envp)) != NULL)
389: uap->envp++, ne++;
390: }
391: if (ap == NULL)
392: break;
393: na++;
394: if (ap == -1) {
395: error = EFAULT;
396: break;
397: }
398: do {
399: if (nc >= NCARGS-1) {
400: error = E2BIG;
401: break;
402: }
403: if (sharg) {
404: error = copystr(sharg, cp, (unsigned)cc, &len);
405: sharg += len;
406: } else {
407: error = copyinstr((caddr_t)ap, cp, (unsigned)cc,
408: &len);
409: ap += len;
410: }
411: cp += len;
412: nc += len;
413: cc -= len;
414: } while (error == ENAMETOOLONG);
415: if (error) {
416: goto bad;
417: }
418: }
419: nc = (nc + NBPW-1) & ~(NBPW-1);
420:
421: /*
422: * If we have a fat file, find "our" executable.
423: */
424: if (is_fat) {
425: /*
426: * Look up our architecture in the fat file.
427: */
428: lret = fatfile_getarch(vp, (vm_offset_t)fat_header, &fat_arch);
429: if (lret != LOAD_SUCCESS) {
430: error = load_return_to_errno(lret);
431: goto bad;
432: }
433: /* Read the Mach-O header out of it */
434: #if MACH_NBC
435: /*
436: * because exec doesn't go through open and close
437: * we need to map the vnode for proper coherency
438: * and then unmap it to release the kernel map
439: */
440: map_vnode(vp, p);
441: #endif /* MACH_NBC */
442: error = vn_rdwr(UIO_READ, vp, (caddr_t)&exdata.mach_header,
443: sizeof (exdata.mach_header),
444: fat_arch.offset,
445: UIO_SYSSPACE, (IO_UNIT|IO_NODELOCKED), cred, &resid, p);
446: #if MACH_NBC
447: unmap_vnode(vp, p);
448: #endif /* MACH_NBC */
449:
450: if (error) {
451: goto bad;
452: }
453:
454: /* Did we read a complete header? */
455: if (resid) {
456: error = EBADEXEC;
457: goto bad;
458: }
459:
460: /* Is what we found a Mach-O executable */
461: if (mach_header->magic != MH_MAGIC) {
462: error = ENOEXEC;
463: goto bad;
464: }
465:
466: /*
467: * Load the Mach-O file.
468: */
469: #if !MACH_NBC
470: VOP_UNLOCK(vp, 0, p);
471: #endif /* !MACH_NBC */
472: lret = load_machfile(vp, mach_header, fat_arch.offset,
473: fat_arch.size, &load_result);
474: } else {
475: /*
476: * Load the Mach-O file.
477: */
478: #if !MACH_NBC
479: VOP_UNLOCK(vp, 0, p);
480: #endif /* !MACH_NBC */
481: lret = load_machfile(vp, mach_header, 0,
482: (u_long)vattr.va_size, &load_result);
483: }
484:
485: if (lret != LOAD_SUCCESS) {
486: error = load_return_to_errno(lret);
487: goto bad;
488: }
489:
490: /*
491: * deal with set[ug]id.
492: */
493: p->p_flag &= ~P_SUGID;
494: if (((origvattr.va_mode & VSUID) != 0 &&
495: p->p_ucred->cr_uid != origvattr.va_uid)
496: || (origvattr.va_mode & VSGID) != 0 &&
497: p->p_ucred->cr_gid != origvattr.va_gid) {
498: p->p_ucred = crcopy(cred);
499: #if KTRACE
500: /*
501: * If process is being ktraced, turn off - unless
502: * root set it.
503: */
504: if (p->p_tracep && !(p->p_traceflag & KTRFAC_ROOT)) {
505: vrele(p->p_tracep);
506: p->p_tracep = NULL;
507: p->p_traceflag = 0;
508: }
509: #endif
510: if (origvattr.va_mode & VSUID)
511: p->p_ucred->cr_uid = origvattr.va_uid;
512: if (origvattr.va_mode & VSGID)
513: p->p_ucred->cr_gid = origvattr.va_gid;
514: p->p_flag |= P_SUGID;
515: /* Radar 2261856; setuid security hole fix */
516: /* Patch from OpenBSD: A. Ramesh */
517: /*
518: * XXX For setuid processes, attempt to ensure that
519: * stdin, stdout, and stderr are already allocated.
520: * We do not want userland to accidentally allocate
521: * descriptors in this range which has implied meaning
522: * to libc.
523: */
524: for (i = 0; i < 3; i++) {
525: extern struct fileops vnops;
526: struct nameidata nd1;
527: struct file *fp;
528: int indx;
529:
530: if (p->p_fd->fd_ofiles[i] == NULL) {
531: if ((error = falloc(p, &fp, &indx)) != 0)
532: continue;
533: NDINIT(&nd1, LOOKUP, FOLLOW, UIO_SYSSPACE,
534: "/dev/null", p);
535: if ((error = vn_open(&nd1, FREAD, 0)) != 0) {
536: ffree(fp);
537: p->p_fd->fd_ofiles[indx] = NULL;
538: break;
539: }
540: fp->f_flag = FREAD;
541: fp->f_type = DTYPE_VNODE;
542: fp->f_ops = &vnops;
543: fp->f_data = (caddr_t)nd1.ni_vp;
544: VOP_UNLOCK(nd1.ni_vp, 0, p);
545: }
546: }
547:
548:
549:
550: }
551: p->p_cred->p_svuid = p->p_ucred->cr_uid;
552: p->p_cred->p_svgid = p->p_ucred->cr_gid;
553:
554: if (p->p_flag & P_TRACED)
555: exception_from_kernel(EXC_BREAKPOINT, 0, 0);
556:
557: /*
558: * Temp hack until ld changes... allocate page 0 if its not
559: * already allocated.
560: *
561: * FIXME: ld has changed, can we remove this yet? -PK
562: */
563: {
564: vm_offset_t addr = 0;
565: kern_return_t ret;
566:
567: ret = vm_allocate(current_task()->map, &addr, PAGE_SIZE,
568: FALSE);
569: if (ret == KERN_SUCCESS) {
570: (void)vm_protect(current_task()->map, 0, PAGE_SIZE,
571: FALSE, VM_PROT_NONE);
572: }
573: }
574: if (error) {
575: /*
576: * NOTE: to prevent a race condition, getxfile had
577: * to temporarily unlock the inode. If new code needs to
578: * be inserted here before the iput below, and it needs
579: * to deal with the inode, keep this in mind.
580: */
581: goto bad;
582: }
583: VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY, p);
584: vput(vp);
585: vp = NULL;
586:
587: if (load_result.unixproc &&
588: create_unix_stack(current_task()->map,
589: load_result.user_stack, p)) {
590: error = load_return_to_errno(LOAD_NOSPACE);
591: goto bad;
592: }
593:
594: /*
595: * Copy back arglist if necessary.
596: */
597:
598: ucp = p->user_stack;
599: if (load_result.unixproc) {
600: #if STACK_GROWTH_UP
601: /* for stacks that grow up we:
602: * place storage for the ps_strings stuff
603: * put a pointer to the end of the string area at
604: * the beginning of the stack (used by table()),
605: * put a pointer to the arg area where we start the
606: * process stack pointer.
607: */
608: ap = ucp + NBPW; // leave word for string ptr
609: (void) suword((caddr_t)ap, load_result.mach_header); // dyld
610: ap += NBPW;
611: ucp = ap + na*NBPW + 3*NBPW;
612: (void) suword((caddr_t)(ap - 2 * NBPW), ucp + nc);
613: uthread->uu_ar0[SP] = ucp + nc;
614: (void) suword((caddr_t)uthread->uu_ar0[SP], 0);
615: uthread->uu_ar0[SP] += NBPW;
616: (void) suword((caddr_t)uthread->uu_ar0[SP], ap);
617: #else STACK_GROWTH_UP
618: ucp = ucp - nc - NBPW;
619: ap = ucp - na*NBPW - 3*NBPW;
620: uthread->uu_ar0[SP] = ap;
621: #endif /* STACK_GROWTH_UP */
622: (void) suword((caddr_t)ap, na-ne);
623: nc = 0;
624: cc = 0;
625: cp = (char *) execargs;
626: cc = NCARGS;
627: ps.ps_argvstr = (char *)ucp; /* first argv string */
628: ps.ps_nargvstr = na - ne; /* argc */
629: for (;;) {
630: ap += NBPW;
631: if (na == ne) {
632: (void) suword((caddr_t)ap, 0);
633: ap += NBPW;
634: ps.ps_envstr = (char *)ucp;
635: ps.ps_nenvstr = ne;
636: }
637: if (--na < 0)
638: break;
639: (void) suword((caddr_t)ap, ucp);
640: do {
641: error = copyoutstr(cp, (caddr_t)ucp,
642: (unsigned)cc, &len);
643: ucp += len;
644: cp += len;
645: nc += len;
646: cc -= len;
647: } while (error == ENOENT);
648: if (error == EFAULT)
649: break; /* bad stack - user's problem */
650: }
651: (void) suword((caddr_t)ap, 0);
652: // (void) copyout((caddr_t)&ps, (caddr_t)PS_STRINGS, sizeof(ps));
653: }
654:
655: #if STACK_GROWTH_UP
656: #else STACK_GROWTH_UP
657: if (load_result.dynlinker) {
658: ap = uthread->uu_ar0[SP] -= 4;
659: (void) suword((caddr_t)ap, load_result.mach_header);
660: }
661: #endif /* STACK_GROWTH_UP */
662:
663: /*
664: * This is GROSS XXX FIXME
665: */
666: #if defined(i386) || defined(ppc)
667: uthread->uu_ar0[PC] = load_result.entry_point;
668: #else
669: #error architecture not implemented!
670: #endif
671:
672: /*
673: * Reset signal state.
674: */
675: execsigs(p);
676:
677: /*
678: * Close file descriptors
679: * which specify close-on-exec.
680: */
681: fdexec(p);
682:
683: /*
684: * Remember file name for accounting.
685: */
686: p->p_acflag &= ~AFORK;
687: if (nd.ni_cnd.cn_namelen > MAXCOMLEN)
688: nd.ni_cnd.cn_namelen = MAXCOMLEN;
689: bcopy((caddr_t)nd.ni_cnd.cn_nameptr, (caddr_t)p->p_comm,
690: (unsigned)nd.ni_cnd.cn_namelen);
691: p->p_comm[nd.ni_cnd.cn_namelen] = '\0';
692:
693: /*
694: * mark as execed, wakeup the process that vforked (if any) and tell
695: * it that it now has it's own resources back
696: */
697: p->p_flag |= P_EXEC;
698: if (p->p_pptr && (p->p_flag & P_PPWAIT)) {
699: p->p_flag &= ~P_PPWAIT;
700: wakeup((caddr_t)p->p_pptr);
701: }
702:
703: bad:
704: FREE_ZONE(nd.ni_cnd.cn_pnbuf, nd.ni_cnd.cn_pnlen, M_NAMEI);
705: if (vp)
706: vput(vp);
707: bad1:
708: if (execargs)
709: kmem_free_wakeup(kernel_pageable_map, execargs, NCARGS);
710: return(error);
711: }
712:
713:
714: #define unix_stack_size(p) (p->p_rlimit[RLIMIT_STACK].rlim_cur)
715:
716: kern_return_t create_unix_stack(map, user_stack, p)
717: vm_map_t map;
718: vm_offset_t user_stack;
719: struct proc *p;
720: {
721: vm_size_t size;
722: vm_offset_t addr;
723:
724: p->user_stack = user_stack;
725: size = round_page(unix_stack_size(p));
726: #if STACK_GROWTH_UP
727: // stack always points to first address for stacks
728: addr = user_stack;
729: #else STACK_GROWTH_UP
730: addr = trunc_page(user_stack - size);
731: #endif /* STACK_GROWTH_UP */
732: return(vm_map_find(map, VM_OBJECT_NULL, (vm_offset_t) 0,
733: &addr, size, FALSE));
734: }
735:
736: #include <sys/reboot.h>
737:
738: char init_program_name[128] = "/sbin/mach_init\0";
739:
740: char init_args[128] = "-D\0";
741:
742: struct execve_args init_exec_args;
743: int init_attempts = 0;
744:
745:
746: void load_init_program(p)
747: struct proc *p;
748: {
749: vm_offset_t init_addr;
750: int *old_ap;
751: char *argv[3];
752: int error;
753: register_t retval[2];
754:
755:
756: unix_master();
757:
758: error = 0;
759:
760: /* init_args are copied in string form directly from bootstrap */
761:
762: do {
763: if (boothowto & RB_INITNAME) {
764: printf("init program? ");
765: gets(init_program_name, init_program_name);
766: }
767:
768: if (error && ((boothowto & RB_INITNAME) == 0) &&
769: (init_attempts == 1)) {
770: static char other_init[] = "/etc/mach_init";
771: printf("Load of %s, errno %d, trying %s\n",
772: init_program_name, error, other_init);
773: error = 0;
774: bcopy(other_init, init_program_name,
775: sizeof(other_init));
776: }
777:
778: init_attempts++;
779:
780: if (error) {
781: printf("Load of %s failed, errno %d\n",
782: init_program_name, error);
783: error = 0;
784: boothowto |= RB_INITNAME;
785: continue;
786: }
787:
788: /*
789: * Copy out program name.
790: */
791:
792: init_addr = VM_MIN_ADDRESS;
793: (void) vm_allocate(current_task()->map, &init_addr,
794: PAGE_SIZE, TRUE);
795: if (init_addr == 0)
796: init_addr++;
797: (void) copyout((caddr_t) init_program_name,
798: (caddr_t) (init_addr),
799: (unsigned) sizeof(init_program_name)+1);
800:
801: argv[0] = (char *) init_addr;
802: init_addr += sizeof(init_program_name);
803: init_addr = (vm_offset_t)ROUND_PTR(char, init_addr);
804:
805: /*
806: * Put out first (and only) argument, similarly.
807: * Assumes everything fits in a page as allocated
808: * above.
809: */
810:
811: (void) copyout((caddr_t) init_args,
812: (caddr_t) (init_addr),
813: (unsigned) sizeof(init_args));
814:
815: argv[1] = (char *) init_addr;
816: init_addr += sizeof(init_args);
817: init_addr = (vm_offset_t)ROUND_PTR(char, init_addr);
818:
819: /*
820: * Null-end the argument list
821: */
822:
823: argv[2] = (char *) 0;
824:
825: /*
826: * Copy out the argument list.
827: */
828:
829: (void) copyout((caddr_t) argv,
830: (caddr_t) (init_addr),
831: (unsigned) sizeof(argv));
832:
833: /*
834: * Set up argument block for fake call to execve.
835: */
836:
837: init_exec_args.fname = argv[0];
838: init_exec_args.argp = (char **) init_addr;
839: init_exec_args.envp = 0;
840:
841: old_ap = current_thread()->_uthread->uu_ap;
842: current_thread()->_uthread->uu_ap = (int *) &init_exec_args;
843: error = execve(p,&init_exec_args,retval);
844: current_thread()->_uthread->uu_ap = old_ap;
845: } while (error);
846:
847: unix_release();
848: }
849:
850: /*
851: * Convert a load_return_t to an errno.
852: */
853: static int load_return_to_errno(load_return_t lrtn)
854: {
855: switch (lrtn) {
856: case LOAD_SUCCESS:
857: return 0;
858: case LOAD_BADARCH:
859: return EBADARCH;
860: case LOAD_BADMACHO:
861: return EBADMACHO;
862: case LOAD_SHLIB:
863: return ESHLIBVERS;
864: case LOAD_NOSPACE:
865: return ENOMEM;
866: case LOAD_PROTECT:
867: return EACCES;
868: case LOAD_RESOURCE:
869: case LOAD_FAILURE:
870: default:
871: return EBADEXEC;
872: }
873: }
874:
875: /*
876: * exec_check_access()
877: */
878: int
879: check_exec_access(p, vp, vap)
880: struct proc *p;
881: struct vnode *vp;
882: struct vattr *vap;
883: {
884: int flag;
885: int error;
886:
887: if (error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p))
888: return (error);
889: flag = p->p_flag;
890: if (flag & P_TRACED) {
891: if (error = VOP_ACCESS(vp, VREAD, p->p_ucred, p))
892: return (error);
893: }
894: if (vp->v_type != VREG ||
895: (vap->va_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0)
896: return (EACCES);
897: return (0);
898: }
899:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.