X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/c4ec2128657d70754f3fc07957ee8b72793dd47c..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 d4499f7822..4d27e87769 100644 --- a/usr/src/sys/kern/kern_exec.c +++ b/usr/src/sys/kern/kern_exec.c @@ -1,106 +1,109 @@ -/* - * 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. * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * %sccs.include.proprietary.c% * - * @(#)kern_exec.c 7.10 (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" -/* - * exec system call, with and without environments. - */ -struct execa { - char *fname; - char **argp; - char **envp; -}; +#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" -execv() -{ - ((struct execa *)u.u_ap)->envp = NULL; - execve(); -} +#include "signalvar.h" +#include "kinfo_proc.h" + +#ifdef HPUXCOMPAT +#include "user.h" /* for pcb */ +#include "hp300/hpux/hpux_exec.h" +#endif -execve() +#ifdef COPY_SIGCODE +extern char sigcode[], esigcode[]; +#define szsigcode (esigcode - sigcode) +#else +#define szsigcode 0 +#endif + +/* + * exec system call + */ +/* ARGSUSED */ +execve(p, uap, retval) + register struct proc *p; + register struct args { + char *fname; + char **argp; + char **envp; + } *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; - register struct execa *uap; - 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 */ struct exec ex_exec; +#ifdef HPUXCOMPAT + struct hpux_exec ex_hexec; +#endif } exdata; - register struct nameidata *ndp = &u.u_nd; - int resid, error; +#ifdef HPUXCOMPAT + struct hpux_exec hhead; +#endif + struct nameidata nd; + struct ps_strings ps; #ifdef SECSIZE extern long argdbsize; /* XXX */ #endif SECSIZE - ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; - ndp->ni_segflg = UIO_USERSPACE; - ndp->ni_dirp = ((struct execa *)u.u_ap)->fname; - if (u.u_error = namei(ndp)) { - return; - } - vp = ndp->ni_vp; - bno = 0; - bp = 0; + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | SAVENAME, UIO_USERSPACE, + uap->fname, p); + if (error = namei(&nd)) + return (error); + vp = nd.ni_vp; indir = 0; - uid = u.u_uid; - gid = u.u_gid; - if (u.u_error = VOP_GETATTR(vp, &vattr, u.u_cred)) + uid = cred->cr_uid; + gid = cred->cr_gid; + if (error = VOP_GETATTR(vp, &vattr, cred, p)) goto bad; - if (vp->v_mount->m_flag & M_NOEXEC) { - u.u_error = ENOEXEC; + if (vp->v_mount->mnt_flag & MNT_NOEXEC) { + error = EACCES; goto bad; } - if ((vp->v_mount->m_flag & M_NOSUID) == 0) { + if ((vp->v_mount->mnt_flag & MNT_NOSUID) == 0) { if (vattr.va_mode & VSUID) uid = vattr.va_uid; if (vattr.va_mode & VSGID) @@ -108,14 +111,13 @@ execve() } again: - if (u.u_error = vn_access(vp, VEXEC, u.u_cred)) + if (error = VOP_ACCESS(vp, VEXEC, cred, p)) goto bad; - if ((u.u_procp->p_flag & STRC) && - (u.u_error = vn_access(vp, VREAD, u.u_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) { - u.u_error = EACCES; + error = EACCES; goto bad; } @@ -134,28 +136,124 @@ execve() * THE ASCII LINE. */ exdata.ex_shell[0] = '\0'; /* for zero length files */ - u.u_error = vn_rdwr(UIO_READ, vp, (caddr_t)&exdata, sizeof (exdata), - (off_t)0, UIO_SYSSPACE, (IO_UNIT|IO_NODELOCKED), u.u_cred, &resid); - if (u.u_error) + error = vn_rdwr(UIO_READ, vp, (caddr_t)&exdata, sizeof (exdata), + (off_t)0, UIO_SYSSPACE, (IO_UNIT|IO_NODELOCKED), cred, &resid, + (struct proc *)0); + if (error) goto bad; #ifndef lint if (resid > sizeof(exdata) - sizeof(exdata.ex_exec) && exdata.ex_shell[0] != '#') { - u.u_error = ENOEXEC; + error = ENOEXEC; goto bad; } +#endif +#if defined(hp300) + switch ((int)exdata.ex_exec.a_mid) { + + /* + * An ancient hp200 or hp300 binary, shouldn't happen anymore. + * Mark as invalid. + */ + case MID_ZERO: + exdata.ex_exec.a_magic = 0; + break; + + /* + * HP200 series has a smaller page size so we cannot + * demand-load or even write protect text, so we just + * treat as OMAGIC. + */ + case MID_HP200: + exdata.ex_exec.a_magic = OMAGIC; + break; + + case MID_HP300: + break; + +#ifdef HPUXCOMPAT + case MID_HPUX: + /* + * Save a.out header. This is eventually saved in the pcb, + * but we cannot do that yet in case the exec fails before + * the image is overlayed. + */ + bcopy((caddr_t)&exdata.ex_hexec, + (caddr_t)&hhead, sizeof hhead); + /* + * If version number is 0x2bad this is a native BSD + * binary created via the HPUX SGS. Should not be + * treated as an HPUX binary. + */ + if (exdata.ex_hexec.ha_version != BSDVNUM) + paged |= SHPUX; /* XXX */ + /* + * Shuffle important fields to their BSD locations. + * Note that the order in which this is done is important. + */ + exdata.ex_exec.a_text = exdata.ex_hexec.ha_text; + exdata.ex_exec.a_data = exdata.ex_hexec.ha_data; + exdata.ex_exec.a_bss = exdata.ex_hexec.ha_bss; + exdata.ex_exec.a_entry = exdata.ex_hexec.ha_entry; + /* + * For ZMAGIC files, make sizes consistant with those + * generated by BSD ld. + */ + if (exdata.ex_exec.a_magic == ZMAGIC) { + exdata.ex_exec.a_text = + ctob(btoc(exdata.ex_exec.a_text)); + nc = exdata.ex_exec.a_data + exdata.ex_exec.a_bss; + exdata.ex_exec.a_data = + ctob(btoc(exdata.ex_exec.a_data)); + nc -= (int)exdata.ex_exec.a_data; + exdata.ex_exec.a_bss = (nc < 0) ? 0 : nc; + } + break; +#endif + } #endif 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: +#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) { - u.u_error = ENOEXEC; + error = ENOEXEC; goto bad; } break; @@ -164,12 +262,12 @@ execve() if (exdata.ex_shell[0] != '#' || exdata.ex_shell[1] != '!' || indir) { - u.u_error = ENOEXEC; + error = ENOEXEC; goto bad; } for (cp = &exdata.ex_shell[2];; ++cp) { if (cp >= &exdata.ex_shell[MAXINTERP]) { - u.u_error = ENOEXEC; + error = ENOEXEC; goto bad; } if (*cp == '\n') { @@ -182,7 +280,7 @@ execve() cp = &exdata.ex_shell[2]; while (*cp == ' ') cp++; - ndp->ni_dirp = cp; + nd.ni_dirp = cp; while (*cp && *cp != ' ') cp++; cfarg[0] = '\0'; @@ -195,18 +293,14 @@ execve() } indir = 1; vput(vp); - ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; - ndp->ni_segflg = UIO_SYSSPACE; - if (u.u_error = namei(ndp)) - return; - vp = ndp->ni_vp; - if (u.u_error = VOP_GETATTR(vp, &vattr, u.u_cred)) + nd.ni_segflg = UIO_SYSSPACE; + if (error = namei(&nd)) + return (error); + 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 = u.u_uid; /* shell scripts can't be setuid */ - gid = u.u_gid; + uid = cred->cr_uid; /* shell scripts can't be setuid */ + gid = cred->cr_gid; goto again; } @@ -216,19 +310,13 @@ execve() na = 0; ne = 0; nc = 0; - cc = 0; - uap = (struct execa *)u.u_ap; -#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(u.u_procp, "exec: no swap space"); - goto bad; - } - if (bno % CLSIZE) - panic("execa rmalloc"); + 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. */ @@ -236,7 +324,7 @@ execve() 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])) { @@ -257,30 +345,13 @@ execve() break; na++; if (ap == -1) { - u.u_error = EFAULT; - break; + error = EFAULT; + 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); @@ -293,270 +364,371 @@ execve() cp += len; nc += len; cc -= len; - } while (error == ENOENT); - if (error) { - u.u_error = 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); - getxfile(vp, &exdata.ex_exec, nc + (na+4)*NBPW, uid, gid, u.u_cred); - if (u.u_error) { -badarg: - for (cc = 0; cc < nc; cc += CLBYTES) { - u.u_error = baddr(argdev_vp, bno + ctod(cc/NBPG), - CLBYTES, &tbp); - bp = tbp; -#endif SECSIZE - if (bp) { - bp->b_flags |= B_AGE; /* throw away */ - bp->b_flags &= ~B_DELWRI; /* cancel io */ - 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; - } vput(vp); vp = NULL; +#ifdef HPUXCOMPAT + /* + * 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 (p->p_addr->u_pcb.pcb_flags & PCB_HPUXBIN) + bcopy((caddr_t)&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, &tbp); - bp = tbp; -#endif SECSIZE - bp->b_flags |= B_AGE; /* throw away */ - bp->b_flags &= ~B_DELWRI; /* cancel io */ - 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 = 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; + } + fdp->fd_ofileflags[nc] &= ~UF_MAPPED; + } /* - * Reset caught signals. Held signals - * remain held through p_sigmask. + * Adjust fd_lastfile to account for descriptors closed above. + * Don't decrement fd_lastfile past 0, as it's unsigned. */ - while (u.u_procp->p_sigcatch) { - nc = ffs((long)u.u_procp->p_sigcatch); - u.u_procp->p_sigcatch &= ~sigmask(nc); - u.u_signal[nc] = SIG_DFL; - } + 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 /* - * Reset stack state to the user stack. - * Clear set of signals caught on the signal stack. + * Install sigcode at top of user stack. */ - u.u_onstack = 0; - u.u_sigsp = 0; - u.u_sigonstack = 0; - - for (nc = u.u_lastfile; nc >= 0; --nc) { - if (u.u_pofile[nc] & UF_EXCLOSE) { - closef(u.u_ofile[nc]); - u.u_ofile[nc] = NULL; - u.u_pofile[nc] = 0; - } - u.u_pofile[nc] &= ~UF_MAPPED; - } - while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL) - u.u_lastfile--; - setregs(exdata.ex_exec.a_entry); + 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)u.u_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)u.u_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); + return (error); } /* * Read in and set up memory for executed file. */ -getxfile(vp, ep, nargc, uid, gid, cred) +getxfile(p, vp, ep, paged, ssize, uid, gid) + register struct proc *p; register struct vnode *vp; register struct exec *ep; - int nargc, uid, gid; - struct ucred *cred; + int paged, ssize, uid, gid; { - size_t ts, ds, ids, uds, ss; - int pagi; + 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 = 0; - if (ep->a_magic == ZMAGIC) - pagi = SPAGV; +#ifdef HPUXCOMPAT + int hpux = (paged & SHPUX); + paged &= ~SHPUX; + if (ep->a_mid == MID_HPUX) + toff = paged ? CLBYTES : sizeof(struct hpux_exec); else - pagi = 0; - if (vp->v_text && (vp->v_text->x_flag & XTRC)) { - u.u_error = ETXTBSY; - goto bad; - } +#endif +#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_count != 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)) { - u.u_error = ETXTBSY; - goto bad; - } - } - } + 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 (chksize((unsigned)ts, (unsigned)ids, (unsigned)uds, (unsigned)ss)) - goto bad; /* - * 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 (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL) - goto bad; - +#ifdef sparc + kill_user_windows(p); /* before addrs go away */ +#endif + 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 { +#ifdef SYSVSHM + if (vm->vm_shm) + shmexit(p); +#endif + (void) vm_map_remove(&vm->vm_map, VM_MIN_ADDRESS, + VM_MAXUSER_ADDRESS); + } /* - * 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 parent is waiting for us to exec or exit, + * SPPWAIT will be set; clear it and wakeup parent. */ - if ((u.u_procp->p_flag & SVFORK) == 0) - vrelvm(); - else { - u.u_procp->p_flag &= ~SVFORK; - u.u_procp->p_flag |= SKEEP; - wakeup((caddr_t)u.u_procp); - while ((u.u_procp->p_flag & SVFDONE) == 0) - sleep((caddr_t)u.u_procp, PZERO - 1); - u.u_procp->p_flag &= ~(SVFDONE|SKEEP); + if (p->p_flag & SPPWAIT) { + p->p_flag &= ~SPPWAIT; + wakeup((caddr_t) p->p_pptr); } - u.u_procp->p_flag &= ~(SPAGV|SSEQL|SUANOM|SOUSIG); - u.u_procp->p_flag |= pagi | SEXEC; - u.u_dmap = u.u_cdmap; - u.u_smap = u.u_csmap; - vgetvm(ts, ds, ss); - - if (pagi == 0) - u.u_error = vn_rdwr(UIO_READ, vp, - (char *)ctob(dptov(u.u_procp, 0)), - (int)ep->a_data, - (off_t)(sizeof (struct exec) + ep->a_text), - UIO_USERSPACE, (IO_UNIT|IO_NODELOCKED), cred, (int *)0); - xalloc(vp, ep, pagi, cred); -#if defined(tahoe) +#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) + p->p_addr->u_pcb.pcb_flags |= PCB_HPUXBIN; + if (hpux) + p->p_flag |= SHPUX; + else + p->p_flag &= ~SHPUX; +#endif +#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 (u.u_procp->p_textp == 0) { /* use existing code key if shared */ - ckeyrelease(u.u_procp->p_ckey); - u.u_procp->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, u.u_procp->p_ckey); - dkeyrelease(u.u_procp->p_dkey); - u.u_procp->p_dkey = getdatakey(); - mtpr(DCK, u.u_procp->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 (pagi && u.u_procp->p_textp) - vinifod((struct fpte *)dptopte(u.u_procp, 0), - PG_FTEXT, u.u_procp->p_textp->x_vptr, - (long)(1 + ts/CLSIZE), (size_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 + 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); + } - if (u.u_error) - swkill(u.u_procp, "exec: I/O error mapping pages"); /* * set SUID/SGID protections, if no tracing */ - if ((u.u_procp->p_flag&STRC)==0) { - if (uid != u.u_uid || gid != u.u_gid) - u.u_cred = crcopy(u.u_cred); - u.u_uid = uid; - u.u_procp->p_uid = uid; - u.u_gid = gid; + if ((p->p_flag&STRC)==0) { + 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(u.u_procp, SIGTRAP); - u.u_tsize = ts; - u.u_dsize = ds; - u.u_ssize = ss; - u.u_prof.pr_scale = 0; + psignal(p, SIGTRAP); + 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 -bad: - return; + return (0); }