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

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

unix.superglobalmegacorp.com

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