Annotation of Net2/kern/kern_execve.c, revision 1.1.1.3

1.1       root        1: /*
1.1.1.2   root        2:  * Copyright (c) 1989, 1990, 1991, 1992 William F. Jolitz, TeleMuse
                      3:  * All rights reserved.
1.1       root        4:  *
1.1.1.2   root        5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. All advertising materials mentioning features or use of this software
                     14:  *    must display the following acknowledgement:
                     15:  *     This software is a component of "386BSD" developed by 
                     16:  *     William F. Jolitz, TeleMuse.
                     17:  * 4. Neither the name of the developer nor the name "386BSD"
                     18:  *    may be used to endorse or promote products derived from this software
                     19:  *    without specific prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ 
                     22:  * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS 
                     23:  * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT. 
                     24:  * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT 
                     25:  * NOT MAKE USE OF THIS WORK.
                     26:  *
                     27:  * FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED
                     28:  * BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN 
                     29:  * REFERENCES SUCH AS THE  "PORTING UNIX TO THE 386" SERIES 
                     30:  * (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING 
                     31:  * JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND 
                     32:  * LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE 
                     33:  * ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS 
                     34:  * OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992.
                     35:  *
                     36:  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND
                     37:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     38:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     39:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE DEVELOPER BE LIABLE
                     40:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     41:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     42:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     43:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     44:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     45:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     46:  * SUCH DAMAGE.
1.1       root       47:  *
                     48:  * This procedure implements a minimal program execution facility for
                     49:  * 386BSD. It interfaces to the BSD kernel as the execve system call.
                     50:  * Significant limitations and lack of compatiblity with POSIX are
                     51:  * present with this version, to make its basic operation more clear.
                     52:  *
1.1.1.3 ! root       53:  * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
        !            54:  * --------------------         -----   ----------------------
        !            55:  * CURRENT PATCH LEVEL:         3       00069
        !            56:  * --------------------         -----   ----------------------
        !            57:  *
        !            58:  * 05 Aug 92   Paul Kranenburg         Fixed #! as a magic number
        !            59:  * 29 Jul 92   Mark Tinguely           Fixed execute permission enforcement
        !            60:  * 15 Aug 92    Terry Lambert           Fixed CMOS RAM size bug
        !            61:  * 12 Dec 92   Julians Elischer        Place argc into user address space
        !            62:  *                                     correctly
1.1       root       63:  */
                     64: 
                     65: #include "param.h"
                     66: #include "systm.h"
1.1.1.2   root       67: #include "signalvar.h"
                     68: #include "resourcevar.h"
1.1       root       69: #include "proc.h"
                     70: #include "mount.h"
                     71: #include "namei.h"
                     72: #include "vnode.h"
                     73: #include "file.h"
                     74: #include "exec.h"
                     75: #include "stat.h"
                     76: #include "wait.h"
                     77: #include "mman.h"
1.1.1.2   root       78: #include "malloc.h"
1.1       root       79: 
                     80: #include "vm/vm.h"
                     81: #include "vm/vm_param.h"
                     82: #include "vm/vm_map.h"
                     83: #include "vm/vm_kern.h"
                     84: 
                     85: #include "machine/reg.h"
                     86: 
1.1.1.2   root       87: extern int dostacklimits;
                     88: #define        copyinoutstr    copyinstr
