lint
[unix-history] / usr / src / sys / kern / kern_exec.c
index 0e5e655..4d27e87 100644 (file)
@@ -4,7 +4,7 @@
  *
  * %sccs.include.proprietary.c%
  *
  *
  * %sccs.include.proprietary.c%
  *
- *     @(#)kern_exec.c 7.51 (Berkeley) %G%
+ *     @(#)kern_exec.c 7.55 (Berkeley) %G%
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -62,7 +62,7 @@ execve(p, uap, retval)
 {
        register struct ucred *cred = p->p_ucred;
        register struct filedesc *fdp = p->p_fd;
 {
        register struct ucred *cred = p->p_ucred;
        register struct filedesc *fdp = p->p_fd;
-       int na, ne, ucp, ap, cc;
+       int na, ne, ucp, ap, cc, ssize;
        register char *cp;
        register int nc;
        unsigned len;
        register char *cp;
        register int nc;
        unsigned len;
@@ -84,6 +84,7 @@ execve(p, uap, retval)
        struct hpux_exec hhead;
 #endif
        struct nameidata nd;
        struct hpux_exec hhead;
 #endif
        struct nameidata nd;
+       struct ps_strings ps;
 #ifdef SECSIZE
        extern long argdbsize;                  /* XXX */
 #endif SECSIZE
 #ifdef SECSIZE
        extern long argdbsize;                  /* XXX */
 #endif SECSIZE
@@ -219,20 +220,37 @@ execve(p, uap, retval)
                        error = ENOEXEC;
                        goto bad;
                }
                        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:
 #endif
                exdata.ex_exec.a_data += exdata.ex_exec.a_text;
                exdata.ex_exec.a_text = 0;
                break;
 
        case ZMAGIC:
-               paged++;
+#ifdef HPUXCOMPAT
+               paged |= 1;     /* XXX fix me */
+#else
+               paged = 1;
+#endif
                /* FALLTHROUGH */
                /* FALLTHROUGH */
+
        case NMAGIC:
 #ifdef COFF
                if (exdata.ex_exec.ex_fhdr.magic != COFF_MAGIC) {
                        error = ENOEXEC;
                        goto bad;
                }
        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;
 #endif
                if (exdata.ex_exec.a_text == 0) {
                        error = ENOEXEC;
@@ -350,9 +368,44 @@ execve(p, uap, retval)
                if (error)
                        goto bad;
        }
                if (error)
                        goto bad;
        }
-       nc = (nc + NBPW-1) & ~(NBPW-1);
-       error = getxfile(p, vp, &exdata.ex_exec, paged, nc + (na+4)*NBPW,
-           uid, gid);
+
+       /*
+        * 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);
        if (error)
                goto bad;
        vput(vp);
@@ -371,18 +424,20 @@ execve(p, uap, retval)
        /*
         * Copy back arglist.
         */
        /*
         * Copy back arglist.
         */
-       ucp = USRSTACK - szsigcode - nc - NBPW;
-       ap = ucp - na*NBPW - 3*NBPW;
        cpu_setstack(p, ap);
        (void) suword((caddr_t)ap, na-ne);
        nc = 0;
        cp = (char *) execargs;
        cc = NCARGS;
        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) {
                        (void) suword((caddr_t)ap, 0);
                        ap += NBPW;
        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;
                }
                if (--na < 0)
                        break;
@@ -399,6 +454,7 @@ execve(p, uap, retval)
                        panic("exec: EFAULT");
        }
        (void) suword((caddr_t)ap, 0);
                        panic("exec: EFAULT");
        }
        (void) suword((caddr_t)ap, 0);
+       (void) copyout((caddr_t)&ps, (caddr_t)PS_STRINGS, sizeof(ps));
 
        execsigs(p);
 
 
        execsigs(p);
 
@@ -423,7 +479,7 @@ execve(p, uap, retval)
        /*
         * Install sigcode at top of user stack.
         */
        /*
         * Install sigcode at top of user stack.
         */
-       copyout((caddr_t)sigcode, (caddr_t)(USRSTACK - szsigcode), szsigcode);
+       copyout((caddr_t)sigcode, (caddr_t)PS_STRINGS - szsigcode, szsigcode);
 #endif
        /*
         * Remember file name for accounting.
 #endif
        /*
         * Remember file name for accounting.
@@ -432,7 +488,7 @@ execve(p, uap, retval)
        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,
        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));
+           (unsigned)nd.ni_cnd.cn_namelen);
        p->p_comm[nd.ni_cnd.cn_namelen] = '\0';
        cpu_exec(p);
 bad:
        p->p_comm[nd.ni_cnd.cn_namelen] = '\0';
        cpu_exec(p);
 bad:
@@ -448,33 +504,35 @@ bad:
 /*
  * Read in and set up memory for executed file.
  */
 /*
  * Read in and set up memory for executed file.
  */
