|
|
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.