Annotation of Net2/kern/kern_exec.c, revision 1.1.1.2

1.1.1.2 ! root        1: /*
        !             2:  * Copyright (C) 1993 Christopher G. Demetriou
        !             3:  * Copyright (C) 1992 Wolfgang Solfrank.
        !             4:  * Copyright (C) 1992 TooLs GmbH.
1.1       root        5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
1.1.1.2 ! root       17:  *     This product includes software developed by TooLs GmbH.
        !            18:  * 4. The name of TooLs GmbH may not be used to endorse or promote products
        !            19:  *    derived from this software without specific prior written permission.
1.1       root       20:  *
1.1.1.2 ! root       21:  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
        !            22:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            23:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            24:  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
        !            25:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
        !            26:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
        !            27:  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
        !            28:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
        !            29:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
        !            30:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.1       root       31:  *
1.1.1.2 ! root       32:  *     kern_exec.c,v 1.20 1993/07/13 22:13:19 cgd Exp
1.1       root       33:  */
                     34: 
1.1.1.2 ! root       35: #undef SETUIDSCRIPTS           /* Define this for setuid scripts */
        !            36: #ifdef SETUIDSCRIPTS
        !            37: #define        FDSCRIPTS               /* setuid scripts probably also want this */
        !            38: #endif
        !            39: 
1.1       root       40: #include "param.h"
                     41: #include "systm.h"
                     42: #include "filedesc.h"
                     43: #include "kernel.h"
                     44: #include "proc.h"
                     45: #include "mount.h"
                     46: #include "malloc.h"
                     47: #include "namei.h"
                     48: #include "vnode.h"
1.1.1.2 ! root       49: /* #include "seg.h" ??? -- cgd */
1.1       root       50: #include "file.h"
                     51: #include "acct.h"
                     52: #include "exec.h"
                     53: #include "ktrace.h"
                     54: #include "resourcevar.h"
1.1.1.2 ! root       55: #include "wait.h"
1.1       root       56: 
                     57: #include "machine/cpu.h"
                     58: #include "machine/reg.h"
1.1.1.2 ! root       59: #include "machine/exec.h"
1.1       root       60: 
                     61: #include "mman.h"
                     62: #include "vm/vm.h"
                     63: #include "vm/vm_param.h"
                     64: #include "vm/vm_map.h"
                     65: #include "vm/vm_kern.h"
                     66: #include "vm/vm_pager.h"
                     67: 
                     68: #include "signalvar.h"
                     69: #include "kinfo_proc.h"
                     70: 
                     71: #ifdef COPY_SIGCODE
                     72: extern char sigcode[], esigcode[];
                     73: #define        szsigcode       (esigcode - sigcode)
                     74: #else
                     75: #define        szsigcode       0
                     76: #endif
                     77: 
