X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/dbf0c42388ea40e835684353b6bf13aa4b80b98b..451df175ed5f4a23ad6cf21e55dfebcd440a527c:/usr/src/sys/kern/kern_exec.c diff --git a/usr/src/sys/kern/kern_exec.c b/usr/src/sys/kern/kern_exec.c index f25718a79f..4d27e87769 100644 --- a/usr/src/sys/kern/kern_exec.c +++ b/usr/src/sys/kern/kern_exec.c @@ -1,57 +1,55 @@ -/* - * Copyright (c) 1982, 1986, 1989 Regents of the University of California. +/*- + * Copyright (c) 1982, 1986, 1991 The Regents of the University of California. * All rights reserved. * - * %sccs.include.redist.c% + * %sccs.include.proprietary.c% * - * @(#)kern_exec.c 7.29 (Berkeley) %G% + * @(#)kern_exec.c 7.55 (Berkeley) %G% */ #include "param.h" #include "systm.h" -#include "map.h" -#include "user.h" +#include "filedesc.h" #include "kernel.h" #include "proc.h" #include "mount.h" -#include "ucred.h" #include "malloc.h" -#include "buf.h" +#include "namei.h" #include "vnode.h" -#include "seg.h" -#include "vm.h" -#include "text.h" #include "file.h" -#include "uio.h" #include "acct.h" #include "exec.h" +#include "ktrace.h" +#include "resourcevar.h" +#include "machine/cpu.h" #include "machine/reg.h" -#include "machine/pte.h" -#include "machine/psl.h" -#include "machine/mtpr.h" + +#include "mman.h" +#include "vm/vm.h" +#include "vm/vm_param.h" +#include "vm/vm_map.h" +#include "vm/vm_kern.h" +#include "vm/vm_pager.h" + +#include "signalvar.h" +#include "kinfo_proc.h" #ifdef HPUXCOMPAT -#include "../hpux/hpux_exec.h" +#include "user.h" /* for pcb */ +#include "hp300/hpux/hpux_exec.h" +#endif + +#ifdef COPY_SIGCODE +extern char sigcode[], esigcode[]; +#define szsigcode (esigcode - sigcode) +#else +#define szsigcode 0 #endif /* - * exec system call, with and without environments. + * exec system call */ -execv(p, uap, retval) - struct proc *p; - struct args { - char *fname; - char **argp; - char **envp; - } *uap; - int *retval; -{ - - uap->envp = NULL; - return (execve(p, uap, retval)); -} - /* ARGSUSED */ execve(p, uap, retval) register struct proc *p; @@ -62,18 +60,18 @@ execve(p, uap, retval) } *uap; int *retval; { - register nc; + register struct ucred *cred = p->p_ucred; + register struct filedesc *fdp = p->p_fd; + int na, ne, ucp, ap, cc, ssize; register char *cp; - register struct buf *bp; - struct buf *tbp; - int na, ne, ucp, ap, cc; + register int nc; unsigned len; int indir, uid, gid; char *sharg; struct vnode *vp; - swblk_t bno; + int resid, error, paged = 0; + vm_offset_t execargs = 0; struct vattr vattr; - char cfname[MAXCOMLEN + 1]; char cfarg[MAXINTERP]; union { char ex_shell[MAXINTERP]; /* #! and interpreter name */ @@ -85,26 +83,21 @@ execve(p, uap, retval) #ifdef HPUXCOMPAT struct hpux_exec hhead; #endif - register struct ucred *cred = u.u_cred; - register struct nameidata *ndp = &u.u_nd; - int resid, error, flags = 0; + struct nameidata nd; + struct ps_strings ps; #ifdef SECSIZE extern long argdbsize; /* XXX */ #endif SECSIZE - start: - ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; - ndp->ni_segflg = UIO_USERSPACE; - ndp->ni_dirp = uap->fname; - if (error = namei(ndp)) + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | SAVENAME, UIO_USERSPACE, + uap->fname, p); + if (error = namei(&nd)) return (error); - vp = ndp->ni_vp; - bno = 0; - bp = 0; + vp = nd.ni_vp; indir = 0; uid = cred->cr_uid; gid = cred->cr_gid; - if (error = VOP_GETATTR(vp, &vattr, cred)) + if (error = VOP_GETATTR(vp, &vattr, cred, p)) goto bad; if (vp->v_mount->mnt_flag & MNT_NOEXEC) { error = EACCES; @@ -118,9 +111,9 @@ execve(p, uap, retval) } again: - if (error = VOP_ACCESS(vp, VEXEC, cred)) + if (error = VOP_ACCESS(vp, VEXEC, cred, p)) goto bad; - if ((p->p_flag & STRC) && (error = VOP_ACCESS(vp, VREAD, cred))) + if ((p->p_flag & STRC) && (error = VOP_ACCESS(vp, VREAD, cred, p))) goto bad; if (vp->v_type != VREG || (vattr.va_mode & (VEXEC|(VEXEC>>3)|(VEXEC>>6))) == 0) { @@ -144,7 +137,8 @@ execve(p, uap, retval) */ exdata.ex_shell[0] = '\0'; /* for zero length files */ error = vn_rdwr(UIO_READ, vp, (caddr_t)&exdata, sizeof (exdata), - (off_t)0, UIO_SYSSPACE, (IO_UNIT|IO_NODELOCKED), cred, &resid); + (off_t)0, UIO_SYSSPACE, (IO_UNIT|IO_NODELOCKED), cred, &resid, + (struct proc *)0); if (error) goto bad; #ifndef lint @@ -192,7 +186,7 @@ execve(p, uap, retval) * treated as an HPUX binary. */ if (exdata.ex_hexec.ha_version != BSDVNUM) - flags |= SHPUX; + paged |= SHPUX; /* XXX */ /* * Shuffle important fields to their BSD locations. * Note that the order in which this is done is important. @@ -221,13 +215,43 @@ execve(p, uap, retval) switch ((int)exdata.ex_exec.a_magic) { case OMAGIC: +#ifdef COFF + if (exdata.ex_exec.ex_fhdr.magic != COFF_MAGIC) { + error = ENOEXEC; + goto bad; + } +#endif +#ifdef sparc + if (exdata.ex_exec.a_mid != MID_SUN_SPARC) { + error = ENOEXEC; + goto bad; + } +#endif exdata.ex_exec.a_data += exdata.ex_exec.a_text; exdata.ex_exec.a_text = 0; break; case ZMAGIC: - flags |= SPAGV; +#ifdef HPUXCOMPAT + paged |= 1; /* XXX fix me */ +#else + paged = 1; +#endif + /* FALLTHROUGH */ + case NMAGIC: +#ifdef COFF + if (exdata.ex_exec.ex_fhdr.magic != COFF_MAGIC) { + error = ENOEXEC; + goto bad; + } +#endif +#ifdef sparc + if (exdata.ex_exec.a_mid != MID_SUN_SPARC) { + error = ENOEXEC; + goto bad; + } +#endif if (exdata.ex_exec.a_text == 0) { error = ENOEXEC; goto bad; @@ -256,7 +280,7 @@ execve(p, uap, retval) cp = &exdata.ex_shell[2]; while (*cp == ' ') cp++; - ndp->ni_dirp = cp; + nd.ni_dirp = cp; while (*cp && *cp != ' ') cp++; cfarg[0] = '\0'; @@ -269,36 +293,16 @@ execve(p, uap, retval) } indir = 1; vput(vp); - ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; - ndp->ni_segflg = UIO_SYSSPACE; - if (error = namei(ndp)) + nd.ni_segflg = UIO_SYSSPACE; + if (error = namei(&nd)) return (error); - vp = ndp->ni_vp; - if (error = VOP_GETATTR(vp, &vattr, cred)) + vp = nd.ni_vp; + if (error = VOP_GETATTR(vp, &vattr, cred, p)) goto bad; - bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)cfname, - MAXCOMLEN); - cfname[MAXCOMLEN] = '\0'; uid = cred->cr_uid; /* shell scripts can't be setuid */ gid = cred->cr_gid; goto again; } - /* - * If the vnode has been modified since we last used it, - * then throw away all its pages and its text table entry. - */ - if (vp->v_text && vp->v_text->x_mtime != vattr.va_mtime.tv_sec) { - /* - * Try once to release, if it is still busy - * take more drastic action. - */ - xrele(vp); - if (vp->v_flag & VTEXT) { - vput(vp); - vgone(vp); - goto start; - } - } /* * Collect arguments on "file" in swap space. @@ -306,22 +310,13 @@ execve(p, uap, retval) na = 0; ne = 0; nc = 0; - cc = 0; -#ifdef SECSIZE - bno = rmalloc(argmap, (clrnd((int)btoc(NCARGS))) * CLBYTES / argdbsize); -#else SECSIZE - bno = rmalloc(argmap, (long)ctod(clrnd((int)btoc(NCARGS)))); -#endif SECSIZE - if (bno == 0) { - swkill(p, "exec: no swap space"); - goto bad; - } - if (bno % CLSIZE) - panic("execa rmalloc"); -#ifdef GENERIC - if (rootdev == dumpdev) - bno += 4096; + cc = NCARGS; + execargs = kmem_alloc_wait(exec_map, NCARGS); +#ifdef DIAGNOSTIC + if (execargs == (vm_offset_t)0) + panic("execve: kmem_alloc_wait"); #endif + cp = (char *) execargs; /* * Copy arguments into file in argdev area. */ @@ -329,7 +324,7 @@ execve(p, uap, retval) ap = NULL; sharg = NULL; if (indir && na == 0) { - sharg = cfname; + sharg = nd.ni_cnd.cn_nameptr; ap = (int)sharg; uap->argp++; /* ignore argv[0] */ } else if (indir && (na == 1 && cfarg[0])) { @@ -351,33 +346,12 @@ execve(p, uap, retval) na++; if (ap == -1) { error = EFAULT; - if (bp) { - brelse(bp); - bp = 0; - } - goto badarg; + goto bad; } do { - if (cc <= 0) { - /* - * We depend on NCARGS being a multiple of - * CLBYTES. This way we need only check - * overflow before each buffer allocation. - */ - if (nc >= NCARGS-1) { - error = E2BIG; - break; - } - if (bp) - bdwrite(bp); - cc = CLBYTES; -#ifdef SECSIZE - bp = getblk(argdev, bno + nc / argdbsize, cc, - argdbsize); -#else SECSIZE - bp = getblk(argdev_vp, bno + ctod(nc/NBPG), cc); -#endif SECSIZE - cp = bp->b_un.b_addr; + if (nc >= NCARGS-1) { + error = E2BIG; + break; } if (sharg) { error = copystr(sharg, cp, (unsigned)cc, &len); @@ -390,37 +364,50 @@ execve(p, uap, retval) cp += len; nc += len; cc -= len; - } while (error == ENOENT); - if (error) { - if (bp) - brelse(bp); - bp = 0; - goto badarg; - } + } while (error == ENAMETOOLONG); + if (error) + goto bad; } - if (bp) - bdwrite(bp); - bp = 0; - nc = (nc + NBPW-1) & ~(NBPW-1); - error = getxfile(p, vp, &exdata.ex_exec, flags, nc + (na+4)*NBPW, - uid, gid); - if (error) { -badarg: - for (cc = 0; cc < nc; cc += CLBYTES) { - (void) baddr(argdev_vp, bno + ctod(cc/NBPG), - CLBYTES, NOCRED, &tbp); - bp = tbp; -#endif SECSIZE - if (bp) { - bp->b_flags |= B_INVAL; /* throw away */ - brelse(bp); - bp = 0; - } - } + + /* + * XXX the following is excessively bogus + * + * Compute initial process stack size and location of argc + * and character strings. `nc' is currently just the number + * of characters of arg and env strings. + * + * nc = size of ps_strings structure + + * size of signal code + + * 4 bytes of NULL pointer + + * nc, + * rounded to nearest integer; + * ucp = USRSTACK - nc; [user characters pointer] + * apsize = padding (if any) + + * 4 bytes of NULL pointer + + * ne 4-byte pointers to env strings + + * 4 bytes of NULL pointer + + * (na-ne) 4-byte pointers to arg strings + + * 4 bytes of argc; + * (this is the same as nc + (na+3)*4) + * ap = ucp - apsize; [user address of argc] + * ssize = ssize + nc + machine-dependent space; + */ + nc = (sizeof(ps) + szsigcode + 4 + nc + NBPW-1) & ~(NBPW - 1); +#ifdef sparc + ucp = USRSTACK; + ssize = (nc + (na + 3) * NBPW + 7) & ~7; + ap = ucp - ssize; + ucp -= nc; + ssize += sizeof(struct rwindow); +#else + ssize = (na + 3) * NBPW; + ucp = USRSTACK - nc; + ap = ucp - ssize; + ssize += nc; +#endif + error = getxfile(p, vp, &exdata.ex_exec, paged, ssize, uid, gid); + if (error) goto bad; - } - if (vp->v_text) - vp->v_text->x_mtime = vattr.va_mtime.tv_sec; vput(vp); vp = NULL; @@ -429,92 +416,85 @@ badarg: * We are now committed to the exec so we can save the exec * header in the pcb where we can dump it if necessary in core() */ - if (u.u_pcb.pcb_flags & PCB_HPUXBIN) + if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXBIN) bcopy((caddr_t)&hhead, - (caddr_t)u.u_pcb.pcb_exec, sizeof hhead); + (caddr_t)p->p_addr->u_pcb.pcb_exec, sizeof hhead); #endif /* * Copy back arglist. */ - ucp = USRSTACK - nc - NBPW; - ap = ucp - na*NBPW - 3*NBPW; - u.u_ar0[SP] = ap; + cpu_setstack(p, ap); (void) suword((caddr_t)ap, na-ne); nc = 0; - cc = 0; + cp = (char *) execargs; + cc = NCARGS; + ps.ps_argvstr = (char *)ucp; /* first argv string */ + ps.ps_nargvstr = na - ne; /* argc */ for (;;) { ap += NBPW; if (na == ne) { (void) suword((caddr_t)ap, 0); ap += NBPW; + ps.ps_envstr = (char *)ucp; + ps.ps_nenvstr = ne; } if (--na < 0) break; (void) suword((caddr_t)ap, ucp); do { - if (cc <= 0) { - if (bp) - brelse(bp); - cc = CLBYTES; -#ifdef SECSIZE - bp = bread(argdev, bno + nc / argdbsize, cc, - argdbsize); -#else SECSIZE - error = bread(argdev_vp, - (daddr_t)(bno + ctod(nc / NBPG)), cc, - NOCRED, &tbp); - bp = tbp; -#endif SECSIZE - bp->b_flags |= B_INVAL; /* throw away */ - cp = bp->b_un.b_addr; - } error = copyoutstr(cp, (caddr_t)ucp, (unsigned)cc, &len); ucp += len; cp += len; nc += len; cc -= len; - } while (error == ENOENT); + } while (error == ENAMETOOLONG); if (error == EFAULT) panic("exec: EFAULT"); } (void) suword((caddr_t)ap, 0); + (void) copyout((caddr_t)&ps, (caddr_t)PS_STRINGS, sizeof(ps)); execsigs(p); - for (nc = u.u_lastfile; nc >= 0; --nc) { - if (u.u_pofile[nc] & UF_EXCLOSE) { - (void) closef(u.u_ofile[nc]); - u.u_ofile[nc] = NULL; - u.u_pofile[nc] = 0; + for (nc = fdp->fd_lastfile; nc >= 0; --nc) { + if (fdp->fd_ofileflags[nc] & UF_EXCLOSE) { + (void) closef(fdp->fd_ofiles[nc], p); + fdp->fd_ofiles[nc] = NULL; + fdp->fd_ofileflags[nc] = 0; + if (nc < fdp->fd_freefile) + fdp->fd_freefile = nc; } - u.u_pofile[nc] &= ~UF_MAPPED; + fdp->fd_ofileflags[nc] &= ~UF_MAPPED; } - while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL) - u.u_lastfile--; - setregs(exdata.ex_exec.a_entry, retval); + /* + * Adjust fd_lastfile to account for descriptors closed above. + * Don't decrement fd_lastfile past 0, as it's unsigned. + */ + while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL) + fdp->fd_lastfile--; + setregs(p, exdata.ex_exec.a_entry, retval); +#ifdef COPY_SIGCODE + /* + * Install sigcode at top of user stack. + */ + copyout((caddr_t)sigcode, (caddr_t)PS_STRINGS - szsigcode, szsigcode); +#endif /* * Remember file name for accounting. */ - u.u_acflag &= ~AFORK; - if (indir) - bcopy((caddr_t)cfname, (caddr_t)p->p_comm, MAXCOMLEN); - else { - if (ndp->ni_dent.d_namlen > MAXCOMLEN) - ndp->ni_dent.d_namlen = MAXCOMLEN; - bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)p->p_comm, - (unsigned)(ndp->ni_dent.d_namlen + 1)); - } + p->p_acflag &= ~AFORK; + if (nd.ni_cnd.cn_namelen > MAXCOMLEN) + nd.ni_cnd.cn_namelen = MAXCOMLEN; + bcopy((caddr_t)nd.ni_cnd.cn_nameptr, (caddr_t)p->p_comm, + (unsigned)nd.ni_cnd.cn_namelen); + p->p_comm[nd.ni_cnd.cn_namelen] = '\0'; + cpu_exec(p); bad: - if (bp) - brelse(bp); - if (bno) -#ifdef SECSIZE - rmfree(argmap, (clrnd((int)btoc(NCARGS))) * CLBYTES / argdbsize, - bno); -#else SECSIZE - rmfree(argmap, (long)ctod(clrnd((int) btoc(NCARGS))), bno); + FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI); + if (execargs) + kmem_free_wakeup(exec_map, execargs, NCARGS); #endif SECSIZE if (vp) vput(vp); @@ -524,149 +504,231 @@ bad: /* * Read in and set up memory for executed file. */ -getxfile(p, vp, ep, flags, nargc, uid, gid) +getxfile(p, vp, ep, paged, ssize, uid, gid) register struct proc *p; register struct vnode *vp; register struct exec *ep; - int flags, nargc, uid, gid; + int paged, ssize, uid, gid; { - segsz_t ts, ds, ids, uds, ss; - register struct ucred *cred = u.u_cred; + register struct ucred *cred = p->p_ucred; + register struct vmspace *vm = p->p_vmspace; + vm_offset_t addr; + vm_size_t xts, size; + segsz_t ds; off_t toff; - int error; + int error = 0; #ifdef HPUXCOMPAT + int hpux = (paged & SHPUX); + paged &= ~SHPUX; if (ep->a_mid == MID_HPUX) - toff = sizeof (struct hpux_exec); + toff = paged ? CLBYTES : sizeof(struct hpux_exec); else #endif - toff = sizeof (struct exec); - if (vp->v_text && (vp->v_text->x_flag & XTRC)) - return (ETXTBSY); +#ifdef COFF + toff = N_TXTOFF(*ep); +#else +#ifdef sparc + if (ep->a_mid == MID_SUN_SPARC) + toff = paged ? 0 : sizeof(struct exec); + else +#endif + if (paged) + toff = CLBYTES; + else + toff = sizeof (struct exec); +#endif if (ep->a_text != 0 && (vp->v_flag & VTEXT) == 0 && - vp->v_usecount != 1) { - register struct file *fp; - - for (fp = file; fp < fileNFILE; fp++) { - if (fp->f_type == DTYPE_VNODE && - fp->f_count > 0 && - (struct vnode *)fp->f_data == vp && - (fp->f_flag & FWRITE)) { - return (ETXTBSY); - } - } - } + vp->v_writecount != 0) + return (ETXTBSY); /* * Compute text and data sizes and make sure not too large. - * NB - Check data and bss separately as they may overflow - * when summed together. + * Text size is rounded to an ``ld page''; data+bss is left + * in machine pages. Check data and bss separately as they + * may overflow when summed together. (XXX not done yet) */ - ts = clrnd(btoc(ep->a_text)); - ids = clrnd(btoc(ep->a_data)); - uds = clrnd(btoc(ep->a_bss)); + xts = roundup(ep->a_text, __LDPGSZ); ds = clrnd(btoc(ep->a_data + ep->a_bss)); - ss = clrnd(SSIZE + btoc(nargc)); - if (error = - chksize((unsigned)ts, (unsigned)ids, (unsigned)uds, (unsigned)ss)) - return (error); /* - * Make sure enough space to start process. + * If we're sharing the address space, allocate a new space + * and release our reference to the old one. Otherwise, + * empty out the existing vmspace. */ - u.u_cdmap = zdmap; - u.u_csmap = zdmap; - if (error = swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap)) - return (error); - - /* - * At this point, we are committed to the new image! - * Release virtual memory resources of old process, and - * initialize the virtual memory of the new process. - * If we resulted from vfork(), instead wakeup our - * parent who will set SVFDONE when he has taken back - * our resources. - */ - if ((p->p_flag & SVFORK) == 0) { -#ifdef MAPMEM - if (u.u_mmap && (error = mmexec(p))) - return (error); +#ifdef sparc + kill_user_windows(p); /* before addrs go away */ #endif - vrelvm(); + if (vm->vm_refcnt > 1) { + p->p_vmspace = vmspace_alloc(VM_MIN_ADDRESS, + VM_MAXUSER_ADDRESS, 1); + vmspace_free(vm); + vm = p->p_vmspace; } else { - p->p_flag &= ~SVFORK; - p->p_flag |= SKEEP; - wakeup((caddr_t)p); - while ((p->p_flag & SVFDONE) == 0) - sleep((caddr_t)p, PZERO - 1); - p->p_flag &= ~(SVFDONE|SKEEP); +#ifdef SYSVSHM + if (vm->vm_shm) + shmexit(p); +#endif + (void) vm_map_remove(&vm->vm_map, VM_MIN_ADDRESS, + VM_MAXUSER_ADDRESS); + } + /* + * If parent is waiting for us to exec or exit, + * SPPWAIT will be set; clear it and wakeup parent. + */ + if (p->p_flag & SPPWAIT) { + p->p_flag &= ~SPPWAIT; + wakeup((caddr_t) p->p_pptr); } -#ifdef hp300 - u.u_pcb.pcb_flags &= ~(PCB_AST|PCB_HPUXMMAP|PCB_HPUXBIN); #ifdef HPUXCOMPAT + p->p_addr->u_pcb.pcb_flags &= ~(PCB_HPUXMMAP|PCB_HPUXBIN); /* remember that we were loaded from an HPUX format file */ if (ep->a_mid == MID_HPUX) - u.u_pcb.pcb_flags |= PCB_HPUXBIN; -#endif + p->p_addr->u_pcb.pcb_flags |= PCB_HPUXBIN; + if (hpux) + p->p_flag |= SHPUX; + else + p->p_flag &= ~SHPUX; #endif - p->p_flag &= ~(SPAGV|SSEQL|SUANOM|SHPUX); - p->p_flag |= flags | SEXEC; - u.u_dmap = u.u_cdmap; - u.u_smap = u.u_csmap; - vgetvm(ts, ds, ss); - - if ((flags & SPAGV) == 0) - (void) vn_rdwr(UIO_READ, vp, - (char *)ctob(dptov(p, 0)), - (int)ep->a_data, - (off_t)(toff + ep->a_text), - UIO_USERSPACE, (IO_UNIT|IO_NODELOCKED), cred, (int *)0); - xalloc(vp, ep, toff, cred); -#if defined(tahoe) +#ifdef ULTRIXCOMPAT /* - * Define new keys. + * Always start out as an ULTRIX process. + * A system call in crt0.o will change us to BSD system calls later. */ - if (p->p_textp == 0) { /* use existing code key if shared */ - ckeyrelease(p->p_ckey); - p->p_ckey = getcodekey(); + p->p_md.md_flags |= MDP_ULTRIX; +#endif + p->p_flag |= SEXEC; +#ifndef COFF + addr = VM_MIN_ADDRESS; + if (vm_allocate(&vm->vm_map, &addr, xts + ctob(ds), FALSE)) { + uprintf("Cannot allocate text+data space\n"); + error = ENOMEM; /* XXX */ + goto badmap; + } + vm->vm_taddr = (caddr_t)VM_MIN_ADDRESS; + vm->vm_daddr = (caddr_t)(VM_MIN_ADDRESS + xts); +#else /* COFF */ + addr = (vm_offset_t)ep->ex_aout.codeStart; + vm->vm_taddr = (caddr_t)addr; + if (vm_allocate(&vm->vm_map, &addr, xts, FALSE)) { + uprintf("Cannot allocate text space\n"); + error = ENOMEM; /* XXX */ + goto badmap; } - mtpr(CCK, p->p_ckey); - dkeyrelease(p->p_dkey); - p->p_dkey = getdatakey(); - mtpr(DCK, p->p_dkey); + addr = (vm_offset_t)ep->ex_aout.heapStart; + vm->vm_daddr = (caddr_t)addr; + if (vm_allocate(&vm->vm_map, &addr, round_page(ctob(ds)), FALSE)) { + uprintf("Cannot allocate data space\n"); + error = ENOMEM; /* XXX */ + goto badmap; + } +#endif /* COFF */ + size = round_page(MAXSSIZ); /* XXX */ +#ifdef i386 + addr = trunc_page(USRSTACK - size) - NBPG; /* XXX */ +#else + addr = trunc_page(USRSTACK - size); #endif - if ((flags & SPAGV) && p->p_textp) - vinifod(p, (struct fpte *)dptopte(p, 0), - PG_FTEXT, p->p_textp->x_vptr, - (long)(1 + ts/CLSIZE), (segsz_t)btoc(ep->a_data)); + if (vm_allocate(&vm->vm_map, &addr, size, FALSE)) { + uprintf("Cannot allocate stack space\n"); + error = ENOMEM; /* XXX */ + goto badmap; + } + size -= round_page(p->p_rlimit[RLIMIT_STACK].rlim_cur); + if (vm_map_protect(&vm->vm_map, addr, addr+size, VM_PROT_NONE, FALSE)) { + uprintf("Cannot protect stack space\n"); + error = ENOMEM; + goto badmap; + } + vm->vm_maxsaddr = (caddr_t)addr; -#if defined(vax) || defined(tahoe) - /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */ - mtpr(TBIA, 0); -#endif -#ifdef hp300 - TBIAU(); -#endif + if (paged == 0) { + /* + * Read in data segment. + */ + (void) vn_rdwr(UIO_READ, vp, vm->vm_daddr, (int) ep->a_data, + (off_t)(toff + ep->a_text), UIO_USERSPACE, + (IO_UNIT|IO_NODELOCKED), cred, (int *)0, p); + /* + * Read in text segment if necessary (0410), + * and read-protect it. + */ + if (ep->a_text > 0) { + error = vn_rdwr(UIO_READ, vp, vm->vm_taddr, + (int)ep->a_text, toff, UIO_USERSPACE, + (IO_UNIT|IO_NODELOCKED), cred, (int *)0, p); + (void) vm_map_protect(&vm->vm_map, + (vm_offset_t)vm->vm_taddr, + (vm_offset_t)vm->vm_taddr + trunc_page(ep->a_text), + VM_PROT_READ|VM_PROT_EXECUTE, FALSE); + } + } else { + /* + * Allocate a region backed by the exec'ed vnode. + */ +#ifndef COFF + addr = VM_MIN_ADDRESS; + size = round_page(xts + ep->a_data); + error = vm_mmap(&vm->vm_map, &addr, size, VM_PROT_ALL, + MAP_FILE|MAP_COPY|MAP_FIXED, + (caddr_t)vp, (vm_offset_t)toff); + (void) vm_map_protect(&vm->vm_map, addr, addr + xts, + VM_PROT_READ|VM_PROT_EXECUTE, FALSE); +#else /* COFF */ + addr = (vm_offset_t)vm->vm_taddr; + size = xts; + error = vm_mmap(&vm->vm_map, &addr, size, + VM_PROT_READ|VM_PROT_EXECUTE, + MAP_FILE|MAP_COPY|MAP_FIXED, + (caddr_t)vp, (vm_offset_t)toff); + toff += size; + addr = (vm_offset_t)vm->vm_daddr; + size = round_page(ep->a_data); + error = vm_mmap(&vm->vm_map, &addr, size, VM_PROT_ALL, + MAP_FILE|MAP_COPY|MAP_FIXED, + (caddr_t)vp, (vm_offset_t)toff); +#endif /* COFF */ + vp->v_flag |= VTEXT; + } + if (error) { +badmap: + printf("pid %d: VM allocation failure\n", p->p_pid); + uprintf("sorry, pid %d was killed in exec: VM allocation\n", + p->p_pid); + psignal(p, SIGKILL); + p->p_flag |= SKEEP; + return(error); + } /* * set SUID/SGID protections, if no tracing */ if ((p->p_flag&STRC)==0) { - if (uid != cred->cr_uid || gid != cred->cr_gid) - u.u_cred = cred = crcopy(cred); - cred->cr_uid = uid; - cred->cr_gid = gid; - p->p_uid = uid; + if (uid != cred->cr_uid || gid != cred->cr_gid) { + p->p_ucred = cred = crcopy(cred); + /* + * If process is being ktraced, turn off - unless + * root set it. + */ + if (p->p_tracep && !(p->p_traceflag & KTRFAC_ROOT)) { + vrele(p->p_tracep); + p->p_tracep = NULL; + p->p_traceflag = 0; + } + cred->cr_uid = uid; + cred->cr_gid = gid; + } } else psignal(p, SIGTRAP); - p->p_svuid = p->p_uid; - p->p_svgid = cred->cr_gid; - u.u_tsize = ts; - u.u_dsize = ds; - u.u_ssize = ss; - u.u_prof.pr_scale = 0; + p->p_cred->p_svuid = cred->cr_uid; + p->p_cred->p_svgid = cred->cr_gid; + vm->vm_tsize = btoc(xts); + vm->vm_dsize = ds; + vm->vm_ssize = ssize; + p->p_stats->p_prof.pr_scale = 0; #if defined(tahoe) - u.u_pcb.pcb_savacc.faddr = (float *)NULL; + /* move this when tahoe cpu_exec is created */ + p->p_addr->u_pcb.pcb_savacc.faddr = (float *)NULL; #endif return (0); }