do not panic after modified data found on the freelist
[unix-history] / usr / src / sys / kern / kern_exec.c
index 1d1879f..c14b32a 100644 (file)
@@ -1,9 +1,10 @@
-/*
- * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
- * All rights reserved.  The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+/*-
+ * Copyright (c) 1982, 1986, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.proprietary.c%
  *
  *
- *     @(#)kern_exec.c 7.38 (Berkeley) %G%
+ *     @(#)kern_exec.c 7.47 (Berkeley) %G%
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -13,6 +14,7 @@
 #include "proc.h"
 #include "mount.h"
 #include "malloc.h"
 #include "proc.h"
 #include "mount.h"
 #include "malloc.h"
+#include "namei.h"
 #include "vnode.h"
 #include "seg.h"
 #include "file.h"
 #include "vnode.h"
 #include "seg.h"
 #include "file.h"
@@ -21,6 +23,7 @@
 #include "ktrace.h"
 #include "resourcevar.h"
 
 #include "ktrace.h"
 #include "resourcevar.h"
 
+#include "machine/cpu.h"
 #include "machine/reg.h"
 
 #include "mman.h"
 #include "machine/reg.h"
 
 #include "mman.h"
 
 #include "signalvar.h"
 #include "kinfo_proc.h"
 
 #include "signalvar.h"
 #include "kinfo_proc.h"
-#include "user.h"                      /* for pcb, sigc */
 
 #ifdef HPUXCOMPAT
 
 #ifdef HPUXCOMPAT
+#include "user.h"                      /* for pcb */
 #include "hp300/hpux/hpux_exec.h"
 #endif
 
 #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
  */
 /*
  * exec system call
  */
@@ -61,10 +71,9 @@ execve(p, uap, retval)
        int indir, uid, gid;
        char *sharg;
        struct vnode *vp;
        int indir, uid, gid;
        char *sharg;
        struct vnode *vp;
-       int resid, error, flags = 0;
+       int resid, error, paged = 0;
        vm_offset_t execargs;
        struct vattr vattr;
        vm_offset_t execargs;
        struct vattr vattr;
-       char cfname[MAXCOMLEN + 1];
        char cfarg[MAXINTERP];
        union {
                char    ex_shell[MAXINTERP];    /* #! and interpreter name */
        char cfarg[MAXINTERP];
        union {
                char    ex_shell[MAXINTERP];    /* #! and interpreter name */
@@ -82,8 +91,7 @@ execve(p, uap, retval)
 #endif SECSIZE
 
        ndp = &nd;
 #endif SECSIZE
 
        ndp = &nd;
-  start:
-       ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
+       ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF | SAVENAME;
        ndp->ni_segflg = UIO_USERSPACE;
        ndp->ni_dirp = uap->fname;
        if (error = namei(ndp, p))
        ndp->ni_segflg = UIO_USERSPACE;
        ndp->ni_dirp = uap->fname;
        if (error = namei(ndp, p))
@@ -92,7 +100,7 @@ execve(p, uap, retval)
        indir = 0;
        uid = cred->cr_uid;
        gid = cred->cr_gid;
        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;
                goto bad;
        if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
                error = EACCES;
@@ -106,9 +114,9 @@ execve(p, uap, retval)
        }
 
   again:
        }
 
   again:
