Annotation of kernel/bsd/kern/kern_exec.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.