1.1       root       89: 
                     90: /*
1.1.1.2   root       91:  * execve() system call.
1.1       root       92:  */
                     93: 
                     94: /* ARGSUSED */
                     95: execve(p, uap, retval)
                     96:        struct proc *p;
                     97:        register struct args {
                     98:                char    *fname;
                     99:                char    **argp;
                    100:                char    **envp;
                    101:        } *uap;
                    102:        int *retval;
                    103: {
                    104:        register struct nameidata *ndp;
                    105:        struct nameidata nd;
1.1.1.2   root      106:        char **argbuf, **argbufp, *stringbuf, *stringbufp;
                    107:        char **vectp, *ep;
                    108:        int needsenv, limitonargs, stringlen, addr, size, len,
                    109:                rv, amt, argc, tsize, dsize, bsize, cnt, foff;
                    110:        struct vattr attr;
1.1       root      111:        struct vmspace *vs;
1.1.1.2   root      112:        caddr_t newframe;
1.1.1.3 ! root      113:        char shellname[MAXINTERP];                      /* 05 Aug 92*/
        !           114:        union {
        !           115:                char    ex_shell[MAXINTERP];    /* #! and interpreter name */
        !           116:                struct  exec ex_hdr;
        !           117:        } exdata;
        !           118:        int indir = 0;
1.1       root      119: 
                    120:        /*
                    121:         * Step 1. Lookup filename to see if we have something to execute.
                    122:         */
                    123:        ndp = &nd;
                    124:        ndp->ni_segflg = UIO_USERSPACE;
                    125:        ndp->ni_dirp = uap->fname;
                    126: 
1.1.1.3 ! root      127: again:                                                 /* 05 Aug 92*/
        !           128:        ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW | SAVENAME;
        !           129: 
1.1       root      130:        /* is it there? */
                    131:        if (rv = namei(ndp, p))
                    132:                return (rv);
                    133: 
1.1.1.2   root      134:        /* does it have any attributes? */
                    135:        rv = VOP_GETATTR(ndp->ni_vp, &attr, p->p_ucred, p);
1.1       root      136:        if (rv)
                    137:                goto exec_fail;
1.1.1.2   root      138: 
1.1.1.3 ! root      139:        if (ndp->ni_vp->v_mount->mnt_flag & MNT_NOEXEC) { /* no exec on fs ?*/
        !           140:                rv = EACCES;
        !           141:                goto exec_fail;
        !           142:        }
        !           143: 
1.1.1.2   root      144:        /* is it executable, and a regular file? */
1.1.1.3 ! root      145:        if ((ndp->ni_vp->v_mount->mnt_flag & MNT_NOEXEC) ||     /* 29 Jul 92*/
        !           146:                (VOP_ACCESS(ndp->ni_vp, VEXEC, p->p_ucred, p)) ||
        !           147:                ((attr.va_mode & 0111) == 0) ||
        !           148:                (attr.va_type != VREG)) {
1.1.1.2   root      149:                rv = EACCES;
1.1       root      150:                goto exec_fail;
1.1.1.2   root      151:        }
1.1       root      152: 
                    153:        /*
                    154:         * Step 2. Does the file contain a format we can
                    155:         * understand and execute
1.1.1.3 ! root      156:         *
        !           157:         * XXX 05 Aug 92
        !           158:         * Read in first few bytes of file for segment sizes, magic number:
        !           159:         *      ZMAGIC = demand paged RO text
        !           160:         * Also an ASCII line beginning with #! is
        !           161:         * the file name of a ``shell'' and arguments may be prepended
        !           162:         * to the argument list if given here.
1.1       root      163:         */
1.1.1.3 ! root      164:        exdata.ex_shell[0] = '\0';      /* for zero length files */
        !           165: 
        !           166:        rv = vn_rdwr(UIO_READ, ndp->ni_vp, (caddr_t)&exdata, sizeof(exdata),
1.1       root      167:                0, UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &amt, p);
                    168: 
                    169:        /* big enough to hold a header? */
                    170:        if (rv)
                    171:                goto exec_fail;
1.1.1.3 ! root      172: 
1.1.1.2   root      173:        /* ... that we recognize? */
1.1       root      174:        rv = ENOEXEC;
1.1.1.3 ! root      175:        if (exdata.ex_hdr.a_magic != ZMAGIC) {
        !           176:                char *cp, *sp;
        !           177: 
        !           178:                if (exdata.ex_shell[0] != '#' ||
        !           179:                    exdata.ex_shell[1] != '!' || indir) {
        !           180:                        rv = ENOEXEC;
        !           181:                        goto exec_fail;
        !           182:                }
        !           183:                for (cp = &exdata.ex_shell[2];; ++cp) {
        !           184:                        if (cp >= &exdata.ex_shell[MAXINTERP]) {
        !           185:                                rv = ENOEXEC;
        !           186:                                goto exec_fail;
        !           187:                        }
        !           188:                        if (*cp == '\n') {
        !           189:                                *cp = '\0';
        !           190:                                break;
        !           191:                        }
        !           192:                        if (*cp == '\t')
        !           193:                                *cp = ' ';
        !           194:                }
        !           195:                cp = &exdata.ex_shell[2];       /* get shell interpreter name */
        !           196:                while (*cp == ' ')
        !           197:                        cp++;
        !           198: 
        !           199:                sp = shellname;
        !           200:                while (*cp && *cp != ' ')
        !           201:                        *sp++ = *cp++;
        !           202:                *sp = '\0';
        !           203: 
        !           204:                indir = 1;              /* indicate this is a script file */
        !           205:                vput(ndp->ni_vp);
        !           206:                FREE(ndp->ni_pnbuf, M_NAMEI);
        !           207: 
        !           208:                ndp->ni_dirp = shellname;       /* find shell interpreter */
        !           209:                ndp->ni_segflg = UIO_SYSSPACE;
        !           210:                goto again;
        !           211:        }
1.1       root      212: 
                    213:        /* sanity check  "ain't not such thing as a sanity clause" -groucho */
1.1.1.2   root      214:        rv = ENOMEM;
1.1.1.3 ! root      215:        if (/*exdata.ex_hdr.a_text == 0 || */ exdata.ex_hdr.a_text > MAXTSIZ ||
        !           216:            exdata.ex_hdr.a_text % NBPG || exdata.ex_hdr.a_text > attr.va_size)
1.1       root      217:                goto exec_fail;
                    218: 
1.1.1.3 ! root      219:        if (exdata.ex_hdr.a_data == 0 || exdata.ex_hdr.a_data > DFLDSIZ
        !           220:                || exdata.ex_hdr.a_data > attr.va_size
        !           221:                || exdata.ex_hdr.a_data + exdata.ex_hdr.a_text > attr.va_size)
1.1       root      222:                goto exec_fail;
                    223: 
1.1.1.3 ! root      224:        if (exdata.ex_hdr.a_bss > MAXDSIZ)
1.1       root      225:                goto exec_fail;
                    226:        
1.1.1.3 ! root      227:        if (exdata.ex_hdr.a_text + exdata.ex_hdr.a_data + exdata.ex_hdr.a_bss > MAXTSIZ + MAXDSIZ)
1.1       root      228:                goto exec_fail;
1.1.1.2   root      229: 
1.1.1.3 ! root      230:        if (exdata.ex_hdr.a_data + exdata.ex_hdr.a_bss > p->p_rlimit[RLIMIT_DATA].rlim_cur)
1.1.1.2   root      231:                goto exec_fail;
                    232: 
1.1.1.3 ! root      233:        if (exdata.ex_hdr.a_entry > exdata.ex_hdr.a_text + exdata.ex_hdr.a_data)
1.1.1.2   root      234:                goto exec_fail;
1.1       root      235:        
                    236:        /*
                    237:         * Step 3.  File and header are valid. Now, dig out the strings
                    238:         * out of the old process image.
                    239:         */
                    240: 
1.1.1.2   root      241:        /*
                    242:         * We implement a single-pass algorithm that builds a new stack
                    243:         * frame within the address space of the "old" process image,
                    244:         * avoiding the second pass entirely. Thus, the new frame is
                    245:         * in position to be run. This consumes much virtual address space,
                    246:         * and two pages more of 'real' memory, such are the costs.
                    247:         * [Also, note the cache wipe that's avoided!]
1.1       root      248:         */
                    249: 
1.1.1.2   root      250:        /* create anonymous memory region for new stack */
                    251:        vs = p->p_vmspace;
                    252:        if ((unsigned)vs->vm_maxsaddr + MAXSSIZ < USRSTACK)
                    253:                newframe = (caddr_t) USRSTACK - MAXSSIZ;
                    254:        else
                    255:                vs->vm_maxsaddr = newframe = (caddr_t) USRSTACK - 2*MAXSSIZ;
                    256: 
                    257:        /* don't do stack limit checking on traps temporarily XXX*/
                    258:        dostacklimits = 0;
                    259: 
                    260:        rv = vm_allocate(&vs->vm_map, &newframe, MAXSSIZ, FALSE);
                    261:        if (rv) goto exec_fail;
                    262: 
1.1       root      263:        /* allocate string buffer and arg buffer */
1.1.1.2   root      264:        argbuf = (char **) (newframe + MAXSSIZ - 3*ARG_MAX);
                    265:        stringbuf = stringbufp = ((char *)argbuf) + 2*ARG_MAX;
                    266:        argbufp = argbuf;
1.1       root      267: 
                    268:        /* first, do args */
                    269:        vectp = uap->argp;
1.1.1.2   root      270:        needsenv = 1;
                    271:        limitonargs = ARG_MAX;
                    272:        cnt = 0;
1.1       root      273: 
1.1.1.3 ! root      274:        /* first, do (shell name if any then) args */
        !           275:        if (indir)  {
        !           276:                ep = shellname;
        !           277: twice:
        !           278:                if (ep) {
        !           279:                        /* did we outgrow initial argbuf, if so, die */
        !           280:                        if (argbufp >= (char **)stringbuf) {
        !           281:                                rv = E2BIG;
        !           282:                                goto exec_dealloc;
        !           283:                        }
        !           284: 
        !           285:                        if (rv = copyoutstr(ep, stringbufp,
        !           286:                                (u_int)limitonargs, (u_int *)&stringlen)) {
        !           287:                                if (rv == ENAMETOOLONG)
        !           288:                                        rv = E2BIG;
        !           289:                                goto exec_dealloc;
        !           290:                        }
        !           291:                        suword(argbufp++, (int)stringbufp);
        !           292:                        cnt++;
        !           293:                        stringbufp += stringlen;
        !           294:                        limitonargs -= stringlen;
        !           295:                }
        !           296: 
        !           297:                if (indir) {
        !           298:                        indir = 0;
        !           299:                        /* orginal executable is 1st argument with scripts */
        !           300:                        ep = uap->fname;
        !           301:                        goto twice;
        !           302:                }
        !           303:                /* terminate in case no more args to script */
        !           304:                suword(argbufp, 0);
        !           305:                if (vectp = uap->argp) vectp++; /* manually doing the first
        !           306:                                                   argument with scripts */
        !           307:        }
        !           308: 
1.1       root      309: do_env_as_well:
                    310:        if(vectp == 0) goto dont_bother;
1.1.1.2   root      311: 
                    312:        /* for each envp, copy in string */
1.1       root      313:        do {
                    314:                /* did we outgrow initial argbuf, if so, die */
1.1.1.2   root      315:                if (argbufp == (char **)stringbuf) {
                    316:                        rv = E2BIG;
                    317:                        goto exec_dealloc;
                    318:                }
1.1       root      319:        
                    320:                /* get an string pointer */
                    321:                ep = (char *)fuword(vectp++);
                    322:                if (ep == (char *)-1) {
                    323:                        rv = EFAULT;
1.1.1.2   root      324:                        goto exec_dealloc;
1.1       root      325:                }
                    326: 
1.1.1.2   root      327:                /* if not a null pointer, copy string */
1.1       root      328:                if (ep) {
1.1.1.2   root      329:                        if (rv = copyinoutstr(ep, stringbufp,
                    330:                                (u_int)limitonargs, (u_int *) &stringlen)) {
                    331:                                if (rv == ENAMETOOLONG)
                    332:                                        rv = E2BIG;
                    333:                                goto exec_dealloc;
                    334:                        }
                    335:                        suword(argbufp++, (int)stringbufp);
1.1       root      336:                        cnt++;
1.1.1.2   root      337:                        stringbufp += stringlen;
                    338:                        limitonargs -= stringlen;
1.1       root      339:                } else {
1.1.1.2   root      340:                        suword(argbufp++, 0);
1.1       root      341:                        break;
                    342:                }
                    343:        } while (limitonargs > 0);
                    344: 
                    345: dont_bother:
                    346:        if (limitonargs <= 0) {
                    347:                rv = E2BIG;
1.1.1.2   root      348:                goto exec_dealloc;
1.1       root      349:        }
                    350: 
1.1.1.2   root      351:        /* have we done the environment yet ? */
1.1       root      352:        if (needsenv) {
1.1.1.2   root      353:                /* remember the arg count for later */
1.1       root      354:                argc = cnt;
                    355:                vectp = uap->envp;
                    356:                needsenv = 0;
                    357:                goto do_env_as_well;
                    358:        }
                    359:  
1.1.1.2   root      360:        /* At this point, one could optionally implement a
                    361:         * second pass to condense the strings, arguement vectors,
                    362:         * and stack to fit the fewest pages.
                    363:         *
                    364:         * One might selectively do this when copying was cheaper
                    365:         * than leaving allocated two more pages per process.
                    366:         */
                    367: 
                    368:        /* stuff arg count on top of "new" stack */
1.1.1.3 ! root      369:        /* argbuf[-1] = (char *)argc;*/
        !           370:        suword(argbuf-1,argc);
1.1       root      371: 
                    372:        /*
                    373:         * Step 4. Build the new processes image.
1.1.1.2   root      374:         *
                    375:         * At this point, we are committed -- destroy old executable!
1.1       root      376:         */
                    377: 
1.1.1.2   root      378:        /* blow away all address space, except the stack */
                    379:        rv = vm_deallocate(&vs->vm_map, 0, USRSTACK - 2*MAXSSIZ);
1.1       root      380:        if (rv)
                    381:                goto exec_abort;
                    382: 
1.1.1.2   root      383:        /* destroy "old" stack */
                    384:        if ((unsigned)newframe < USRSTACK - MAXSSIZ) {
                    385:                rv = vm_deallocate(&vs->vm_map, USRSTACK - MAXSSIZ, MAXSSIZ);
                    386:                if (rv)
                    387:                        goto exec_abort;
                    388:        } else {
                    389:                rv = vm_deallocate(&vs->vm_map, USRSTACK - 2*MAXSSIZ, MAXSSIZ);
                    390:                if (rv)
                    391:                        goto exec_abort;
                    392:        }
                    393: 
1.1       root      394:        /* build a new address space */
                    395:        addr = 0;
1.1.1.2   root      396: 
                    397:        /* screwball mode -- special case of 413 to save space for floppy */
1.1.1.3 ! root      398:        if (exdata.ex_hdr.a_text == 0) {
1.1       root      399:                foff = tsize = 0;
1.1.1.3 ! root      400:                exdata.ex_hdr.a_data += exdata.ex_hdr.a_text;
1.1       root      401:        } else {
1.1.1.3 ! root      402:                tsize = roundup(exdata.ex_hdr.a_text, NBPG);
1.1       root      403:                foff = NBPG;
                    404:        }
1.1.1.2   root      405: 
                    406:        /* treat text and data in terms of integral page size */
1.1.1.3 ! root      407:        dsize = roundup(exdata.ex_hdr.a_data, NBPG);
        !           408:        bsize = roundup(exdata.ex_hdr.a_bss + dsize, NBPG);
1.1       root      409:        bsize -= dsize;
                    410: 
1.1.1.2   root      411:        /* map text & data in file, as being "paged in" on demand */
1.1.1.3 ! root      412:        rv = vm_mmap(&vs->vm_map, &addr, tsize+dsize, VM_PROT_ALL, VM_PROT_DEFAULT,
1.1.1.2   root      413:                MAP_FILE|MAP_COPY|MAP_FIXED, (caddr_t)ndp->ni_vp, foff);
1.1       root      414:        if (rv)
                    415:                goto exec_abort;
                    416: 
1.1.1.2   root      417:        /* mark pages r/w data, r/o text */
1.1       root      418:        if (tsize) {
                    419:                addr = 0;
1.1.1.2   root      420:                rv = vm_protect(&vs->vm_map, addr, tsize, FALSE,
                    421:                        VM_PROT_READ|VM_PROT_EXECUTE);
1.1       root      422:                if (rv)
                    423:                        goto exec_abort;
                    424:        }
                    425: 
                    426:        /* create anonymous memory region for bss */
                    427:        addr = dsize + tsize;
                    428:        rv = vm_allocate(&vs->vm_map, &addr, bsize, FALSE);
                    429:        if (rv)
                    430:                goto exec_abort;
                    431: 
                    432:        /*
                    433:         * Step 5. Prepare process for execution.
                    434:         */
                    435: 
1.1.1.2   root      436:        /* touchup process information -- vm system is unfinished! */
1.1       root      437:        vs->vm_tsize = tsize/NBPG;              /* text size (pages) XXX */
                    438:        vs->vm_dsize = (dsize+bsize)/NBPG;      /* data size (pages) XXX */
1.1.1.2   root      439:        vs->vm_taddr = 0;               /* user virtual address of text XXX */
1.1       root      440:        vs->vm_daddr = (caddr_t)tsize;  /* user virtual address of data XXX */
1.1.1.2   root      441:        vs->vm_maxsaddr = newframe;     /* user VA at max stack growth XXX */
                    442:        vs->vm_ssize =  ((unsigned)vs->vm_maxsaddr + MAXSSIZ
                    443:                - (unsigned)argbuf)/ NBPG + 1; /* stack size (pages) */
                    444:        dostacklimits = 1;      /* allow stack limits to be enforced XXX */
1.1       root      445: 
                    446:        /* close files on exec, fixup signals */
                    447:        fdcloseexec(p);
                    448:        execsigs(p);
                    449: 
1.1.1.2   root      450:        /* name this process - nameiexec(p, ndp) */
                    451:        len = MIN(ndp->ni_namelen,MAXCOMLEN);
                    452:        bcopy(ndp->ni_ptr, p->p_comm, len);
                    453:        p->p_comm[len] = 0;
                    454:        
                    455:        /* mark as executable, wakeup any process that was vforked and tell
                    456:         * it that it now has it's own resources back */
                    457:        p->p_flag |= SEXEC;
                    458:        if (p->p_pptr && (p->p_flag & SPPWAIT)) {
                    459:            p->p_flag &= ~SPPWAIT;
                    460:            wakeup(p->p_pptr);
                    461:        }
                    462:        
                    463:        /* implement set userid/groupid */
                    464:        if ((attr.va_mode&VSUID) && (p->p_flag & STRC) == 0) {
                    465:            p->p_ucred = crcopy(p->p_ucred);
                    466:            p->p_cred->p_svuid = p->p_ucred->cr_uid = attr.va_uid;
                    467:        }
                    468:        if ((attr.va_mode&VSGID) && (p->p_flag & STRC) == 0) {
                    469:            p->p_ucred = crcopy(p->p_ucred);
                    470:            p->p_cred->p_svgid = p->p_ucred->cr_groups[0] = attr.va_gid;
                    471:        }
                    472: 
                    473:        /* setup initial register state */
                    474:        p->p_regs[SP] = (unsigned) (argbuf - 1);
1.1.1.3 ! root      475:        setregs(p, exdata.ex_hdr.a_entry);
        !           476: 
        !           477:        ndp->ni_vp->v_flag |= VTEXT;            /* mark vnode pure text */
1.1.1.2   root      478: 
1.1       root      479:        vput(ndp->ni_vp);
1.1.1.2   root      480:        FREE(ndp->ni_pnbuf, M_NAMEI);
                    481: 
                    482:        /* if tracing process, pass control back to debugger so breakpoints
                    483:           can be set before the program "runs" */
                    484:        if (p->p_flag & STRC)
                    485:                psignal(p, SIGTRAP);
                    486: 
1.1       root      487:        return (0);
                    488: 
1.1.1.2   root      489: exec_dealloc:
                    490:        /* remove interim "new" stack frame we were building */
                    491:        vm_deallocate(&vs->vm_map, newframe, MAXSSIZ);
                    492: 
1.1       root      493: exec_fail:
1.1.1.2   root      494:        dostacklimits = 1;
1.1       root      495:        vput(ndp->ni_vp);
1.1.1.2   root      496:        FREE(ndp->ni_pnbuf, M_NAMEI);
                    497: 
1.1       root      498:        return(rv);
                    499: 
                    500: exec_abort:
1.1.1.2   root      501:        /* sorry, no more process anymore. exit gracefully */
                    502:        vm_deallocate(&vs->vm_map, newframe, MAXSSIZ);
1.1       root      503:        vput(ndp->ni_vp);
1.1.1.2   root      504:        FREE(ndp->ni_pnbuf, M_NAMEI);
1.1       root      505:        exit(p, W_EXITCODE(0, SIGABRT));
                    506: 
1.1.1.2   root      507:        /* NOTREACHED */
                    508:        return(0);
1.1       root      509: }

unix.superglobalmegacorp.com

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