1.1.1.2 ! root       78: #ifdef FDSCRIPTS
        !            79: /* The returned attributes are only good for set[ug]id scripts/programs */
        !            80: static checkaout(p,ndp,vpp,ap,hdr,fdp,argp,argc,epp)
        !            81: struct proc *p;
        !            82: struct nameidata *ndp;
        !            83: struct vnode **vpp;
        !            84: struct vattr *ap;
        !            85: struct exec *hdr;
        !            86: int *fdp;
        !            87: char **argp;
        !            88: int *argc;
        !            89: struct exec_package *epp;
        !            90: #else
        !            91: static checkaout(p,ndp,vpp,ap,hdr,argp,argc,epp)
        !            92: struct proc *p;
        !            93: struct nameidata *ndp;
        !            94: struct vnode **vpp;
        !            95: struct vattr *ap;
        !            96: struct exec *hdr;
        !            97: char **argp;
        !            98: int *argc;
        !            99: struct exec_package *epp;
        !           100: #endif
        !           101: {
        !           102:     int error;
        !           103:     struct vnode *vp;
        !           104:     char *cp, *ep, *name;
        !           105:     int resid;
        !           106:     
        !           107:     /* XXX - THIS ENTIRE FUCTION SHOULD BE REWRITTEN - cgd */
        !           108: 
        !           109:     /* first get the vnode */
        !           110:     if (error = namei(ndp,p))
        !           111:        return error;
        !           112:     *vpp = vp = ndp->ni_vp;
        !           113:     
        !           114:     /* check for regular file */
        !           115:     if (vp->v_type != VREG) {
        !           116:        error = EACCES;
        !           117:        goto bad1;
        !           118:     }
        !           119:     
        !           120:     /* get attributes */
        !           121:     if (error = VOP_GETATTR(vp,ap,p->p_ucred,p))
        !           122:        goto bad1;
        !           123:     
        !           124:     /* Check mount point */
        !           125:     if (vp->v_mount->mnt_flag&MNT_NOEXEC) {
        !           126:        error = ENOEXEC;
        !           127:        goto bad1;
        !           128:     }
        !           129:     if ((vp->v_mount->mnt_flag&MNT_NOSUID) || (p->p_flag&STRC))
        !           130:        ap->va_mode &= ~(VSUID|VSGID);
        !           131:     
        !           132:     /* for root we have to check for any exec bit on */
        !           133:     /* doing it always doesn't hurt) */
        !           134:     if (!(ap->va_mode&0111)) {
        !           135:        error = EACCES;
        !           136:        goto bad1;
        !           137:     }
        !           138:     
        !           139:     /* check access */
        !           140:     if ((error = VOP_ACCESS(vp,VEXEC,p->p_ucred,p))
        !           141:        || (error = VOP_OPEN(vp,FREAD,p->p_ucred,p)))
        !           142:        goto bad1;
        !           143:     
        !           144:     /* now we have the file, get the exec header */
        !           145:     if (error = vn_rdwr(UIO_READ,vp,(caddr_t)hdr,sizeof(*hdr),0,
        !           146:                        UIO_SYSSPACE,IO_NODELOCKED,p->p_ucred,&resid,p))
        !           147:        goto bad2;
        !           148:     
        !           149:     if (!resid && !(hdr->a_text&PGOFSET) && !(hdr->a_data&PGOFSET)) {
        !           150:       /* sanity check: if it could get by the above, and still be a
        !           151:        * shell script.  if so, don't try the vmcmd tricks.
        !           152:        */
        !           153:       cp = (char *)hdr;
        !           154:       if (!(*cp == '#' && cp[1] == '!')) {
        !           155:        /* set up the vmcmds for creation of the process address space */
        !           156:        epp->ep_execp = hdr;
        !           157:        epp->ep_vp = vp;
        !           158:        epp->ep_vap = ap;
        !           159:        if (error = exec_makecmds(p, epp))
        !           160:          goto bad2;
        !           161: 
        !           162:        if (epp->ep_entry > VM_MAXUSER_ADDRESS) {
        !           163:          error = ENOEXEC;
        !           164:          goto bad2;
        !           165:        }
        !           166:        
        !           167:        /* check limits */
        !           168:        if ((epp->ep_tsize > MAXTSIZ) ||
        !           169:            (epp->ep_dsize > p->p_rlimit[RLIMIT_DATA].rlim_cur) ||
        !           170:            (epp->ep_ssize > p->p_rlimit[RLIMIT_STACK].rlim_cur)) {
        !           171:          error = ENOMEM;
        !           172:          goto bad2;
        !           173:        }
        !           174:        
        !           175:        return 0;
        !           176:       }
        !           177:     }
        !           178:     
        !           179:     /* scripts only if it's the first round */
        !           180:     cp = (char *)hdr;
        !           181:     ep = (char *)(hdr + 1) - resid;
        !           182:     if (ndp->ni_segflg == UIO_USERSPACE && *cp == '#' && cp[1] == '!') {
        !           183: #ifdef SETUIDSCRIPTS
        !           184:        struct vattr attr;
        !           185: #define        ATTRP   &attr
        !           186: #else
        !           187: #define        ATTRP   ap
        !           188: #endif
        !           189: #ifdef FDSCRIPTS
        !           190:        struct file *fp;
        !           191:        int fd;
        !           192:        extern struct fileops vnops;
        !           193:        char fdscripts = 0;
        !           194:        
        !           195:        /* we want to give the interpreter /dev/fd/xxx if the script is:
        !           196:           set[ug]id or
        !           197:           execute only */
        !           198:        
        !           199:        if (VOP_ACCESS(vp,VREAD,p->p_ucred,p) == EACCES
        !           200:            || (ap->va_mode&(VSUID|VSGID)))
        !           201:            fdscripts = 1;
        !           202:        
        !           203:        if (fdscripts) {
        !           204:            if (error = falloc(p,&fp,&fd))
        !           205:                goto bad2;
        !           206:            
        !           207:            VOP_UNLOCK(vp);
        !           208:            fp->f_type = DTYPE_VNODE;
        !           209:            fp->f_ops = &vnops;
        !           210:            fp->f_data = (caddr_t)vp;
        !           211:            fp->f_flag = FREAD;
        !           212:        } else {
        !           213: #endif
        !           214:            VOP_UNLOCK(vp);
        !           215:            vn_close(vp,FREAD,p->p_ucred,p);
        !           216: #ifdef FDSCRIPTS
        !           217:        }
        !           218: #endif
        !           219:        
        !           220:        for (cp += 2; cp < ep; cp++) {
        !           221:            switch (*cp) {
        !           222:            case ' ':
        !           223:            case '\t':
        !           224:                continue;
        !           225:            }
        !           226:            break;
        !           227:        }
        !           228:        if (cp >= ep)
        !           229:            error = EACCES;
        !           230:        
        !           231:        ++*argc;
        !           232:        for (name = cp; cp < ep; cp++) {
        !           233:            switch (*cp) {
        !           234:            default:
        !           235:                *(*argp)++ = *cp;
        !           236:                continue;
        !           237:            case '\0':
        !           238:            case '\n':
        !           239:                ep = cp;
        !           240:            case ' ':
        !           241:            case '\t':
        !           242:                *(*argp)++ = *cp++ = 0;
        !           243:                goto out1;
        !           244:            }
        !           245:            break;
        !           246:        }
        !           247: out1:
        !           248:        for (; cp < ep; cp++) {
        !           249:            switch (*cp) {
        !           250:            case ' ':
        !           251:            case '\t':
        !           252:                continue;
        !           253:            case '\0':
        !           254:            case '\n':
        !           255:                ep = cp;
        !           256:            }
        !           257:            break;
        !           258:        }
        !           259:        if (cp < ep) {
        !           260:            ++*argc;
        !           261:            for (; cp < ep; cp++) {
        !           262:                switch (*cp) {
        !           263:                default:
        !           264:                    *(*argp)++ = *cp;
        !           265:                    continue;
        !           266:                case '\0':
        !           267:                case '\n':
        !           268:                    *(*argp)++ = 0;
        !           269:                    goto out2;
        !           270:                }
        !           271:                break;
        !           272:            }
        !           273:        }
        !           274: out2:
        !           275:        
        !           276: #ifdef FDSCRIPTS
        !           277:        if (fdscripts) {
        !           278:            sprintf(*argp,"/dev/fd/%d",fd);
        !           279:            *fdp = fd;
        !           280:        } else
        !           281: #endif
        !           282:            strcpy(*argp,ndp->ni_pnbuf);
        !           283:        while (*(*argp)++);
        !           284:        ++*argc;
        !           285: 
        !           286:        ndp->ni_dirp = name;
        !           287:        ndp->ni_segflg = UIO_SYSSPACE;
        !           288: #ifdef FDSCRIPTS
        !           289:        if (!error && !(error = checkaout(p,ndp,vpp,ATTRP,hdr,&fd,argp,
        !           290:                                          argc,epp))) {
        !           291: #else
        !           292:        if (!error && !(error = checkaout(p,ndp,vpp,ATTRP,hdr,argp,
        !           293:                                          argc,epp))) {
        !           294: #endif
        !           295: #ifdef SETUIDSCRIPTS
        !           296:            if (!(ap->va_mode&VSUID))
        !           297:                ap->va_uid = attr.va_uid;
        !           298:            if (!(ap->va_mode&VSGID))
        !           299:                ap->va_gid = attr.va_gid;
        !           300:            ap->va_mode |= attr.va_mode&(VSUID|VSGID);
        !           301: #endif
        !           302:            return 0;
        !           303:        }
        !           304:        
        !           305: #ifdef FDSCRIPTS
        !           306:        if (fdscripts) {
        !           307:            closefd(p,fd);
        !           308:            goto bad2;
        !           309:        }
        !           310: #endif
        !           311:        return error;
        !           312:     }
        !           313:     
        !           314:     error = ENOEXEC;
        !           315:     
        !           316: bad2:
        !           317:     VOP_UNLOCK(vp);
        !           318:     vn_close(vp,FREAD,p->p_ucred,p);
        !           319:     FREE(ndp->ni_pnbuf,M_NAMEI);
        !           320:     return error;
        !           321: bad1:
        !           322:     FREE(ndp->ni_pnbuf,M_NAMEI);
        !           323:     vput(vp);
        !           324:     return error;
        !           325: }
        !           326: 
        !           327: #ifdef FDSCRIPTS
        !           328: static closefd(p,fd)
        !           329: struct proc *p;
        !           330: {
        !           331:     /* have to close file again */
        !           332:     if (p->p_fd->fd_lastfile == fd)
        !           333:        p->p_fd->fd_lastfile--;
        !           334:     if (p->p_fd->fd_freefile > fd)
        !           335:        p->p_fd->fd_freefile = fd;
        !           336:     closef(p->p_fd->fd_ofiles[fd],p);
        !           337:     p->p_fd->fd_ofiles[fd] = 0;
        !           338: }
        !           339: #endif
        !           340: 
        !           341: #ifdef EXEC_DEBUG
        !           342: exec_print_vmspaceinfo(struct proc *p)
        !           343: {
        !           344:   printf("process vmspace:\n");
        !           345:   printf("\tvm_taddr:    0x%x\n", p->p_vmspace->vm_taddr);
        !           346:   printf("\tvm_tsize:    0x%x\n", p->p_vmspace->vm_tsize);
        !           347:   printf("\tvm_daddr:    0x%x\n", p->p_vmspace->vm_daddr);
        !           348:   printf("\tvm_dsize:    0x%x\n", p->p_vmspace->vm_dsize);
        !           349:   printf("\tvm_ssize:    0x%x\n", p->p_vmspace->vm_ssize);
        !           350:   printf("\tvm_maxsaddr: 0x%x\n", p->p_vmspace->vm_maxsaddr);
        !           351: 
        !           352:   /* handy place for debugger breakpoint, but name is too long... */
        !           353:   asm(".globl _exec_print_vmspaceinfo_leave ; _exec_print_vmspaceinfo_leave:");
        !           354: }
        !           355: #endif
        !           356: 
        !           357: #ifdef EXEC_DEBUG
        !           358: exec_print_argstring(char *str, int len, char **ap, char *a)
        !           359: {
        !           360:   printf("(0x%x)-> \t0x%x     \t: %s (%d)\n", ap, a, str, len);
        !           361: }
        !           362: #endif
        !           363: 
1.1       root      364: /*
                    365:  * exec system call
                    366:  */
1.1.1.2 ! root      367: 
        !           368: struct execve_args {
        !           369:        char    *fname;
        !           370:        char    **argp;
        !           371:        char    **envp;
        !           372: };
        !           373: 
1.1       root      374: /* ARGSUSED */
                    375: execve(p, uap, retval)
                    376:        register struct proc *p;
1.1.1.2 ! root      377:        register struct execve_args *uap;
1.1       root      378:        int *retval;
                    379: {
                    380: 
                    381:        /*
                    382:         * Body deleted.
                    383:         */
1.1.1.2 ! root      384:        /*
        !           385:         * And reimplemented by ws.
        !           386:         * I think this should be vastly more machine dependent
        !           387:         * (e.g. stack up/down, startup stack format etc.)
        !           388:         */
        !           389:        int error;
        !           390:        struct vnode *vp;
        !           391:        struct nameidata nid;
        !           392:        struct ucred *cred = p->p_ucred;
        !           393:        char *argp;
        !           394:        struct exec hdr;
        !           395:        char **cpp, *dp, *sp, *np;
        !           396:        int argc, envc, len;
        !           397:        char *stack;
        !           398:        struct vattr attr;
        !           399:        struct ps_strings arginfo;
        !           400:        struct exec_package pack;
        !           401: #ifdef FDSCRIPTS
        !           402:        int fd;
        !           403: #endif
        !           404:        
        !           405:        /* get space for argv & environment */
        !           406: /* was:        if(!(dp = argp = (char *)kmem_alloc_wait(exec_map,ARG_MAX))) - cgd */
        !           407:        MALLOC(argp, char *, ARG_MAX, M_EXEC, M_WAITOK);
        !           408:        if(!argp)
        !           409:            panic("exec: can't allocate ARG_MAX");
        !           410:        dp = argp;
        !           411:        argc = 0;
        !           412: #ifdef FDSCRIPTS
        !           413:        fd = -1;
        !           414: #endif
        !           415:        
        !           416:        nid.ni_dirp = uap->fname;
        !           417:        nid.ni_segflg = UIO_USERSPACE;
        !           418:        nid.ni_nameiop = LOOKUP|FOLLOW|LOCKLEAF|SAVENAME;
        !           419:        /* checkaout possibly copies arguments for scripts */
        !           420: #ifdef FDSCRIPTS
        !           421:        if (error = checkaout(p,&nid,&vp,&attr,&hdr,&fd,&dp,&argc,&pack))
        !           422: #else
        !           423:        if (error = checkaout(p,&nid,&vp,&attr,&hdr,&dp,&argc,&pack))
        !           424: #endif
        !           425:            goto freeargs;
        !           426: 
        !           427:        /* Now get argv & environment */
        !           428:        if (!(cpp = uap->argp)) {
        !           429:            error = EINVAL;
        !           430:            goto bad;
        !           431:        }
        !           432:        
        !           433:        if (argc > 0) {
        !           434:            /* it is a script, so we have to skip the 0th arg */
        !           435:            cpp++;
        !           436:            /* check access to arg here? */
        !           437:        }
        !           438:        
        !           439: #ifdef EXEC_DEBUG
        !           440:        printf("start of args = 0x%x\n", dp);
        !           441: #endif
        !           442:        while (1) {
        !           443:            len = argp + ARG_MAX - dp;
        !           444:            if (error = copyin(cpp,&sp,sizeof(sp)))
        !           445:                goto bad;
        !           446:            if (!sp)
        !           447:                break;
        !           448:            if (error = copyinstr(sp,dp,len,(u_int *)&len)) {
        !           449:                if (error == ENAMETOOLONG)
        !           450:                    error = E2BIG;
        !           451:                goto bad;
        !           452:            }
        !           453:            dp += len;
        !           454:            cpp++;
        !           455:            argc++;
        !           456:        }
        !           457: #ifdef EXEC_DEBUG
        !           458:        printf("end of args = 0x%x\n", dp);
        !           459: #endif
        !           460: 
        !           461:        envc = 0;
        !           462:        if (cpp = uap->envp) {  /* environment need not be there */
        !           463:            while (1) {
        !           464:                len = argp + ARG_MAX - dp;
        !           465:                if (error = copyin(cpp,&sp,sizeof(sp)))
        !           466:                    goto bad;
        !           467:                if (!sp)
        !           468:                    break;
        !           469:                if (error = copyinstr(sp,dp,len,(u_int *)&len)) {
        !           470:                    if (error == ENAMETOOLONG)
        !           471:                        error = E2BIG;
        !           472:                    goto bad;
        !           473:                }
        !           474:                dp += len;
        !           475:                cpp++;
        !           476:                envc++;
        !           477:            }
        !           478:            dp = (char *)ALIGN(dp);
        !           479:        }
        !           480: #ifdef EXEC_DEBUG
        !           481:        printf("end of env = 0x%x\n", dp);
        !           482:        printf("argc/envc = %d/%d\n", argc, envc);
        !           483: #endif
        !           484: 
        !           485:        /* Now check if args & environ fit into new stack */
        !           486:        len = ((argc + envc + 2) * sizeof(char *) + sizeof(int) +
        !           487:               dp + sizeof(struct ps_strings) + szsigcode) - argp;
        !           488:        len = roundup(len, sizeof(char *));
        !           489:        if (len > p->p_rlimit[RLIMIT_STACK].rlim_cur) {
        !           490:            error = ENOMEM;
        !           491:            goto bad;
        !           492:        }
        !           493: 
        !           494:        /* Unmap old program */
        !           495:        vm_deallocate(&p->p_vmspace->vm_map,0,USRSTACK);
        !           496:        
        !           497:        /* Now map address space */
        !           498:        p->p_vmspace->vm_taddr = (char *) pack.ep_taddr;
        !           499:        p->p_vmspace->vm_tsize = btoc(pack.ep_tsize);
        !           500:        p->p_vmspace->vm_daddr = (char *) pack.ep_daddr;
        !           501:        p->p_vmspace->vm_dsize = btoc(pack.ep_dsize);
        !           502:        p->p_vmspace->vm_ssize = btoc(pack.ep_ssize);
        !           503:        p->p_vmspace->vm_maxsaddr = (char *) pack.ep_maxsaddr;
        !           504:        if (error = exec_runcmds(p, &pack))
        !           505:                goto exec_abort;
        !           506:        kill_vmcmd(&pack.ep_vcp);
        !           507:        
        !           508:        /* remember information about the process */
        !           509:        arginfo.ps_nargvstr = argc;
        !           510:        arginfo.ps_nenvstr = envc;
        !           511: 
        !           512:        /* Now copy argc, args & environ to new stack */
        !           513:        stack = (char *)(USRSTACK - len);
        !           514: #ifdef EXEC_DEBUG
        !           515:        printf("stack wants to live at: 0x%x\n", stack);
        !           516: #endif
        !           517:        cpp = (char **)stack;
        !           518:        
        !           519:        if (copyout(&argc,cpp++,sizeof(argc)))
        !           520:            goto exec_abort;
        !           521: #ifdef EXEC_DEBUG
        !           522:        printf("0x%x     \targ count: %d\n", (cpp - 1), argc);
        !           523: #endif
        !           524:        dp = (char *)(cpp + argc + envc + 2);
        !           525: 
        !           526:        arginfo.ps_argvstr = dp; /* remember location of argv for later */
        !           527:        for (sp = argp; --argc >= 0; sp += len, dp += len) {
        !           528:            len = strlen(sp) + 1;
        !           529:            if (copyout(&dp,cpp++,sizeof(dp))
        !           530:                || copyoutstr(sp,dp,len,0))
        !           531:                goto exec_abort;
        !           532: #ifdef EXEC_DEBUG
        !           533:            exec_print_argstring(sp, len, (cpp - 1), dp);
        !           534: #endif
        !           535:        }
        !           536:        np = 0;
        !           537:        if (copyout(&np,cpp++,sizeof(np)))
        !           538:            goto exec_abort;
        !           539: 
        !           540:        arginfo.ps_envstr = dp; /* remember location of env for later */
        !           541:        for (; --envc >= 0; sp += len, dp += len) {
        !           542:            len = strlen(sp) + 1;
        !           543:            if (copyout(&dp,cpp++,sizeof(dp))
        !           544:                || copyoutstr(sp,dp,len,0))
        !           545:                goto exec_abort;
        !           546: #ifdef EXEC_DEBUG
        !           547:            exec_print_argstring(sp, len, (cpp - 1), dp);
        !           548: #endif
        !           549:        }
        !           550:        if (copyout(&np,cpp,sizeof(np)))
        !           551:            goto exec_abort;
        !           552: 
        !           553:        /* copy out the process's ps_strings structure */
        !           554:        if (copyout(&arginfo, (char *)PS_STRINGS, sizeof(arginfo)))
        !           555:            goto exec_abort;
        !           556: 
        !           557: #ifdef COPY_SIGCODE
        !           558:         /* copy out the process's signal trapoline code */
        !           559:         if (copyout((char *)sigcode, ((char *)PS_STRINGS) - szsigcode,
        !           560:                    szsigcode)) {
        !           561:          goto exec_abort;
        !           562:        }
        !           563: #endif
        !           564: 
        !           565:        fdcloseexec(p); /* handle close on exec */
        !           566:        execsigs(p);    /* reset catched signals */
        !           567: 
        !           568:        /* set command name & other accounting info */
        !           569:        len = MIN(nid.ni_namelen,MAXCOMLEN);
        !           570:        bcopy(nid.ni_ptr,p->p_comm,len);
        !           571:        p->p_comm[len] = 0;
        !           572:        p->p_acflag &= ~AFORK;
        !           573:        
        !           574:        p->p_flag |= SEXEC;
        !           575:        if (p->p_flag&SPPWAIT) {
        !           576:            p->p_flag &= ~SPPWAIT;
        !           577:            wakeup((caddr_t)p->p_pptr);
        !           578:        }
        !           579:        
        !           580:        /*
        !           581:         *deal with set[ug]id
        !           582:         * MNT_NOEXEC and STRC have already been used to disable s[ug]id
        !           583:         */
        !           584:        if (attr.va_mode&VSUID) {
        !           585:            p->p_ucred = crcopy(cred);
        !           586:            p->p_ucred->cr_uid = attr.va_uid;
        !           587:        }
        !           588:        p->p_cred->p_svuid = p->p_ucred->cr_uid;
        !           589:        if (attr.va_mode&VSGID) {
        !           590:            p->p_ucred = crcopy(p->p_ucred);
        !           591:            p->p_ucred->cr_gid = attr.va_gid;
        !           592:        }
        !           593:        p->p_cred->p_svgid = p->p_ucred->cr_gid;
        !           594:        /* what else? */
        !           595:        
        !           596: /* was: kmem_free_wakeup(exec_map,argp,ARG_MAX); - cgd */
        !           597:        FREE(argp, M_EXEC);
        !           598:        
        !           599:        FREE(nid.ni_pnbuf,M_NAMEI);
        !           600:        VOP_CLOSE(vp,FREAD,cred,p);
        !           601:        vput(vp);
        !           602:        
        !           603:        /* setup new registers */
        !           604:        setregs(p, hdr.a_entry, (u_long) stack, retval);
        !           605: #ifdef EXEC_DEBUG
        !           606:        printf("exec returning normally\n");
        !           607: #endif
        !           608: 
        !           609:        if (p->p_flag & STRC)
        !           610:                psignal(p, SIGTRAP);
        !           611: 
        !           612:        return EJUSTRETURN;
        !           613:        
        !           614: bad:
        !           615:        FREE(nid.ni_pnbuf,M_NAMEI);
        !           616:        VOP_CLOSE(vp,FREAD,cred,p);
        !           617:        vput(vp);
        !           618: #ifdef FDSCRIPTS
        !           619:        if (fd)
        !           620:            closefd(p,fd);
        !           621: #endif
        !           622: freeargs:
        !           623: /* was:        kmem_free_wakeup(exec_map,argp,ARG_MAX); - cgd */
        !           624:        FREE(argp, M_EXEC);
        !           625: #ifdef EXEC_DEBUG
        !           626:        printf("exec returning on error\n");
        !           627: #endif
        !           628:        return error;
        !           629: 
        !           630: exec_abort:
        !           631:        /* the old process doesn't exist anymore.  exit gracefully.
        !           632:         *
        !           633:         * get rid of the (new) address space we have created, if any,
        !           634:         * get rid of our namei data and vnode, and exit noting failure
        !           635:         */
        !           636: #ifdef EXEC_DEBUG
        !           637:        printf("exec bailing out (abort)\n");
        !           638: #endif
        !           639:        vm_deallocate(&p->p_vmspace->vm_map,0,USRSTACK);
        !           640:         FREE(nid.ni_pnbuf,M_NAMEI);
        !           641:         VOP_CLOSE(vp,FREAD,cred,p);
        !           642:        vput(vp);
        !           643:        kexit(p, W_EXITCODE(0, SIGABRT));
        !           644:        kexit(p, -1);
        !           645: 
        !           646:        /* NOTREACHED */
        !           647:        return 0;
        !           648: }
        !           649: 
        !           650: int
        !           651: exec_runcmds(p, epp)
        !           652:      struct proc *p;
        !           653:      struct exec_package *epp;
        !           654: {
        !           655:   struct exec_vmcmd *cur = epp->ep_vcp;
        !           656:   int error;
        !           657: 
        !           658:   while (cur && !(error = (*cur->ev_proc)(p, cur)))
        !           659:     cur = cur->ev_next;
        !           660: 
        !           661:   return error;
        !           662: }
        !           663: 
        !           664: int
        !           665: exec_makecmds(p, epp)
        !           666:      struct proc *p;
        !           667:      struct exec_package *epp;
        !           668: {
        !           669:   u_long midmag, magic;
        !           670:   u_short mid;
        !           671:   int error;
        !           672: 
        !           673:   epp->ep_vcp = NULL;
        !           674: 
        !           675:   midmag = ntohl(epp->ep_execp->a_midmag);
        !           676:   mid = (midmag >> 16 ) & 0x3ff;
        !           677:   magic = midmag & 0xffff;
        !           678: 
        !           679: #ifdef EXEC_DEBUG
        !           680:   printf("exec_makecmds: a_midmag is %x, magic=%x mid=%x\n",
        !           681:     epp->ep_execp->a_midmag, magic, mid);
        !           682: #endif
        !           683: 
        !           684:   midmag = mid<<16 | magic;
        !           685: 
        !           686:   switch (midmag) {
        !           687:   case (MID_MACHINE << 16) | ZMAGIC:
        !           688:     error = exec_prep_zmagic(p, epp);
        !           689:     break;
        !           690:   case (MID_MACHINE << 16) | OMAGIC:
        !           691:   case (MID_MACHINE << 16) | NMAGIC:
        !           692:   default:
        !           693:     error = cpu_exec_makecmds(p, epp);
        !           694:   }
        !           695: 
        !           696:   if (error && epp->ep_vcp)
        !           697:     kill_vmcmd(&epp->ep_vcp);
        !           698: 
        !           699: bad:
        !           700: 
        !           701: #ifdef EXEC_DEBUG
        !           702:   printf("exec_makecmds returning with error = %d\n", error);
        !           703: #endif
        !           704:   return error;
        !           705: }
        !           706: 
        !           707: void
        !           708: kill_vmcmd(vcpp)
        !           709:      struct exec_vmcmd **vcpp;
        !           710: {
        !           711:   struct exec_vmcmd *cur, *next;
        !           712: 
        !           713:   cur = *vcpp;
        !           714:   *vcpp = NULL;
        !           715:   while (cur != NULL) {
        !           716:     if (cur->ev_vp != NULL)
        !           717:       vrele(cur->ev_vp);
        !           718:     next = cur->ev_next;
        !           719:     FREE(cur, M_EXEC);
        !           720:     cur = next;
        !           721:   }
        !           722: }
        !           723: 
        !           724: inline struct exec_vmcmd *
        !           725: new_vmcmd(proc, len, addr, vp, offset, prot)
        !           726:      int (*proc) __P((struct proc *p, struct exec_vmcmd *));
        !           727:      unsigned long len;
        !           728:      unsigned long addr;
        !           729:      struct vnode *vp;
        !           730:      unsigned long offset;
        !           731:      unsigned long prot;
        !           732: {
        !           733:   struct exec_vmcmd *tmpcmdp;
        !           734: 
        !           735:   MALLOC(tmpcmdp, struct exec_vmcmd *, sizeof(struct exec_vmcmd),
        !           736:         M_EXEC, M_WAITOK);
        !           737:   tmpcmdp->ev_next = NULL;
        !           738:   tmpcmdp->ev_proc = proc;
        !           739:   tmpcmdp->ev_len = len;
        !           740:   tmpcmdp->ev_addr = addr;
        !           741:   if ((tmpcmdp->ev_vp = vp) != NULL)
        !           742:     vref(vp);
        !           743:   tmpcmdp->ev_offset = offset;
        !           744:   tmpcmdp->ev_prot = prot;
        !           745: 
        !           746:   return tmpcmdp;
        !           747: }
        !           748: 
        !           749: int
        !           750: exec_prep_zmagic(p, epp)
        !           751:      struct proc *p;
        !           752:      struct exec_package *epp;
        !           753: {
        !           754:   struct exec *execp = epp->ep_execp;
        !           755:   struct exec_vmcmd *ccmdp;
        !           756: 
        !           757:   epp->ep_taddr = USRTEXT;
        !           758:   epp->ep_tsize = execp->a_text;
        !           759:   epp->ep_daddr = epp->ep_taddr + execp->a_text;
        !           760:   epp->ep_dsize = execp->a_data + execp->a_bss;
        !           761:   epp->ep_maxsaddr = USRSTACK - MAXSSIZ;
        !           762:   epp->ep_minsaddr = USRSTACK;
        !           763:   epp->ep_ssize = p->p_rlimit[RLIMIT_STACK].rlim_cur;
        !           764:   epp->ep_entry = execp->a_entry;
        !           765: 
        !           766:   /* check if vnode is in open for writing, because we want to demand-page
        !           767:    * out of it.  if it is, don't do it, for various reasons
        !           768:    */
        !           769:   if ((execp->a_text != 0 || execp->a_data != 0) &&
        !           770:       (epp->ep_vp->v_flag & VTEXT) == 0 && epp->ep_vp->v_writecount != 0) {
        !           771: #ifdef DIAGNOSTIC
        !           772:     if (epp->ep_vp->v_flag & VTEXT)
        !           773:       panic("exec: a VTEXT vnode has writecount != 0\n");
        !           774: #endif
        !           775:     epp->ep_vcp = NULL;
        !           776:     return ETXTBSY;
        !           777:   }
        !           778:   epp->ep_vp->v_flag |= VTEXT;
        !           779: 
        !           780:   /* set up command for text segment */
        !           781:   epp->ep_vcp = new_vmcmd(vmcmd_map_pagedvn,
        !           782:                          execp->a_text,
        !           783:                          epp->ep_taddr,
        !           784:                          epp->ep_vp,
        !           785:                          0,
        !           786:                          VM_PROT_READ|VM_PROT_EXECUTE);
        !           787:   ccmdp = epp->ep_vcp;
        !           788: 
        !           789:   /* set up command for data segment */
        !           790:   ccmdp->ev_next = new_vmcmd(vmcmd_map_pagedvn,
        !           791:                             execp->a_data,
        !           792:                             epp->ep_daddr,
        !           793:                             epp->ep_vp,
        !           794:                             execp->a_text,
        !           795:                             VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
        !           796:   ccmdp = ccmdp->ev_next;
        !           797: 
        !           798:   /* set up command for bss segment */
        !           799:   ccmdp->ev_next = new_vmcmd(vmcmd_map_zero,
        !           800:                             execp->a_bss,
        !           801:                             epp->ep_daddr + execp->a_data,
        !           802:                             0,
        !           803:                             0,
        !           804:                             VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
        !           805:   ccmdp = ccmdp->ev_next;
        !           806: 
        !           807:   /* set up commands for stack.  note that this takes *two*, one
        !           808:    * to map the part of the stack which we can access, and one
        !           809:    * to map the part which we can't.
        !           810:    *
        !           811:    * arguably, it could be made into one, but that would require
        !           812:    * the addition of another mapping proc, which is unnecessary
        !           813:    *
        !           814:    * note that in memory, thigns assumed to be:
        !           815:    *    0 ....... ep_maxsaddr <stack> ep_minsaddr
        !           816:    */
        !           817:   ccmdp->ev_next = new_vmcmd(vmcmd_map_zero,
        !           818:                             ((epp->ep_minsaddr - epp->ep_ssize) -
        !           819:                              epp->ep_maxsaddr),
        !           820:                             epp->ep_maxsaddr,
        !           821:                             0,
        !           822:                             0,
        !           823:                             VM_PROT_NONE);
        !           824:   ccmdp = ccmdp->ev_next;
        !           825:   ccmdp->ev_next = new_vmcmd(vmcmd_map_zero,
        !           826:                             epp->ep_ssize,
        !           827:                             (epp->ep_minsaddr - epp->ep_ssize),
        !           828:                             0,
        !           829:                             0,
        !           830:                             VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
        !           831: 
        !           832:   return 0;
        !           833: }
        !           834: 
        !           835: int vmcmd_map_pagedvn(p,cmd )
        !           836:      struct proc *p;
        !           837:      struct exec_vmcmd *cmd;
        !           838: {
        !           839:   /* note that if you're going to map part of an process as being paged from
        !           840:    * a vnode, that vnode had damn well better be marked as VTEXT.  that's
        !           841:    * handled in the routine which sets up the vmcmd to call this routine.
        !           842:    */
        !           843: #ifdef EXEC_DEBUG
        !           844:   printf("vmcmd_map_pagedvn: mapping into addr %x for len %x (%x/%x)\n",
        !           845:         cmd->ev_addr, cmd->ev_len, cmd->ev_prot, VM_PROT_DEFAULT);
        !           846: #endif
        !           847:   return vm_mmap(&p->p_vmspace->vm_map,
        !           848:                 &cmd->ev_addr,
        !           849:                 cmd->ev_len,
        !           850:                 cmd->ev_prot,
        !           851:                 VM_PROT_DEFAULT,
        !           852:                 MAP_FIXED|MAP_FILE|MAP_COPY,
        !           853:                 cmd->ev_vp,
        !           854:                 cmd->ev_offset);
        !           855: }
        !           856: 
        !           857: int vmcmd_map_zero(p, cmd)
        !           858:      struct proc *p;
        !           859:      struct exec_vmcmd *cmd;
        !           860: {
        !           861:   int  error;
        !           862: 
        !           863: #ifdef EXEC_DEBUG
        !           864:   printf("vmcmd_map_zero: mapping into addr %x for len %x (%x/%x)\n",
        !           865:         cmd->ev_addr, cmd->ev_len, cmd->ev_prot, VM_PROT_DEFAULT);
        !           866: #endif
        !           867:   error = vm_allocate(&p->p_vmspace->vm_map,
        !           868:                      &cmd->ev_addr,
        !           869:                      cmd->ev_len,
        !           870:                      0);
        !           871:   if (error)
        !           872:     return error;
        !           873: 
        !           874:   return vm_protect(&p->p_vmspace->vm_map,
        !           875:                        cmd->ev_addr,
        !           876:                        cmd->ev_len,
        !           877:                        FALSE,
        !           878:                        cmd->ev_prot);
1.1       root      879: }

unix.superglobalmegacorp.com

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