]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/kern_exec.c
298e00dbfe546803d9bc23f9ce471d6dd0f7ec5b
[apple/xnu.git] / bsd / kern / kern_exec.c
1 /*
2 * Copyright (c) 2000-2004 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 #include <sys/aio_kern.h>
93
94 #include <bsm/audit_kernel.h>
95
96 #include <mach/vm_param.h>
97
98 #include <vm/vm_map.h>
99
100 extern vm_map_t vm_map_switch(vm_map_t map); /* XXX */
101
102 #include <vm/vm_kern.h>
103 #include <vm/vm_shared_memory_server.h>
104
105 #include <kern/thread.h>
106 #include <kern/task.h>
107
108 #include <kern/ast.h>
109 #include <kern/mach_loader.h>
110 #include <mach-o/fat.h>
111 #include <mach-o/loader.h>
112 #include <machine/vmparam.h>
113 #if KTRACE
114 #include <sys/ktrace.h>
115 #include <sys/ubc.h>
116 #endif
117
118 int app_profile = 0;
119
120 extern vm_map_t bsd_pageable_map;
121
122 #define ROUND_PTR(type, addr) \
123 (type *)( ( (unsigned)(addr) + 16 - 1) \
124 & ~(16 - 1) )
125
126 static int load_return_to_errno(load_return_t lrtn);
127 int execve(struct proc *p, struct execve_args *uap, register_t *retval);
128 static int execargs_alloc(vm_offset_t *addrp);
129 static int execargs_free(vm_offset_t addr);
130
131 int
132 execv(p, args, retval)
133 struct proc *p;
134 void *args;
135 int *retval;
136 {
137 ((struct execve_args *)args)->envp = NULL;
138 return (execve(p, args, retval));
139 }
140
141 extern char classichandler[32];
142 extern long classichandler_fsid;
143 extern long classichandler_fileid;
144
145 /*
146 * Helper routine to get rid of a loop in execve. Given a pointer to
147 * something for the arg list (which might be in kernel space or in user
148 * space), copy it into the kernel buffer at the currentWritePt. This code
149 * does the proper thing to get the data transferred.
150 * bytesWritten, currentWritePt, and bytesLeft are kept up-to-date.
151 */
152
153 static int copyArgument(char *argument, int pointerInKernel,
154 int *bytesWritten,char **currentWritePt,
155 int *bytesLeft){
156 int error = 0;
157 do {
158 size_t len = 0;
159 if (*bytesLeft <= 0) {
160 error = E2BIG;
161 break;
162 }
163 if (pointerInKernel == UIO_SYSSPACE) {
164 error = copystr(argument, *currentWritePt, (unsigned)*bytesLeft, &len);
165 } else {
166 /*
167 * pointer in kernel == UIO_USERSPACE
168 * Copy in from user space.
169 */
170 error = copyinstr((caddr_t)argument, *currentWritePt, (unsigned)*bytesLeft,
171 &len);
172 }
173 *currentWritePt += len;
174 *bytesWritten += len;
175 *bytesLeft -= len;
176 } while (error == ENAMETOOLONG);
177 return error;
178 }
179
180 /* ARGSUSED */
181 int
182 execve(p, uap, retval)
183 register struct proc *p;
184 register struct execve_args *uap;
185 register_t *retval;
186 {
187 register struct ucred *cred = p->p_ucred;
188 register struct filedesc *fdp = p->p_fd;
189 int nc;
190 char *cp;
191 int na, ne, ucp, ap, cc;
192 unsigned len;
193 int executingInterpreter=0;
194
195 int executingClassic=0;
196 char binaryWithClassicName[sizeof(p->p_comm)] = {0};
197 char *execnamep;
198 struct vnode *vp;
199 struct vattr vattr;
200 struct vattr origvattr;
201 vm_offset_t execargs;
202 struct nameidata nd;
203 struct ps_strings ps;
204 #define SHSIZE 512
205 /* Argument(s) to an interpreter. If we're executing a shell
206 * script, the name (#!/bin/csh) is allowed to be followed by
207 * arguments. cfarg holds these arguments.
208 */
209 char cfarg[SHSIZE];
210 boolean_t is_fat;
211 kern_return_t ret;
212 struct mach_header *mach_header;
213 struct fat_header *fat_header;
214 struct fat_arch fat_arch;
215 load_return_t lret;
216 load_result_t load_result;
217 struct uthread *uthread;
218 vm_map_t old_map;
219 vm_map_t map;
220 int i;
221 boolean_t clean_regions = FALSE;
222 shared_region_mapping_t shared_region = NULL;
223 shared_region_mapping_t initial_region = NULL;
224
225 union {
226 /* #! and name of interpreter */
227 char ex_shell[SHSIZE];
228 /* Mach-O executable */
229 struct mach_header mach_header;
230 /* Fat executable */
231 struct fat_header fat_header;
232 char pad[512];
233 } exdata;
234 int resid, error;
235 char *savedpath;
236 int savedpathlen = 0;
237 vm_offset_t *execargsp;
238 char *cpnospace;
239 task_t task;
240 task_t new_task;
241 thread_act_t thr_act;
242 int numthreads;
243 int vfexec=0;
244 unsigned long arch_offset =0;
245 unsigned long arch_size = 0;
246 char *ws_cache_name = NULL; /* used for pre-heat */
247
248 /*
249 * XXXAUDIT: Currently, we only audit the pathname of the binary.
250 * There may also be poor interaction with dyld.
251 */
252
253 cfarg[0] = '\0'; /* initialize to null value. */
254 task = current_task();
255 thr_act = current_act();
256 uthread = get_bsdthread_info(thr_act);
257
258 if (uthread->uu_flag & P_VFORK) {
259 vfexec = 1; /* Mark in exec */
260 } else {
261 if (task != kernel_task) {
262 numthreads = get_task_numacts(task);
263 if (numthreads <= 0 )
264 return(EINVAL);
265 if (numthreads > 1) {
266 return(EOPNOTSUPP);
267 }
268 }
269 }
270
271 error = execargs_alloc(&execargs);
272 if (error)
273 return(error);
274
275 savedpath = (char *)execargs;
276
277 /*
278 * To support new app package launching for Mac OS X, the dyld
279 * needs the first argument to execve() stored on the user stack.
280 * Copyin the "path" at the begining of the "execargs" buffer
281 * allocated above.
282 *
283 * We have to do this before namei() because in case of
284 * symbolic links, namei() would overwrite the original "path".
285 * In case the last symbolic link resolved was a relative pathname
286 * we would lose the original "path", which could be an
287 * absolute pathname. This might be unacceptable for dyld.
288 */
289 /* XXX We could optimize to avoid copyinstr in the namei() */
290
291 /*
292 * XXXAUDIT: Note: the double copyin introduces an audit
293 * race. To correct this race, we must use a single
294 * copyin().
295 */
296
297 error = copyinstr(uap->fname, savedpath,
298 MAXPATHLEN, (size_t *)&savedpathlen);
299 if (error) {
300 execargs_free(execargs);
301 return(error);
302 }
303 /*
304 * copyinstr will put in savedpathlen, the count of
305 * characters (including NULL) in the path.
306 * No app profiles under chroot
307 */
308
309 if((fdp->fd_rdir == NULLVP) && (app_profile != 0)) {
310
311 /* grab the name of the file out of its path */
312 /* we will need this for lookup within the */
313 /* name file */
314 ws_cache_name = savedpath + savedpathlen;
315 while (ws_cache_name[0] != '/') {
316 if(ws_cache_name == savedpath) {
317 ws_cache_name--;
318 break;
319 }
320 ws_cache_name--;
321 }
322 ws_cache_name++;
323 }
324
325 /* Save the name aside for future use */
326 execargsp = (vm_offset_t *)((char *)(execargs) + savedpathlen);
327
328 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | SAVENAME | AUDITVNPATH1,
329 UIO_USERSPACE, uap->fname, p);
330 error = namei(&nd);
331 if (error)
332 goto bad1;
333 vp = nd.ni_vp;
334 VOP_LEASE(vp, p, p->p_ucred, LEASE_READ);
335
336 if ((error = VOP_GETATTR(vp, &origvattr, p->p_ucred, p)))
337 goto bad;
338
339 /* Check mount point */
340 if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
341 error = EACCES;
342 goto bad;
343 }
344
345 if ((vp->v_mount->mnt_flag & MNT_NOSUID) || (p->p_flag & P_TRACED))
346 origvattr.va_mode &= ~(VSUID | VSGID);
347
348 *(&vattr) = *(&origvattr);
349
350 again:
351 error = check_exec_access(p, vp, &vattr);
352 if (error)
353 goto bad;
354
355 /*
356 * Read in first few bytes of file for segment sizes, magic number:
357 * 407 = plain executable
358 * 410 = RO text
359 * 413 = demand paged RO text
360 * Also an ASCII line beginning with #! is
361 * the file name of a ``shell'' and arguments may be prepended
362 * to the argument list if given here.
363 *
364 * SHELL NAMES ARE LIMITED IN LENGTH.
365 *
366 * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM
367 * THE ASCII LINE.
368 */
369
370 exdata.ex_shell[0] = '\0'; /* for zero length files */
371
372 error = vn_rdwr(UIO_READ, vp, (caddr_t)&exdata, sizeof (exdata), 0,
373 UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
374
375 if (error)
376 goto bad;
377
378 #ifndef lint
379 if (resid > sizeof(exdata) - min(sizeof(exdata.mach_header),
380 sizeof(exdata.fat_header))
381 && exdata.ex_shell[0] != '#') {
382 error = ENOEXEC;
383 goto bad;
384 }
385 #endif /* lint */
386 mach_header = &exdata.mach_header;
387 fat_header = &exdata.fat_header;
388 if ((mach_header->magic == MH_CIGAM) &&
389 (classichandler[0] == 0)) {
390 error = EBADARCH;
391 goto bad;
392 } else if ((mach_header->magic == MH_MAGIC) ||
393 (mach_header->magic == MH_CIGAM)) {
394 is_fat = FALSE;
395 } else if ((fat_header->magic == FAT_MAGIC) ||
396 (fat_header->magic == FAT_CIGAM)) {
397 is_fat = TRUE;
398 } else {
399 /* If we've already redirected once from an interpreted file
400 * to an interpreter, don't permit the second time.
401 */
402 if (exdata.ex_shell[0] != '#' ||
403 exdata.ex_shell[1] != '!' ||
404 executingInterpreter) {
405 error = ENOEXEC;
406 goto bad;
407 }
408 if (executingClassic == 1) {
409 error = EBADARCH;
410 goto bad;
411 }
412 cp = &exdata.ex_shell[2]; /* skip "#!" */
413 while (cp < &exdata.ex_shell[SHSIZE]) {
414 if (*cp == '\t') /* convert all tabs to spaces */
415 *cp = ' ';
416 else if (*cp == '\n' || *cp == '#') {
417 *cp = '\0'; /* trunc the line at nl or comment */
418
419 /* go back and remove the spaces before the /n or # */
420 /* todo: do we have to do this if we fix the passing of args to shells ? */
421 if ( cp != &exdata.ex_shell[2] ) {
422 do {
423 if ( *(cp-1) != ' ')
424 break;
425 *(--cp) = '\0';
426 } while ( cp != &exdata.ex_shell[2] );
427 }
428 break;
429 }
430 cp++;
431 }
432 if (*cp != '\0') {
433 error = ENOEXEC;
434 goto bad;
435 }
436 cp = &exdata.ex_shell[2];
437 while (*cp == ' ')
438 cp++;
439 execnamep = cp;
440 while (*cp && *cp != ' ')
441 cp++;
442 cfarg[0] = '\0';
443 cpnospace = cp;
444 if (*cp) {
445 *cp++ = '\0';
446 while (*cp == ' ')
447 cp++;
448 if (*cp)
449 bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE);
450 }
451
452 /*
453 * Support for new app package launching for Mac OS X.
454 * We are about to retry the execve() by changing the path to the
455 * interpreter name. Need to re-initialize the savedpath and
456 * savedpathlen. +1 for NULL.
457 */
458 savedpathlen = (cpnospace - execnamep + 1);
459 error = copystr(execnamep, savedpath,
460 savedpathlen, (size_t *)&savedpathlen);
461 if (error)
462 goto bad;
463
464 /* Save the name aside for future use */
465 execargsp = (vm_offset_t *)((char *)(execargs) + savedpathlen);
466
467 executingInterpreter= 1;
468 vput(vp);
469 nd.ni_cnd.cn_nameiop = LOOKUP;
470 nd.ni_cnd.cn_flags = (nd.ni_cnd.cn_flags & HASBUF) |
471 (FOLLOW | LOCKLEAF | SAVENAME);
472 nd.ni_segflg = UIO_SYSSPACE;
473 nd.ni_dirp = execnamep;
474 if ((error = namei(&nd)))
475 goto bad1;
476 vp = nd.ni_vp;
477 VOP_LEASE(vp, p, cred, LEASE_READ);
478 if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)))
479 goto bad;
480 goto again;
481 }
482
483 /*
484 * Collect arguments on "file" in swap space.
485 */
486 na = 0;
487 ne = 0;
488 nc = 0;
489 cc = 0;
490 /*
491 * Support for new app package launching for Mac OS X allocates
492 * the "path" at the begining.
493 * execargs get allocated after that
494 */
495 cp = (char *) execargsp; /* running pointer for copy */
496 /*
497 * size of execargs less sizeof "path",
498 * a pointer to "path" and a NULL poiter
499 */
500 cc = NCARGS - savedpathlen - 2*NBPW;
501 /*
502 * Copy arguments into file in argdev area.
503 */
504
505
506 /*
507 * If we have a fat file, find "our" executable.
508 */
509 if (is_fat) {
510 /*
511 * Look up our architecture in the fat file.
512 */
513 lret = fatfile_getarch_affinity(vp,(vm_offset_t)fat_header, &fat_arch,
514 (p->p_flag & P_AFFINITY));
515 if (lret != LOAD_SUCCESS) {
516 error = load_return_to_errno(lret);
517 goto bad;
518 }
519 /* Read the Mach-O header out of it */
520 error = vn_rdwr(UIO_READ, vp, (caddr_t)&exdata.mach_header,
521 sizeof (exdata.mach_header),
522 fat_arch.offset,
523 UIO_SYSSPACE, (IO_UNIT|IO_NODELOCKED), cred, &resid, p);
524
525 if (error) {
526 goto bad;
527 }
528
529 /* Did we read a complete header? */
530 if (resid) {
531 error = EBADEXEC;
532 goto bad;
533 }
534
535 /* Is what we found a Mach-O executable */
536 if ((mach_header->magic != MH_MAGIC) &&
537 (mach_header->magic != MH_CIGAM)) {
538 error = ENOEXEC;
539 goto bad;
540 }
541
542 arch_offset = fat_arch.offset;
543 arch_size = fat_arch.size;
544 } else {
545 /*
546 * Load the Mach-O file.
547 */
548 arch_offset = 0;
549 arch_size = (u_long)vattr.va_size;
550 }
551
552 if ( ! check_cpu_subtype(mach_header->cpusubtype) ) {
553 error = EBADARCH;
554 goto bad;
555 }
556
557 if (mach_header->magic == MH_CIGAM) {
558
559 int classicBinaryLen = nd.ni_cnd.cn_namelen;
560 if (classicBinaryLen > MAXCOMLEN)
561 classicBinaryLen = MAXCOMLEN;
562 bcopy((caddr_t)nd.ni_cnd.cn_nameptr,
563 (caddr_t)binaryWithClassicName,
564 (unsigned)classicBinaryLen);
565 binaryWithClassicName[classicBinaryLen] = '\0';
566 executingClassic = 1;
567
568 vput(vp); /* cleanup? */
569 nd.ni_cnd.cn_nameiop = LOOKUP;
570
571 nd.ni_cnd.cn_flags = (nd.ni_cnd.cn_flags & HASBUF) |
572 /* (FOLLOW | LOCKLEAF | SAVENAME) */
573 (LOCKLEAF | SAVENAME);
574 nd.ni_segflg = UIO_SYSSPACE;
575
576 nd.ni_dirp = classichandler;
577 if ((error = namei(&nd)) != 0) {
578 error = EBADARCH;
579 goto bad1;
580 }
581 vp = nd.ni_vp;
582
583 VOP_LEASE(vp,p,cred,LEASE_READ);
584 if ((error = VOP_GETATTR(vp,&vattr,p->p_ucred,p))) {
585 goto bad;
586 }
587 goto again;
588 }
589
590 if (uap->argp != NULL) {
591 /* geez -- why would argp ever be NULL, and why would we proceed? */
592
593 /* First, handle any argument massaging */
594 if (executingInterpreter && executingClassic) {
595 error = copyArgument(classichandler,UIO_SYSSPACE,&nc,&cp,&cc);
596 na++;
597 if (error) goto bad;
598
599 /* Now name the interpreter. */
600 error = copyArgument(savedpath,UIO_SYSSPACE,&nc,&cp,&cc);
601 na++;
602 if (error) goto bad;
603
604 /*
605 * if we're running an interpreter, as we'd be passing the
606 * command line executable as an argument to the interpreter already.
607 * Doing "execve("myShellScript","bogusName",arg1,arg2,...)
608 * probably shouldn't ever let bogusName be seen by the shell
609 * script.
610 */
611
612 if (cfarg[0]) {
613 error = copyArgument(cfarg,UIO_SYSSPACE,&nc,&cp,&cc);
614 na++;
615 if (error) goto bad;
616 }
617
618 char* originalExecutable = uap->fname;
619 error = copyArgument(originalExecutable,UIO_USERSPACE,&nc,&cp,&cc);
620 na++;
621 /* remove argv[0] b/c we've already placed it at */
622 /* this point */
623 uap->argp++;
624 if (error) goto bad;
625
626 /* and continue with rest of the arguments. */
627 } else if (executingClassic) {
628 error = copyArgument(classichandler,UIO_SYSSPACE,&nc,&cp,&cc);
629 na++;
630 if (error) goto bad;
631
632 char* originalExecutable = uap->fname;
633 error = copyArgument(originalExecutable,UIO_USERSPACE,&nc,&cp,&cc);
634 if (error) goto bad;
635 uap->argp++;
636 na++;
637
638 /* and rest of arguments continue as before. */
639 } else if (executingInterpreter) {
640 char *actualExecutable = nd.ni_cnd.cn_nameptr;
641 error = copyArgument(actualExecutable,UIO_SYSSPACE,&nc,&cp,&cc);
642 na++;
643 /* remove argv[0] b/c we just placed it in the arg list. */
644 uap->argp++;
645 if (error) goto bad;
646 /* Copy the argument in the interpreter first line if there
647 * was one.
648 */
649 if (cfarg[0]) {
650 error = copyArgument(cfarg,UIO_SYSSPACE,&nc,&cp,&cc);
651 na++;
652 if (error) goto bad;
653 }
654
655 /* copy the name of the file being interpreted, gotten from
656 * the structures passed in to execve.
657 */
658 error = copyArgument(uap->fname,UIO_USERSPACE,&nc,&cp,&cc);
659 na++;
660 }
661 /* Now, get rest of arguments */
662 while (uap->argp != NULL) {
663 char* userArgument = (char*)fuword((caddr_t) uap->argp);
664 uap->argp++;
665 if (userArgument == NULL) {
666 break;
667 } else if ((int)userArgument == -1) {
668 /* Um... why would it be -1? */
669 error = EFAULT;
670 goto bad;
671 }
672 error = copyArgument(userArgument, UIO_USERSPACE,&nc,&cp,&cc);
673 if (error) goto bad;
674 na++;
675 }
676 /* Now, get the environment */
677 while (uap->envp != NULL) {
678 char *userEnv = (char*) fuword((caddr_t) uap->envp);
679 uap->envp++;
680 if (userEnv == NULL) {
681 break;
682 } else if ((int)userEnv == -1) {
683 error = EFAULT;
684 goto bad;
685 }
686 error = copyArgument(userEnv,UIO_USERSPACE,&nc,&cp,&cc);
687 if (error) goto bad;
688 na++;
689 ne++;
690 }
691 }
692
693 /* make sure there are nulls are the end!! */
694 {
695 int cnt = 3;
696 char *mp = cp;
697
698 while ( cnt-- )
699 *mp++ = '\0';
700 }
701
702 /* and round up count of bytes written to next word. */
703 nc = (nc + NBPW-1) & ~(NBPW-1);
704
705 if (vattr.va_fsid == classichandler_fsid &&
706 vattr.va_fileid == classichandler_fileid) {
707 executingClassic = 1;
708 }
709
710 if (vfexec) {
711 kern_return_t result;
712
713 result = task_create_internal(task, FALSE, &new_task);
714 if (result != KERN_SUCCESS)
715 printf("execve: task_create failed. Code: 0x%x\n", result);
716 p->task = new_task;
717 set_bsdtask_info(new_task, p);
718 if (p->p_nice != 0)
719 resetpriority(p);
720 task = new_task;
721 map = get_task_map(new_task);
722 result = thread_create(new_task, &thr_act);
723 if (result != KERN_SUCCESS)
724 printf("execve: thread_create failed. Code: 0x%x\n", result);
725 uthread = get_bsdthread_info(thr_act);
726 } else {
727 map = VM_MAP_NULL;
728 }
729
730 /*
731 * Load the Mach-O file.
732 */
733 VOP_UNLOCK(vp, 0, p); /* XXX */
734 if(ws_cache_name) {
735 tws_handle_startup_file(task, cred->cr_uid,
736 ws_cache_name, vp, &clean_regions);
737 }
738
739 vm_get_shared_region(task, &initial_region);
740 int parentIsClassic = (p->p_flag & P_CLASSIC);
741 struct vnode *rootDir = p->p_fd->fd_rdir;
742
743 if ((parentIsClassic && !executingClassic) ||
744 (!parentIsClassic && executingClassic)) {
745 shared_region = lookup_default_shared_region(
746 (int)rootDir,
747 (executingClassic ?
748 CPU_TYPE_POWERPC :
749 machine_slot[cpu_number()].cpu_type));
750 if (shared_region == NULL) {
751 shared_region_mapping_t old_region;
752 shared_region_mapping_t new_region;
753 vm_get_shared_region(current_task(), &old_region);
754 /* grrrr... this sets current_task(), not task
755 * -- they're different (usually)
756 */
757 shared_file_boot_time_init(
758 (int)rootDir,
759 (executingClassic ?
760 CPU_TYPE_POWERPC :
761 machine_slot[cpu_number()].cpu_type));
762 if ( current_task() != task ) {
763 vm_get_shared_region(current_task(),&new_region);
764 vm_set_shared_region(task,new_region);
765 vm_set_shared_region(current_task(),old_region);
766 }
767 } else {
768 vm_set_shared_region(task, shared_region);
769 }
770 shared_region_mapping_dealloc(initial_region);
771 }
772
773 lret = load_machfile(vp, mach_header, arch_offset,
774 arch_size, &load_result, thr_act, map, clean_regions);
775
776 if (lret != LOAD_SUCCESS) {
777 error = load_return_to_errno(lret);
778 vrele(vp);
779 vp = NULL;
780 goto badtoolate;
781 }
782
783 /* load_machfile() maps the vnode */
784 ubc_map(vp);
785
786 /*
787 * deal with set[ug]id.
788 */
789 p->p_flag &= ~P_SUGID;
790 if (((origvattr.va_mode & VSUID) != 0 &&
791 p->p_ucred->cr_uid != origvattr.va_uid)
792 || (origvattr.va_mode & VSGID) != 0 &&
793 p->p_ucred->cr_gid != origvattr.va_gid) {
794 p->p_ucred = crcopy(cred);
795 #if KTRACE
796 /*
797 * If process is being ktraced, turn off - unless
798 * root set it.
799 */
800 if (p->p_tracep && !(p->p_traceflag & KTRFAC_ROOT)) {
801 struct vnode *tvp = p->p_tracep;
802 p->p_tracep = NULL;
803 p->p_traceflag = 0;
804
805 if (UBCINFOEXISTS(tvp))
806 ubc_rele(tvp);
807 vrele(tvp);
808 }
809 #endif
810 if (origvattr.va_mode & VSUID)
811 p->p_ucred->cr_uid = origvattr.va_uid;
812 if (origvattr.va_mode & VSGID)
813 p->p_ucred->cr_gid = origvattr.va_gid;
814
815 /*
816 * Have mach reset the task port. We don't want
817 * anyone who had the task port before a setuid
818 * exec to be able to access/control the task
819 * after.
820 */
821 ipc_task_reset(task);
822
823 p->p_flag |= P_SUGID;
824
825 /* Radar 2261856; setuid security hole fix */
826 /* Patch from OpenBSD: A. Ramesh */
827 /*
828 * XXX For setuid processes, attempt to ensure that
829 * stdin, stdout, and stderr are already allocated.
830 * We do not want userland to accidentally allocate
831 * descriptors in this range which has implied meaning
832 * to libc.
833 */
834 for (i = 0; i < 3; i++) {
835 extern struct fileops vnops;
836 struct nameidata nd1;
837 struct file *fp;
838 int indx;
839
840 if (p->p_fd->fd_ofiles[i] == NULL) {
841 if ((error = falloc(p, &fp, &indx)) != 0)
842 continue;
843 NDINIT(&nd1, LOOKUP, FOLLOW, UIO_SYSSPACE,
844 "/dev/null", p);
845 if ((error = vn_open(&nd1, FREAD, 0)) != 0) {
846 ffree(fp);
847 p->p_fd->fd_ofiles[indx] = NULL;
848 break;
849 }
850 fp->f_flag = FREAD;
851 fp->f_type = DTYPE_VNODE;
852 fp->f_ops = &vnops;
853 fp->f_data = (caddr_t)nd1.ni_vp;
854 VOP_UNLOCK(nd1.ni_vp, 0, p);
855 }
856 }
857 }
858 p->p_cred->p_svuid = p->p_ucred->cr_uid;
859 p->p_cred->p_svgid = p->p_ucred->cr_gid;
860 set_security_token(p);
861
862 KNOTE(&p->p_klist, NOTE_EXEC);
863
864 if (!vfexec && (p->p_flag & P_TRACED))
865 psignal(p, SIGTRAP);
866
867 if (error) {
868 vrele(vp);
869 vp = NULL;
870 goto badtoolate;
871 }
872 VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY, p); /* XXX */
873 vput(vp);
874 vp = NULL;
875
876 if (load_result.unixproc &&
877 create_unix_stack(get_task_map(task),
878 load_result.user_stack, load_result.customstack, p)) {
879 error = load_return_to_errno(LOAD_NOSPACE);
880 goto badtoolate;
881 }
882
883 if (vfexec) {
884 uthread->uu_ar0 = (void *)get_user_regs(thr_act);
885 }
886
887 /*
888 * Copy back arglist if necessary.
889 */
890
891
892 ucp = (int)p->user_stack;
893 if (vfexec) {
894 old_map = vm_map_switch(get_task_map(task));
895 }
896 if (load_result.unixproc) {
897 int pathptr;
898
899 ucp = ucp - nc - NBPW; /* begining of the STRING AREA */
900
901 /*
902 * Support for new app package launching for Mac OS X allocates
903 * the "path" at the begining of the execargs buffer.
904 * copy it just before the string area.
905 */
906 len = 0;
907 pathptr = ucp - ((savedpathlen + NBPW-1) & ~(NBPW-1));
908 error = copyoutstr(savedpath, (caddr_t)pathptr,
909 (unsigned)savedpathlen, (size_t *)&len);
910 savedpathlen = (savedpathlen + NBPW-1) & ~(NBPW-1);
911
912 if (error) {
913 if (vfexec)
914 vm_map_switch(old_map);
915 goto badtoolate;
916 }
917
918 /*
919 * Record the size of the arguments area so that
920 * sysctl_procargs() can return the argument area without having
921 * to parse the arguments.
922 */
923 p->p_argslen = (int)p->user_stack - pathptr;
924 p->p_argc = na - ne; /* save argc for sysctl_procargs() */
925
926 /* Save a NULL pointer below it */
927 (void) suword((caddr_t)(pathptr - NBPW), 0);
928
929 /* Save the pointer to "path" just below it */
930 (void) suword((caddr_t)(pathptr - 2*NBPW), pathptr);
931
932 /*
933 * na includes arg[] and env[].
934 * NBPW for 2 NULL one each ofter arg[argc -1] and env[n]
935 * NBPW for argc
936 * skip over saved path, NBPW for pointer to path,
937 * and NBPW for the NULL after pointer to path.
938 */
939 ap = ucp - na*NBPW - 3*NBPW - savedpathlen - 2*NBPW;
940 #if defined(ppc)
941 thread_setuserstack(thr_act, ap); /* Set the stack */
942 #else
943 uthread->uu_ar0[SP] = ap;
944 #endif
945 (void) suword((caddr_t)ap, na-ne); /* argc */
946 nc = 0;
947 cc = 0;
948
949 cp = (char *) execargsp;
950 cc = NCARGS - savedpathlen - 2*NBPW;
951 ps.ps_argvstr = (char *)ucp; /* first argv string */
952 ps.ps_nargvstr = na - ne; /* argc */
953 for (;;) {
954 ap += NBPW;
955 if (na == ne) {
956 (void) suword((caddr_t)ap, 0);
957 ap += NBPW;
958 ps.ps_envstr = (char *)ucp;
959 ps.ps_nenvstr = ne;
960 }
961 if (--na < 0)
962 break;
963 (void) suword((caddr_t)ap, ucp);
964 do {
965 error = copyoutstr(cp, (caddr_t)ucp,
966 (unsigned)cc, (size_t *)&len);
967 ucp += len;
968 cp += len;
969 nc += len;
970 cc -= len;
971 } while (error == ENAMETOOLONG);
972 if (error == EFAULT)
973 break; /* bad stack - user's problem */
974 }
975 (void) suword((caddr_t)ap, 0);
976 }
977
978 if (load_result.dynlinker) {
979 #if defined(ppc)
980 ap = thread_adjuserstack(thr_act, -4); /* Adjust the stack */
981 #else
982 ap = uthread->uu_ar0[SP] -= 4;
983 #endif
984 (void) suword((caddr_t)ap, load_result.mach_header);
985 }
986
987 if (vfexec) {
988 vm_map_switch(old_map);
989 }
990 #if defined(ppc)
991 thread_setentrypoint(thr_act, load_result.entry_point); /* Set the entry point */
992 #elif defined(i386)
993 uthread->uu_ar0[PC] = load_result.entry_point;
994 #else
995 #error architecture not implemented!
996 #endif
997
998 /* Stop profiling */
999 stopprofclock(p);
1000
1001 /*
1002 * Reset signal state.
1003 */
1004 execsigs(p, thr_act);
1005
1006 /*
1007 * Close file descriptors
1008 * which specify close-on-exec.
1009 */
1010 fdexec(p);
1011
1012 /*
1013 * need to cancel async IO requests that can be cancelled and wait for those
1014 * already active. MAY BLOCK!
1015 */
1016 _aio_exec( p );
1017
1018 /* FIXME: Till vmspace inherit is fixed: */
1019 if (!vfexec && p->vm_shm)
1020 shmexec(p);
1021 /* Clean up the semaphores */
1022 semexit(p);
1023
1024 /*
1025 * Remember file name for accounting.
1026 */
1027 p->p_acflag &= ~AFORK;
1028 /* If the translated name isn't NULL, then we want to use
1029 * that translated name as the name we show as the "real" name.
1030 * Otherwise, use the name passed into exec.
1031 */
1032 if (0 != binaryWithClassicName[0]) {
1033 bcopy((caddr_t)binaryWithClassicName, (caddr_t)p->p_comm,
1034 sizeof(binaryWithClassicName));
1035 } else {
1036 if (nd.ni_cnd.cn_namelen > MAXCOMLEN)
1037 nd.ni_cnd.cn_namelen = MAXCOMLEN;
1038 bcopy((caddr_t)nd.ni_cnd.cn_nameptr, (caddr_t)p->p_comm,
1039 (unsigned)nd.ni_cnd.cn_namelen);
1040 p->p_comm[nd.ni_cnd.cn_namelen] = '\0';
1041 }
1042
1043 {
1044 /* This is for kdebug */
1045 long dbg_arg1, dbg_arg2, dbg_arg3, dbg_arg4;
1046
1047 /* Collect the pathname for tracing */
1048 kdbg_trace_string(p, &dbg_arg1, &dbg_arg2, &dbg_arg3, &dbg_arg4);
1049
1050
1051
1052 if (vfexec)
1053 {
1054 KERNEL_DEBUG_CONSTANT1((TRACEDBG_CODE(DBG_TRACE_DATA, 2)) | DBG_FUNC_NONE,
1055 p->p_pid ,0,0,0, (unsigned int)thr_act);
1056 KERNEL_DEBUG_CONSTANT1((TRACEDBG_CODE(DBG_TRACE_STRING, 2)) | DBG_FUNC_NONE,
1057 dbg_arg1, dbg_arg2, dbg_arg3, dbg_arg4, (unsigned int)thr_act);
1058 }
1059 else
1060 {
1061 KERNEL_DEBUG_CONSTANT((TRACEDBG_CODE(DBG_TRACE_DATA, 2)) | DBG_FUNC_NONE,
1062 p->p_pid ,0,0,0,0);
1063 KERNEL_DEBUG_CONSTANT((TRACEDBG_CODE(DBG_TRACE_STRING, 2)) | DBG_FUNC_NONE,
1064 dbg_arg1, dbg_arg2, dbg_arg3, dbg_arg4, 0);
1065 }
1066 }
1067
1068 if (executingClassic)
1069 p->p_flag |= P_CLASSIC | P_AFFINITY;
1070 else
1071 p->p_flag &= ~P_CLASSIC;
1072
1073 /*
1074 * mark as execed, wakeup the process that vforked (if any) and tell
1075 * it that it now has it's own resources back
1076 */
1077 p->p_flag |= P_EXEC;
1078 if (p->p_pptr && (p->p_flag & P_PPWAIT)) {
1079 p->p_flag &= ~P_PPWAIT;
1080 wakeup((caddr_t)p->p_pptr);
1081 }
1082
1083 if (vfexec && (p->p_flag & P_TRACED)) {
1084 psignal_vfork(p, new_task, thr_act, SIGTRAP);
1085 }
1086
1087 badtoolate:
1088 if (vfexec) {
1089 task_deallocate(new_task);
1090 act_deallocate(thr_act);
1091 if (error)
1092 error = 0;
1093 }
1094 bad:
1095 FREE_ZONE(nd.ni_cnd.cn_pnbuf, nd.ni_cnd.cn_pnlen, M_NAMEI);
1096 if (vp)
1097 vput(vp);
1098 bad1:
1099 if (execargs)
1100 execargs_free(execargs);
1101 if (!error && vfexec) {
1102 vfork_return(current_act(), p->p_pptr, p, retval);
1103 (void) thread_resume(thr_act);
1104 return(0);
1105 }
1106 return(error);
1107 }
1108
1109
1110 #define unix_stack_size(p) (p->p_rlimit[RLIMIT_STACK].rlim_cur)
1111
1112 kern_return_t
1113 create_unix_stack(map, user_stack, customstack, p)
1114 vm_map_t map;
1115 vm_offset_t user_stack;
1116 int customstack;
1117 struct proc *p;
1118 {
1119 vm_size_t size;
1120 vm_offset_t addr;
1121
1122 p->user_stack = (caddr_t)user_stack;
1123 if (!customstack) {
1124 size = round_page_64(unix_stack_size(p));
1125 addr = trunc_page_32(user_stack - size);
1126 return (vm_allocate(map, &addr, size,
1127 VM_MAKE_TAG(VM_MEMORY_STACK) | FALSE));
1128 } else
1129 return(KERN_SUCCESS);
1130 }
1131
1132 #include <sys/reboot.h>
1133
1134 char init_program_name[128] = "/sbin/mach_init\0";
1135
1136 char init_args[128] = "";
1137
1138 struct execve_args init_exec_args;
1139 int init_attempts = 0;
1140
1141
1142 void
1143 load_init_program(p)
1144 struct proc *p;
1145 {
1146 vm_offset_t init_addr;
1147 int *old_ap;
1148 char *argv[3];
1149 int error;
1150 register_t retval[2];
1151 struct uthread * ut;
1152
1153 error = 0;
1154
1155 /* init_args are copied in string form directly from bootstrap */
1156
1157 do {
1158 if (boothowto & RB_INITNAME) {
1159 printf("init program? ");
1160 #if FIXME /* [ */
1161 gets(init_program_name, init_program_name);
1162 #endif /* FIXME ] */
1163 }
1164
1165 if (error && ((boothowto & RB_INITNAME) == 0) &&
1166 (init_attempts == 1)) {
1167 static char other_init[] = "/etc/mach_init";
1168 printf("Load of %s, errno %d, trying %s\n",
1169 init_program_name, error, other_init);
1170 error = 0;
1171 bcopy(other_init, init_program_name,
1172 sizeof(other_init));
1173 }
1174
1175 init_attempts++;
1176
1177 if (error) {
1178 printf("Load of %s failed, errno %d\n",
1179 init_program_name, error);
1180 error = 0;
1181 boothowto |= RB_INITNAME;
1182 continue;
1183 }
1184
1185 /*
1186 * Copy out program name.
1187 */
1188
1189 init_addr = VM_MIN_ADDRESS;
1190 (void) vm_allocate(current_map(), &init_addr,
1191 PAGE_SIZE, TRUE);
1192 if (init_addr == 0)
1193 init_addr++;
1194 (void) copyout((caddr_t) init_program_name,
1195 (caddr_t) (init_addr),
1196 (unsigned) sizeof(init_program_name)+1);
1197
1198 argv[0] = (char *) init_addr;
1199 init_addr += sizeof(init_program_name);
1200 init_addr = (vm_offset_t)ROUND_PTR(char, init_addr);
1201
1202 /*
1203 * Put out first (and only) argument, similarly.
1204 * Assumes everything fits in a page as allocated
1205 * above.
1206 */
1207
1208 (void) copyout((caddr_t) init_args,
1209 (caddr_t) (init_addr),
1210 (unsigned) sizeof(init_args));
1211
1212 argv[1] = (char *) init_addr;
1213 init_addr += sizeof(init_args);
1214 init_addr = (vm_offset_t)ROUND_PTR(char, init_addr);
1215
1216 /*
1217 * Null-end the argument list
1218 */
1219
1220 argv[2] = (char *) 0;
1221
1222 /*
1223 * Copy out the argument list.
1224 */
1225
1226 (void) copyout((caddr_t) argv,
1227 (caddr_t) (init_addr),
1228 (unsigned) sizeof(argv));
1229
1230 /*
1231 * Set up argument block for fake call to execve.
1232 */
1233
1234 init_exec_args.fname = argv[0];
1235 init_exec_args.argp = (char **) init_addr;
1236 init_exec_args.envp = 0;
1237
1238 /* So that mach_init task
1239 * is set with uid,gid 0 token
1240 */
1241 set_security_token(p);
1242
1243 error = execve(p,&init_exec_args,retval);
1244 } while (error);
1245 }
1246
1247 /*
1248 * Convert a load_return_t to an errno.
1249 */
1250 static int
1251 load_return_to_errno(load_return_t lrtn)
1252 {
1253 switch (lrtn) {
1254 case LOAD_SUCCESS:
1255 return 0;
1256 case LOAD_BADARCH:
1257 return EBADARCH;
1258 case LOAD_BADMACHO:
1259 return EBADMACHO;
1260 case LOAD_SHLIB:
1261 return ESHLIBVERS;
1262 case LOAD_NOSPACE:
1263 case LOAD_RESOURCE:
1264 return ENOMEM;
1265 case LOAD_PROTECT:
1266 return EACCES;
1267 case LOAD_ENOENT:
1268 return ENOENT;
1269 case LOAD_IOERROR:
1270 return EIO;
1271 case LOAD_FAILURE:
1272 default:
1273 return EBADEXEC;
1274 }
1275 }
1276
1277 /*
1278 * exec_check_access()
1279 */
1280 int
1281 check_exec_access(p, vp, vap)
1282 struct proc *p;
1283 struct vnode *vp;
1284 struct vattr *vap;
1285 {
1286 int flag;
1287 int error;
1288
1289 if (error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p))
1290 return (error);
1291 flag = p->p_flag;
1292 if (flag & P_TRACED) {
1293 if (error = VOP_ACCESS(vp, VREAD, p->p_ucred, p))
1294 return (error);
1295 }
1296 if (vp->v_type != VREG ||
1297 (vap->va_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0)
1298 return (EACCES);
1299 return (0);
1300 }
1301
1302 #include <mach/mach_types.h>
1303 #include <mach/vm_prot.h>
1304 #include <mach/semaphore.h>
1305 #include <mach/sync_policy.h>
1306 #include <kern/clock.h>
1307 #include <mach/kern_return.h>
1308
1309 extern semaphore_t execve_semaphore;
1310
1311 static int
1312 execargs_alloc(addrp)
1313 vm_offset_t *addrp;
1314 {
1315 kern_return_t kret;
1316
1317 kret = semaphore_wait(execve_semaphore);
1318 if (kret != KERN_SUCCESS)
1319 switch (kret) {
1320 default:
1321 return (EINVAL);
1322 case KERN_INVALID_ADDRESS:
1323 case KERN_PROTECTION_FAILURE:
1324 return (EACCES);
1325 case KERN_ABORTED:
1326 case KERN_OPERATION_TIMED_OUT:
1327 return (EINTR);
1328 }
1329
1330 kret = kmem_alloc_pageable(bsd_pageable_map, addrp, NCARGS);
1331 if (kret != KERN_SUCCESS) {
1332 semaphore_signal(execve_semaphore);
1333 return (ENOMEM);
1334 }
1335 return (0);
1336 }
1337
1338 static int
1339 execargs_free(addr)
1340 vm_offset_t addr;
1341 {
1342 kern_return_t kret;
1343
1344 kmem_free(bsd_pageable_map, addr, NCARGS);
1345
1346 kret = semaphore_signal(execve_semaphore);
1347 switch (kret) {
1348 case KERN_INVALID_ADDRESS:
1349 case KERN_PROTECTION_FAILURE:
1350 return (EINVAL);
1351 case KERN_ABORTED:
1352 case KERN_OPERATION_TIMED_OUT:
1353 return (EINTR);
1354 case KERN_SUCCESS:
1355 return(0);
1356 default:
1357 return (EINVAL);
1358 }
1359 }