-       if (error = VOP_ACCESS(vp, VEXEC, cred))
+       if (error = VOP_ACCESS(vp, VEXEC, cred, p))
                goto bad;
                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) {
                goto bad;
        if (vp->v_type != VREG ||
            (vattr.va_mode & (VEXEC|(VEXEC>>3)|(VEXEC>>6))) == 0) {
@@ -132,7 +140,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),
         */
        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
        if (error)
                goto bad;
 #ifndef lint
@@ -180,7 +189,7 @@ execve(p, uap, retval)
                 * treated as an HPUX binary.
                 */
                if (exdata.ex_hexec.ha_version != BSDVNUM)
                 * 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.
                /*
                 * Shuffle important fields to their BSD locations.
                 * Note that the order in which this is done is important.
@@ -214,7 +223,8 @@ execve(p, uap, retval)
                break;
 
        case ZMAGIC:
                break;
 
        case ZMAGIC:
-               flags |= SPAGV;
+               paged++;
+               /* FALLTHROUGH */
        case NMAGIC:
                if (exdata.ex_exec.a_text == 0) {
                        error = ENOEXEC;
        case NMAGIC:
                if (exdata.ex_exec.a_text == 0) {
                        error = ENOEXEC;
@@ -257,16 +267,12 @@ execve(p, uap, retval)
                }
                indir = 1;
                vput(vp);
                }
                indir = 1;
                vput(vp);
-               ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
                ndp->ni_segflg = UIO_SYSSPACE;
                if (error = namei(ndp, p))
                        return (error);
                vp = ndp->ni_vp;
                ndp->ni_segflg = UIO_SYSSPACE;
                if (error = namei(ndp, p))
                        return (error);
                vp = ndp->ni_vp;
-               if (error = VOP_GETATTR(vp, &vattr, cred))
+               if (error = VOP_GETATTR(vp, &vattr, cred, p))
                        goto bad;
                        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;
                uid = cred->cr_uid;     /* shell scripts can't be setuid */
                gid = cred->cr_gid;
                goto again;
@@ -288,7 +294,7 @@ execve(p, uap, retval)
                ap = NULL;
                sharg = NULL;
                if (indir && na == 0) {
                ap = NULL;
                sharg = NULL;
                if (indir && na == 0) {
-                       sharg = cfname;
+                       sharg = ndp->ni_ptr;
                        ap = (int)sharg;
                        uap->argp++;            /* ignore argv[0] */
                } else if (indir && (na == 1 && cfarg[0])) {
                        ap = (int)sharg;
                        uap->argp++;            /* ignore argv[0] */
                } else if (indir && (na == 1 && cfarg[0])) {
@@ -333,7 +339,7 @@ execve(p, uap, retval)
                        goto bad;
        }
        nc = (nc + NBPW-1) & ~(NBPW-1);
                        goto bad;
        }
        nc = (nc + NBPW-1) & ~(NBPW-1);
-       error = getxfile(p, vp, &exdata.ex_exec, flags, nc + (na+4)*NBPW,
+       error = getxfile(p, vp, &exdata.ex_exec, paged, nc + (na+4)*NBPW,
            uid, gid);
        if (error)
                goto bad;
            uid, gid);
        if (error)
                goto bad;
@@ -345,15 +351,15 @@ execve(p, uap, retval)
         * 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()
         */
         * 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,
                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.
         */
 #endif
 
        /*
         * Copy back arglist.
         */
-       ucp = USRSTACK - sizeof(u.u_pcb.pcb_sigc) - nc - NBPW;
+       ucp = USRSTACK - szsigcode - nc - NBPW;
        ap = ucp - na*NBPW - 3*NBPW;
        p->p_regs[SP] = ap;
        (void) suword((caddr_t)ap, na-ne);
        ap = ucp - na*NBPW - 3*NBPW;
        p->p_regs[SP] = ap;
        (void) suword((caddr_t)ap, na-ne);
@@ -400,26 +406,25 @@ execve(p, uap, retval)
         */
        while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
                fdp->fd_lastfile--;
         */
        while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
                fdp->fd_lastfile--;
-       setregs(exdata.ex_exec.a_entry, retval);
+       setregs(p, exdata.ex_exec.a_entry, retval);
+#ifdef COPY_SIGCODE
        /*
         * Install sigcode at top of user stack.
         */
        /*
         * Install sigcode at top of user stack.
         */
-       copyout((caddr_t)u.u_pcb.pcb_sigc,
-               (caddr_t)(USRSTACK - sizeof(u.u_pcb.pcb_sigc)),
-               sizeof(u.u_pcb.pcb_sigc));
+       copyout((caddr_t)sigcode, (caddr_t)(USRSTACK - szsigcode), szsigcode);
+#endif
        /*
         * Remember file name for accounting.
         */
        p->p_acflag &= ~AFORK;
        /*
         * Remember file name for accounting.
         */
        p->p_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));
