Annotation of XNU/bsd/kern/kern_exec.c, revision 1.1.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.