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

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

unix.superglobalmegacorp.com

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