X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/82177e7b53a4cbf22ca6a738370be71bce0bf9b5..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 c14b32af26..4d27e87769 100644 --- a/usr/src/sys/kern/kern_exec.c +++ b/usr/src/sys/kern/kern_exec.c @@ -4,7 +4,7 @@ * * %sccs.include.proprietary.c% * - * @(#)kern_exec.c 7.47 (Berkeley) %G% + * @(#)kern_exec.c 7.55 (Berkeley) %G% */ #include "param.h" @@ -16,7 +16,6 @@ #include "malloc.h" #include "namei.h" #include "vnode.h" -#include "seg.h" #include "file.h" #include "acct.h" #include "exec.h" @@ -62,9 +61,8 @@ execve(p, uap, retval) int *retval; { register struct ucred *cred = p->p_ucred; - register struct nameidata *ndp; 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; @@ -72,7 +70,7 @@ execve(p, uap, retval) char *sharg; struct vnode *vp; int resid, error, paged = 0; - vm_offset_t execargs; + vm_offset_t execargs = 0; struct vattr vattr; char cfarg[MAXINTERP]; union { @@ -86,17 +84,16 @@ execve(p, uap, retval) struct hpux_exec hhead; #endif struct nameidata nd; + struct ps_strings ps; #ifdef SECSIZE extern long argdbsize; /* XXX */ #endif SECSIZE - ndp = &nd; - ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF | SAVENAME; - ndp->ni_segflg = UIO_USERSPACE; - ndp->ni_dirp = uap->fname; - if (error = namei(ndp, p)) + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | SAVENAME, UIO_USERSPACE, + uap->fname, p); + if (error = namei(&nd)) return (error); - vp = ndp->ni_vp; + vp = nd.ni_vp; indir = 0; uid = cred->cr_uid; gid = cred->cr_gid; @@ -218,14 +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: - paged++; +#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; @@ -254,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'; @@ -267,10 +293,10 @@ execve(p, uap, retval) } indir = 1; vput(vp); - ndp->ni_segflg = UIO_SYSSPACE; - if (error = namei(ndp, p)) + nd.ni_segflg = UIO_SYSSPACE; + if (error = namei(&nd)) return (error); - vp = ndp->ni_vp; + vp = nd.ni_vp; if (error = VOP_GETATTR(vp, &vattr, cred, p)) goto bad; uid = cred->cr_uid; /* shell scripts can't be setuid */ @@ -286,6 +312,10 @@ execve(p, uap, retval) nc = 0; 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. @@ -294,7 +324,7 @@ execve(p, uap, retval) ap = NULL; sharg = NULL; if (indir && na == 0) { - sharg = ndp->ni_ptr; + sharg = nd.ni_cnd.cn_nameptr; ap = (int)sharg; uap->argp++; /* ignore argv[0] */ } else if (indir && (na == 1 && cfarg[0])) { @@ -338,9 +368,44 @@ execve(p, uap, retval) 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); @@ -359,18 +424,20 @@ execve(p, uap, retval) /* * Copy back arglist. */ - ucp = USRSTACK - szsigcode - nc - NBPW; - ap = ucp - na*NBPW - 3*NBPW; - p->p_regs[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) { (void) suword((caddr_t)ap, 0); ap += NBPW; + ps.ps_envstr = (char *)ucp; + ps.ps_nenvstr = ne; } if (--na < 0) break; @@ -387,6 +454,7 @@ execve(p, uap, retval) panic("exec: EFAULT"); } (void) suword((caddr_t)ap, 0); + (void) copyout((caddr_t)&ps, (caddr_t)PS_STRINGS, sizeof(ps)); execsigs(p); @@ -411,20 +479,20 @@ execve(p, uap, retval) /* * 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. */ p->p_acflag &= ~AFORK; - 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'; + 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: - FREE(ndp->ni_pnbuf, M_NAMEI); + FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI); if (execargs) kmem_free_wakeup(exec_map, execargs, NCARGS); #endif SECSIZE @@ -436,52 +504,61 @@ bad: /* * 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; - int paged, nargc, uid, gid; + int paged, ssize, uid, gid; { - segsz_t ts, ds, ss; 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; - vm_offset_t addr; - vm_size_t size; - struct vmspace *vm = p->p_vmspace; #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 +#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. - * 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)); - 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. */ +#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); @@ -512,14 +589,40 @@ getxfile(p, vp, ep, paged, nargc, uid, gid) p->p_flag |= SHPUX; else p->p_flag &= ~SHPUX; +#endif +#ifdef ULTRIXCOMPAT + /* + * Always start out as an ULTRIX process. + * A system call in crt0.o will change us to BSD system calls later. + */ + 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, 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; + 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 */ @@ -538,8 +641,6 @@ getxfile(p, vp, ep, paged, nargc, uid, gid) 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)); if (paged == 0) { /* @@ -554,28 +655,43 @@ getxfile(p, vp, ep, paged, nargc, uid, gid) */ 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_MIN_ADDRESS, - VM_MIN_ADDRESS + 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 { /* * Allocate a region backed by the exec'ed vnode. */ +#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); - (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; + 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; } -badmap: 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); @@ -599,16 +715,16 @@ badmap: 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; - vm->vm_tsize = ts; + vm->vm_tsize = btoc(xts); 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 */