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