-/* kern_exec.c 6.4 84/07/21 */
+/*-
+ * Copyright (c) 1982, 1986, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.proprietary.c%
+ *
+ * @(#)kern_exec.c 7.55 (Berkeley) %G%
+ */
+
+#include "param.h"
+#include "systm.h"
+#include "filedesc.h"
+#include "kernel.h"
+#include "proc.h"
+#include "mount.h"
+#include "malloc.h"
+#include "namei.h"
+#include "vnode.h"
+#include "file.h"
+#include "acct.h"
+#include "exec.h"
+#include "ktrace.h"
+#include "resourcevar.h"
+
+#include "machine/cpu.h"
+#include "machine/reg.h"
-#include "../machine/reg.h"
-#include "../machine/pte.h"
-#include "../machine/psl.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 "../h/param.h"
-#include "../h/systm.h"
-#include "../h/map.h"
-#include "../h/dir.h"
-#include "../h/user.h"
-#include "../h/kernel.h"
-#include "../h/proc.h"
-#include "../h/buf.h"
-#include "../h/inode.h"
-#include "../h/seg.h"
-#include "../h/vm.h"
-#include "../h/text.h"
-#include "../h/file.h"
-#include "../h/uio.h"
-#include "../h/acct.h"
-#include "../h/exec.h"
+#include "signalvar.h"
+#include "kinfo_proc.h"
+
+#ifdef HPUXCOMPAT
+#include "user.h" /* for pcb */
+#include "hp300/hpux/hpux_exec.h"
+#endif
-#ifdef vax
-#include "../vax/mtpr.h"
+#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
*/
-struct execa {
- char *fname;
- char **argp;
- char **envp;
-};
-
-execv()
-{
- ((struct execa *)u.u_ap)->envp = NULL;
- execve();
-}
-
-execve()
+/* 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;
- register struct execa *uap;
- int na, ne, ucp, ap, c;
+ register int nc;
+ unsigned len;
int indir, uid, gid;
char *sharg;
- struct inode *ip;
- swblk_t bno;
- char cfname[MAXCOMLEN + 1];
-#define SHSIZE 32
- char cfarg[SHSIZE];
+ struct vnode *vp;
+ int resid, error, paged = 0;
+ vm_offset_t execargs = 0;
+ struct vattr vattr;
+ char cfarg[MAXINTERP];
union {
- char ex_shell[SHSIZE]; /* #! and name of interpreter */
+ 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;
+#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;
- ndp->ni_segflg = UIO_USERSPACE;
- ndp->ni_dirp = ((struct execa *)u.u_ap)->fname;
- if ((ip = namei(ndp)) == NULL)
- return;
- 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 (ip->i_mode & ISUID)
- uid = ip->i_uid;
- if (ip->i_mode & ISGID)
- gid = ip->i_gid;
+ uid = cred->cr_uid;
+ gid = cred->cr_gid;
+ if (error = VOP_GETATTR(vp, &vattr, cred, p))
+ goto bad;
+ if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
+ error = EACCES;
+ goto bad;
+ }
+ if ((vp->v_mount->mnt_flag & MNT_NOSUID) == 0) {
+ if (vattr.va_mode & VSUID)
+ uid = vattr.va_uid;
+ if (vattr.va_mode & VSGID)
+ gid = vattr.va_gid;
+ }
again:
- if (access(ip, IEXEC))
+ if (error = VOP_ACCESS(vp, VEXEC, cred, p))
goto bad;
- if ((u.u_procp->p_flag&STRC) && access(ip, IREAD))
+ if ((p->p_flag & STRC) && (error = VOP_ACCESS(vp, VREAD, cred, p)))
goto bad;
- if ((ip->i_mode & IFMT) != IFREG ||
- (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) {
- u.u_error = EACCES;
+ if (vp->v_type != VREG ||
+ (vattr.va_mode & (VEXEC|(VEXEC>>3)|(VEXEC>>6))) == 0) {
+ error = EACCES;
goto bad;
}
/*
- * Read in first few bytes of file for segment sizes, ux_mag:
- * 407 = plain executable
- * 410 = RO text
- * 413 = demand paged RO text
+ * Read in first few bytes of file for segment sizes, magic number:
+ * OMAGIC = plain executable
+ * NMAGIC = RO text
+ * ZMAGIC = demand paged RO text
* Also an ASCII line beginning with #! is
* the file name of a ``shell'' and arguments may be prepended
* to the argument list if given here.
* THE ASCII LINE.
*/
exdata.ex_shell[0] = '\0'; /* for zero length files */
- u.u_error = rdwri(UIO_READ, ip, (caddr_t)&exdata,
- sizeof (struct exec), 0, 1, &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 (struct exec) - sizeof (exdata.ex_exec.a_magic) &&
+ if (resid > sizeof(exdata) - sizeof(exdata.ex_exec) &&
exdata.ex_shell[0] != '#') {
- u.u_error = ENOEXEC;
+ error = ENOEXEC;
goto bad;
}
#endif
- switch (exdata.ex_exec.a_magic) {
+#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 0407:
+ 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 0413:
- case 0410:
+ 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;
if (exdata.ex_shell[0] != '#' ||
exdata.ex_shell[1] != '!' ||
indir) {
- u.u_error = ENOEXEC;
+ error = ENOEXEC;
goto bad;
}
- cp = &exdata.ex_shell[2]; /* skip "#!" */
- while (cp < &exdata.ex_shell[SHSIZE]) {
- if (*cp == '\t')
- *cp = ' ';
- else if (*cp == '\n') {
+ for (cp = &exdata.ex_shell[2];; ++cp) {
+ if (cp >= &exdata.ex_shell[MAXINTERP]) {
+ error = ENOEXEC;
+ goto bad;
+ }
+ if (*cp == '\n') {
*cp = '\0';
break;
}
- cp++;
- }
- if (*cp != '\0') {
- u.u_error = ENOEXEC;
- goto bad;
+ if (*cp == '\t')
+ *cp = ' ';
}
cp = &exdata.ex_shell[2];
while (*cp == ' ')
cp++;
- ndp->ni_dirp = cp;
+ nd.ni_dirp = cp;
while (*cp && *cp != ' ')
cp++;
- sharg = NULL;
+ cfarg[0] = '\0';
if (*cp) {
*cp++ = '\0';
while (*cp == ' ')
cp++;
- if (*cp) {
- bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE);
- sharg = cfarg;
- }
+ if (*cp)
+ bcopy((caddr_t)cp, (caddr_t)cfarg, MAXINTERP);
}
- if (ndp->ni_dent.d_namlen > MAXCOMLEN)
- ndp->ni_dent.d_namlen = MAXCOMLEN;
- bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)cfname,
- (unsigned)(ndp->ni_dent.d_namlen + 1));
- cfname[MAXCOMLEN] = 0;
indir = 1;
- iput(ip);
- ndp->ni_nameiop = LOOKUP | FOLLOW;
- ndp->ni_segflg = UIO_SYSSPACE;
- ip = namei(ndp);
- if (ip == NULL)
- return;
+ vput(vp);
+ 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;
+ uid = cred->cr_uid; /* shell scripts can't be setuid */
+ gid = cred->cr_gid;
goto again;
}
na = 0;
ne = 0;
nc = 0;
- uap = (struct execa *)u.u_ap;
- bno = rmalloc(argmap, (long)ctod(clrnd((int)btoc(NCARGS))));
- if (bno == 0) {
- swkill(u.u_procp, "exece");
- 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.
+ */
if (uap->argp) for (;;) {
ap = NULL;
- if (indir && (na == 1 || na == 2 && sharg))
+ sharg = NULL;
+ if (indir && na == 0) {
+ sharg = nd.ni_cnd.cn_nameptr;
+ ap = (int)sharg;
+ uap->argp++; /* ignore argv[0] */
+ } else if (indir && (na == 1 && cfarg[0])) {
+ sharg = cfarg;
+ ap = (int)sharg;
+ } else if (indir && (na == 1 || na == 2 && cfarg[0]))
ap = (int)uap->fname;
else if (uap->argp) {
ap = fuword((caddr_t)uap->argp);
uap->argp++;
}
- if (ap==NULL && uap->envp) {
+ if (ap == NULL && uap->envp) {
uap->argp = NULL;
- if ((ap = fuword((caddr_t)uap->envp)) == NULL)
- break;
- uap->envp++;
- ne++;
+ if ((ap = fuword((caddr_t)uap->envp)) != NULL)
+ uap->envp++, ne++;
}
if (ap == NULL)
break;
na++;
- if (ap == -1)
- u.u_error = EFAULT;
+ if (ap == -1) {
+ error = EFAULT;
+ goto bad;
+ }
do {
- if (nc >= NCARGS-1)
- u.u_error = E2BIG;
- if (indir && na == 2 && sharg != NULL)
- c = *sharg++ & 0377;
- else if ((c = fubyte((caddr_t)ap++)) < 0)
- u.u_error = EFAULT;
- if (u.u_error) {
- if (bp)
- brelse(bp);
- bp = 0;
- goto badarg;
+ if (nc >= NCARGS-1) {
+ error = E2BIG;
+ break;
}
- if (nc % (CLSIZE*NBPG) == 0) {
- if (bp)
- bdwrite(bp);
- bp = getblk(argdev, bno + ctod(nc / NBPG),
- CLSIZE*NBPG);
- cp = bp->b_un.b_addr;
+ if (sharg) {
+ error = copystr(sharg, cp, (unsigned)cc, &len);
+ sharg += len;
+ } else {
+ error = copyinstr((caddr_t)ap, cp, (unsigned)cc,
+ &len);
+ ap += len;
}
- nc++;
- *cp++ = c;
- } while (c > 0);
- }
- if (bp)
- bdwrite(bp);
- bp = 0;
- nc = (nc + NBPW-1) & ~(NBPW-1);
- if (indir) {
- ndp->ni_dent.d_namlen = strlen(cfname);
- bcopy((caddr_t)cfname, (caddr_t)ndp->ni_dent.d_name,
- (unsigned)(ndp->ni_dent.d_namlen + 1));
+ cp += len;
+ nc += len;
+ cc -= len;
+ } while (error == ENAMETOOLONG);
+ if (error)
+ goto bad;
}
- getxfile(ip, &exdata.ex_exec, nc + (na+4)*NBPW, uid, gid);
- if (u.u_error) {
-badarg:
- for (c = 0; c < nc; c += CLSIZE*NBPG) {
- bp = baddr(argdev, bno + ctod(c / NBPG), CLSIZE*NBPG);
- 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
+ * 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;
+ 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) {
+ 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 (nc % (CLSIZE*NBPG) == 0) {
- if (bp)
- brelse(bp);
- bp = bread(argdev, bno + ctod(nc / NBPG),
- CLSIZE*NBPG);
- bp->b_flags |= B_AGE; /* throw away */
- bp->b_flags &= ~B_DELWRI; /* cancel io */
- cp = bp->b_un.b_addr;
- }
- (void) subyte((caddr_t)ucp++, (c = *cp++));
- nc++;
- } while(c&0377);
+ error = copyoutstr(cp, (caddr_t)ucp, (unsigned)cc,
+ &len);
+ ucp += len;
+ cp += len;
+ nc += len;
+ cc -= len;
+ } while (error == ENAMETOOLONG);
+ if (error == EFAULT)
+ panic("exec: EFAULT");
}
(void) suword((caddr_t)ap, 0);
- setregs(exdata.ex_exec.a_entry);
+ (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;
+ }
+ /*
+ * 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;
- 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)
- rmfree(argmap, (long)ctod(clrnd((int) btoc(NCARGS))), bno);
- iput(ip);
+ 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(ip, ep, nargc, uid, gid)
- register struct inode *ip;
+getxfile(p, vp, ep, paged, ssize, uid, gid)
+ register struct proc *p;
+ register struct vnode *vp;
register struct exec *ep;
- int nargc, uid, gid;
+ int paged, ssize, uid, gid;
{
- register size_t ts, ds, 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 == 0413)
- pagi = SPAGI;
+#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 (ep->a_text != 0 && (ip->i_flag&ITEXT) == 0 &&
- ip->i_count != 1) {
- register struct file *fp;
-
- for (fp = file; fp < fileNFILE; fp++) {
- if (fp->f_type == DTYPE_INODE &&
- fp->f_count > 0 &&
- (struct inode *)fp->f_data == ip &&
- (fp->f_flag&FWRITE)) {
- 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_writecount != 0)
+ return (ETXTBSY);
/*
* Compute text and data sizes and make sure not too large.
+ * 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));
- ds = clrnd(btoc((ep->a_data + ep->a_bss)));
- ss = clrnd(SSIZE + btoc(nargc));
- if (chksize((unsigned)ts, (unsigned)ds, (unsigned)ss))
- goto bad;
+ xts = roundup(ep->a_text, __LDPGSZ);
+ ds = clrnd(btoc(ep->a_data + ep->a_bss));
/*
- * 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, 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 &= ~(SPAGI|SSEQL|SUANOM|SOUSIG);
- u.u_procp->p_flag |= pagi;
- u.u_dmap = u.u_cdmap;
- u.u_smap = u.u_csmap;
- vgetvm(ts, ds, ss);
-
- if (pagi == 0)
- u.u_error =
- rdwri(UIO_READ, ip,
- (char *)ctob(dptov(u.u_procp, 0)),
- (int)ep->a_data,
- (int)(sizeof (struct exec) + ep->a_text),
- 0, (int *)0);
- xalloc(ip, ep, pagi);
- if (pagi && u.u_procp->p_textp)
- vinifod((struct fpte *)dptopte(u.u_procp, 0),
- PG_FTEXT, u.u_procp->p_textp->x_iptr,
- (long)(1 + ts/CLSIZE), (int)btoc(ep->a_data));
-
-#ifdef vax
- /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */
- mtpr(TBIA, 0);
+#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
-
- if (u.u_error)
- swkill(u.u_procp, "i/o error mapping pages");
+#ifdef ULTRIXCOMPAT
/*
- * set SUID/SGID protections, if no tracing
+ * 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_flag&STRC)==0) {
- u.u_uid = uid;
- u.u_procp->p_uid = uid;
- u.u_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;
-bad:
- return;
-}
+ 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;
+ }
+ 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 (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;
-/*
- * Clear registers on exec
- */
-setregs(entry)
- int entry;
-{
- register int i;
- register struct proc *p = u.u_procp;
+ 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);
+ }
/*
- * Reset caught signals. Held signals
- * remain held through p_sigmask.
+ * set SUID/SGID protections, if no tracing
*/
- while (p->p_sigcatch) {
- (void) spl6();
- i = ffs(p->p_sigcatch);
- p->p_sigcatch &= ~(1 << (i - 1));
- u.u_signal[i] = SIG_DFL;
- (void) spl0();
- }
-#ifdef notdef
- /* should pass args to init on the stack */
- for (rp = &u.u_ar0[0]; rp < &u.u_ar0[16];)
- *rp++ = 0;
-#endif
- u.u_ar0[PC] = entry + 2;
- for (i=0; i<NOFILE; i++) {
- if (u.u_pofile[i]&UF_EXCLOSE) {
- closef(u.u_ofile[i]);
- u.u_ofile[i] = NULL;
- u.u_pofile[i] = 0;
+ 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;
}
- u.u_pofile[i] &= ~UF_MAPPED;
- }
+ } else
+ 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)
+ /* move this when tahoe cpu_exec is created */
+ p->p_addr->u_pcb.pcb_savacc.faddr = (float *)NULL;
+#endif
+ return (0);
}