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

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: 

unix.superglobalmegacorp.com

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