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