-getxfile(p, vp, ep, paged, nargc, uid, gid)
+getxfile(p, vp, ep, paged, ssize, 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 paged, nargc, uid, gid;
+       int paged, ssize, uid, gid;
 {
 {
-       segsz_t ts, ds, ss;
        register struct ucred *cred = p->p_ucred;
        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;
        off_t toff;
        int error = 0;
-       vm_offset_t addr;
-       vm_size_t size;
-       struct vmspace *vm = p->p_vmspace;
 
 #ifdef HPUXCOMPAT
        int hpux = (paged & SHPUX);
        paged &= ~SHPUX;
 
 #ifdef HPUXCOMPAT
        int hpux = (paged & SHPUX);
        paged &= ~SHPUX;
-       if (ep->a_mid == MID_HPUX) {
-               if (paged)
-                       toff = CLBYTES;
-               else
-                       toff = sizeof (struct hpux_exec);
-       } else
+       if (ep->a_mid == MID_HPUX)
+               toff = paged ? CLBYTES : sizeof(struct hpux_exec);
+       else
 #endif
 #ifdef COFF
        toff = N_TXTOFF(*ep);
 #else
 #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
        if (paged)
                toff = CLBYTES;
        else
@@ -486,18 +544,21 @@ getxfile(p, vp, ep, paged, nargc, uid, gid)
 
        /*
         * Compute text and data sizes and make sure not too large.
 
        /*
         * 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));
+       xts = roundup(ep->a_text, __LDPGSZ);
        ds = clrnd(btoc(ep->a_data + ep->a_bss));
        ds = clrnd(btoc(ep->a_data + ep->a_bss));
-       ss = clrnd(SSIZE + btoc(nargc + szsigcode));
 
        /*
         * 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.
         */
 
        /*
         * 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.
         */
+#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);
        if (vm->vm_refcnt > 1) {
                p->p_vmspace = vmspace_alloc(VM_MIN_ADDRESS,
                    VM_MAXUSER_ADDRESS, 1);
@@ -539,17 +600,17 @@ getxfile(p, vp, ep, paged, nargc, uid, gid)
        p->p_flag |= SEXEC;
 #ifndef COFF
        addr = VM_MIN_ADDRESS;
        p->p_flag |= SEXEC;
 #ifndef COFF
        addr = VM_MIN_ADDRESS;
-       if (vm_allocate(&vm->vm_map, &addr, round_page(ctob(ts + ds)), FALSE)) {
+       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;
                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 + ctob(ts));
+       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;
 #else /* COFF */
        addr = (vm_offset_t)ep->ex_aout.codeStart;
        vm->vm_taddr = (caddr_t)addr;
-       if (vm_allocate(&vm->vm_map, &addr, round_page(ctob(ts)), FALSE)) {
+       if (vm_allocate(&vm->vm_map, &addr, xts, FALSE)) {
                uprintf("Cannot allocate text space\n");
                error = ENOMEM;                 /* XXX */
                goto badmap;
                uprintf("Cannot allocate text space\n");
                error = ENOMEM;                 /* XXX */
                goto badmap;
@@ -594,11 +655,12 @@ getxfile(p, vp, ep, paged, nargc, uid, gid)
                 */
                if (ep->a_text > 0) {
                        error = vn_rdwr(UIO_READ, vp, vm->vm_taddr,
                 */
                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->vm_taddr,
-                               vm->vm_taddr + trunc_page(ep->a_text),
-                               VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
+                           (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 {
                /*
                }
        } else {
                /*
@@ -606,16 +668,15 @@ getxfile(p, vp, ep, paged, nargc, uid, gid)
                 */
 #ifndef COFF
                addr = VM_MIN_ADDRESS;
                 */
 #ifndef COFF
                addr = VM_MIN_ADDRESS;
-               size = round_page(ep->a_text + ep->a_data);
+               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);
                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 + trunc_page(ep->a_text),
+               (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;
                        VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
 #else /* COFF */
                addr = (vm_offset_t)vm->vm_taddr;
-               size = round_page(ep->a_text);
+               size = xts;
                error = vm_mmap(&vm->vm_map, &addr, size,
                        VM_PROT_READ|VM_PROT_EXECUTE,
                        MAP_FILE|MAP_COPY|MAP_FIXED,
                error = vm_mmap(&vm->vm_map, &addr, size,
                        VM_PROT_READ|VM_PROT_EXECUTE,
                        MAP_FILE|MAP_COPY|MAP_FIXED,
@@ -629,8 +690,8 @@ getxfile(p, vp, ep, paged, nargc, uid, gid)
 #endif /* COFF */
                vp->v_flag |= VTEXT;
        }
 #endif /* COFF */
                vp->v_flag |= VTEXT;
        }
-badmap:
        if (error) {
        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);
                printf("pid %d: VM allocation failure\n", p->p_pid);
                uprintf("sorry, pid %d was killed in exec: VM allocation\n",
                        p->p_pid);
@@ -654,16 +715,16 @@ badmap:
                                p->p_tracep = NULL;
                                p->p_traceflag = 0;
                        }
                                p->p_tracep = NULL;
                                p->p_traceflag = 0;
                        }
+                       cred->cr_uid = uid;
+                       cred->cr_gid = gid;
                }
                }
-               cred->cr_uid = uid;
-               cred->cr_gid = gid;
        } else
                psignal(p, SIGTRAP);
        p->p_cred->p_svuid = cred->cr_uid;
        p->p_cred->p_svgid = cred->cr_gid;
        } else
                psignal(p, SIGTRAP);
        p->p_cred->p_svuid = cred->cr_uid;
        p->p_cred->p_svgid = cred->cr_gid;
-       vm->vm_tsize = ts;
+       vm->vm_tsize = btoc(xts);
        vm->vm_dsize = ds;
        vm->vm_dsize = ds;
-       vm->vm_ssize = ss;
+       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_stats->p_prof.pr_scale = 0;
 #if defined(tahoe)
        /* move this when tahoe cpu_exec is created */