-       }
+       if (ndp->ni_namelen > MAXCOMLEN)
+               ndp->ni_namelen = MAXCOMLEN;
+       bcopy((caddr_t)ndp->ni_ptr, (caddr_t)p->p_comm,
+           (unsigned)(ndp->ni_namelen));
+       p->p_comm[ndp->ni_namelen] = '\0';
+       cpu_exec(p);
 bad:
 bad:
+       FREE(ndp->ni_pnbuf, M_NAMEI);
        if (execargs)
                kmem_free_wakeup(exec_map, execargs, NCARGS);
 #endif SECSIZE
        if (execargs)
                kmem_free_wakeup(exec_map, execargs, NCARGS);
 #endif SECSIZE
@@ -431,11 +436,11 @@ bad:
 /*
  * Read in and set up memory for executed file.
  */
 /*
  * Read in and set up memory for executed file.
  */
-getxfile(p, vp, ep, flags, nargc, uid, gid)
+getxfile(p, vp, ep, paged, nargc, uid, gid)
        register struct proc *p;
        register struct vnode *vp;
        register struct exec *ep;
        register struct proc *p;
        register struct vnode *vp;
        register struct exec *ep;
-       int flags, nargc, uid, gid;
+       int paged, nargc, uid, gid;
 {
        segsz_t ts, ds, ss;
        register struct ucred *cred = p->p_ucred;
 {
        segsz_t ts, ds, ss;
        register struct ucred *cred = p->p_ucred;
@@ -446,30 +451,22 @@ getxfile(p, vp, ep, flags, nargc, uid, gid)
        struct vmspace *vm = p->p_vmspace;
 
 #ifdef HPUXCOMPAT
        struct vmspace *vm = p->p_vmspace;
 
 #ifdef HPUXCOMPAT
+       int hpux = (paged & SHPUX);
+       paged &= ~SHPUX;
        if (ep->a_mid == MID_HPUX) {
        if (ep->a_mid == MID_HPUX) {
-               if (flags & SPAGV)
+               if (paged)
                        toff = CLBYTES;
                else
                        toff = sizeof (struct hpux_exec);
        } else
 #endif
                        toff = CLBYTES;
                else
                        toff = sizeof (struct hpux_exec);
        } else
 #endif
-       if (flags & SPAGV)
+       if (paged)
                toff = CLBYTES;
        else
                toff = sizeof (struct exec);
        if (ep->a_text != 0 && (vp->v_flag & VTEXT) == 0 &&
                toff = CLBYTES;
        else
                toff = sizeof (struct exec);
        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.
 
        /*
         * Compute text and data sizes and make sure not too large.
@@ -478,7 +475,7 @@ getxfile(p, vp, ep, flags, nargc, uid, gid)
         */
        ts = clrnd(btoc(ep->a_text));
        ds = clrnd(btoc(ep->a_data + ep->a_bss));
         */
        ts = clrnd(btoc(ep->a_text));
        ds = clrnd(btoc(ep->a_data + ep->a_bss));
-       ss = clrnd(SSIZE + btoc(nargc + sizeof(u.u_pcb.pcb_sigc)));
+       ss = clrnd(SSIZE + btoc(nargc + szsigcode));
 
        /*
         * If we're sharing the address space, allocate a new space
 
        /*
         * If we're sharing the address space, allocate a new space
@@ -486,8 +483,8 @@ getxfile(p, vp, ep, flags, nargc, uid, gid)
         * empty out the existing vmspace.
         */
        if (vm->vm_refcnt > 1) {
         * empty out the existing vmspace.
         */
        if (vm->vm_refcnt > 1) {
-               p->p_vmspace = vmspace_alloc(vm_map_min(&vm->vm_map),
-                   vm_map_max(&vm->vm_map), 1);
+               p->p_vmspace = vmspace_alloc(VM_MIN_ADDRESS,
+                   VM_MAXUSER_ADDRESS, 1);
                vmspace_free(vm);
                vm = p->p_vmspace;
        } else {
                vmspace_free(vm);
                vm = p->p_vmspace;
        } else {
@@ -495,8 +492,8 @@ getxfile(p, vp, ep, flags, nargc, uid, gid)
                if (vm->vm_shm)
                        shmexit(p);
 #endif
                if (vm->vm_shm)
                        shmexit(p);
 #endif
-               (void) vm_map_remove(&vm->vm_map, vm_map_min(&vm->vm_map),
-                   vm_map_max(&vm->vm_map));
+               (void) vm_map_remove(&vm->vm_map, VM_MIN_ADDRESS,
+                   VM_MAXUSER_ADDRESS);
        }
        /*
         * If parent is waiting for us to exec or exit,
        }
        /*
         * If parent is waiting for us to exec or exit,
@@ -506,16 +503,17 @@ getxfile(p, vp, ep, flags, nargc, uid, gid)
                p->p_flag &= ~SPPWAIT;
                wakeup((caddr_t) p->p_pptr);
        }
                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
 #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)
        /* 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
 #endif
-       p->p_flag &= ~(SPAGV|SSEQL|SUANOM|SHPUX);
-       p->p_flag |= flags | SEXEC;
+       p->p_flag |= SEXEC;
        addr = VM_MIN_ADDRESS;
        if (vm_allocate(&vm->vm_map, &addr, round_page(ctob(ts + ds)), FALSE)) {
                uprintf("Cannot allocate text+data space\n");
        addr = VM_MIN_ADDRESS;
        if (vm_allocate(&vm->vm_map, &addr, round_page(ctob(ts + ds)), FALSE)) {
                uprintf("Cannot allocate text+data space\n");
@@ -523,23 +521,33 @@ getxfile(p, vp, ep, flags, nargc, uid, gid)
                goto badmap;
        }
        size = round_page(MAXSSIZ);             /* XXX */
                goto badmap;
        }
        size = round_page(MAXSSIZ);             /* XXX */
-       addr = trunc_page(VM_MAX_ADDRESS - size);
+#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;
        }
        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;
        vm->vm_taddr = (caddr_t)VM_MIN_ADDRESS;
        vm->vm_daddr = (caddr_t)(VM_MIN_ADDRESS + ctob(ts));
 
        vm->vm_maxsaddr = (caddr_t)addr;
        vm->vm_taddr = (caddr_t)VM_MIN_ADDRESS;
        vm->vm_daddr = (caddr_t)(VM_MIN_ADDRESS + ctob(ts));
 
-       if ((flags & SPAGV) == 0) {
+       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,
                /*
                 * 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);
+                       (IO_UNIT|IO_NODELOCKED), cred, (int *)0, p);
                /*
                 * Read in text segment if necessary (0410),
                 * and read-protect it.
                /*
                 * Read in text segment if necessary (0410),
                 * and read-protect it.
@@ -547,7 +555,7 @@ getxfile(p, vp, ep, flags, nargc, uid, gid)
                if (ep->a_text > 0) {
                        error = vn_rdwr(UIO_READ, vp, vm->vm_taddr,
                                (int)ep->a_text, toff, UIO_USERSPACE,
                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);
+                               (IO_UNIT|IO_NODELOCKED), cred, (int *)0, p);
                        (void) vm_map_protect(&vm->vm_map, VM_MIN_ADDRESS,
                                VM_MIN_ADDRESS + trunc_page(ep->a_text),
                                VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
                        (void) vm_map_protect(&vm->vm_map, VM_MIN_ADDRESS,
                                VM_MIN_ADDRESS + trunc_page(ep->a_text),
                                VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
@@ -572,7 +580,7 @@ badmap:
                uprintf("sorry, pid %d was killed in exec: VM allocation\n",
                        p->p_pid);
                psignal(p, SIGKILL);
                uprintf("sorry, pid %d was killed in exec: VM allocation\n",
                        p->p_pid);
                psignal(p, SIGKILL);
-               p->p_flag |= SULOCK;
+               p->p_flag |= SKEEP;
                return(error);
        }
 
                return(error);
        }
 
@@ -603,7 +611,8 @@ badmap:
        vm->vm_ssize = ss;
        p->p_stats->p_prof.pr_scale = 0;
 #if defined(tahoe)
        vm->vm_ssize = ss;
        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);
 }
 #endif
        return (0);
 }