- register struct ucred *cred = p->p_ucred;
- register struct nameidata *ndp;
- register struct filedesc *fdp = p->p_fd;
- int na, ne, ucp, ap, cc;
- register char *cp;
- register int nc;
- unsigned len;
- int indir, uid, gid;
- char *sharg;
- struct vnode *vp;
- int resid, error, paged = 0;
- vm_offset_t execargs;
- 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;
-#ifdef HPUXCOMPAT
- struct hpux_exec hhead;
-#endif
- struct nameidata nd;
-#ifdef SECSIZE
- extern long argdbsize; /* XXX */
-#endif SECSIZE
-
- ndp = &nd;
- start:
- ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
- ndp->ni_segflg = UIO_USERSPACE;
- ndp->ni_dirp = uap->fname;
- if (error = namei(ndp, p))
- return (error);
- vp = ndp->ni_vp;
- indir = 0;
- 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 (error = VOP_ACCESS(vp, VEXEC, cred, p))
- goto bad;
- 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) {
- error = EACCES;
- goto bad;
- }
-
- /*
- * 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.
- *
- * SHELL NAMES ARE LIMITED IN LENGTH.
- *
- * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM
- * THE ASCII LINE.
- */
- 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,
- (struct proc *)0);
- if (error)
- goto bad;
-#ifndef lint
- if (resid > sizeof(exdata) - sizeof(exdata.ex_exec) &&
- exdata.ex_shell[0] != '#') {
- 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:
- exdata.ex_exec.a_data += exdata.ex_exec.a_text;
- exdata.ex_exec.a_text = 0;
- break;
-
- case ZMAGIC:
- paged++;
- /* FALLTHROUGH */
- case NMAGIC:
- if (exdata.ex_exec.a_text == 0) {
- error = ENOEXEC;
- goto bad;
- }
- break;
-
- default:
- if (exdata.ex_shell[0] != '#' ||
- exdata.ex_shell[1] != '!' ||
- indir) {
- error = ENOEXEC;
- goto bad;
- }
- for (cp = &exdata.ex_shell[2];; ++cp) {
- if (cp >= &exdata.ex_shell[MAXINTERP]) {
- error = ENOEXEC;
- goto bad;
- }
- if (*cp == '\n') {
- *cp = '\0';
- break;
- }
- if (*cp == '\t')
- *cp = ' ';
- }
- cp = &exdata.ex_shell[2];
- while (*cp == ' ')
- cp++;
- ndp->ni_dirp = cp;
- while (*cp && *cp != ' ')
- cp++;
- cfarg[0] = '\0';
- if (*cp) {
- *cp++ = '\0';
- while (*cp == ' ')
- cp++;
- if (*cp)
- bcopy((caddr_t)cp, (caddr_t)cfarg, MAXINTERP);
- }
- 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;
- 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 = cred->cr_uid; /* shell scripts can't be setuid */
- gid = cred->cr_gid;
- goto again;
- }
-
- /*
- * Collect arguments on "file" in swap space.
- */
- na = 0;
- ne = 0;
- nc = 0;
- cc = NCARGS;
- execargs = kmem_alloc_wait(exec_map, NCARGS);
- cp = (char *) execargs;
- /*
- * Copy arguments into file in argdev area.
- */
- if (uap->argp) for (;;) {
- ap = NULL;
- sharg = NULL;
- if (indir && na == 0) {
- sharg = cfname;
- 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) {
- uap->argp = NULL;
- if ((ap = fuword((caddr_t)uap->envp)) != NULL)
- uap->envp++, ne++;
- }
- if (ap == NULL)
- break;
- na++;
- if (ap == -1) {
- error = EFAULT;
- goto bad;
- }
- do {
- if (nc >= NCARGS-1) {
- error = E2BIG;
- break;
- }
- if (sharg) {
- error = copystr(sharg, cp, (unsigned)cc, &len);
- sharg += len;
- } else {
- error = copyinstr((caddr_t)ap, cp, (unsigned)cc,
- &len);
- ap += len;
- }
- cp += len;
- nc += len;
- cc -= len;
- } while (error == ENAMETOOLONG);
- if (error)
- goto bad;
- }
- nc = (nc + NBPW-1) & ~(NBPW-1);
- error = getxfile(p, vp, &exdata.ex_exec, paged, nc + (na+4)*NBPW,
- 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 (u.u_pcb.pcb_flags & PCB_HPUXBIN)
- bcopy((caddr_t)&hhead,
- (caddr_t)u.u_pcb.pcb_exec, sizeof hhead);
-#endif
-
- /*
- * Copy back arglist.
- */
- ucp = USRSTACK - sizeof(u.u_pcb.pcb_sigc) - nc - NBPW;
- ap = ucp - na*NBPW - 3*NBPW;
- p->p_regs[SP] = ap;
- (void) suword((caddr_t)ap, na-ne);
- nc = 0;
- cp = (char *) execargs;
- cc = NCARGS;
- for (;;) {
- ap += NBPW;
- if (na == ne) {
- (void) suword((caddr_t)ap, 0);
- ap += NBPW;
- }
- if (--na < 0)
- break;
- (void) suword((caddr_t)ap, ucp);
- do {
- 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);
-
- 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(exdata.ex_exec.a_entry, retval);
- /*
- * 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));
- /*
- * 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));
- }
-bad:
- 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(p, vp, ep, paged, nargc, uid, gid)
- register struct proc *p;
- register struct vnode *vp;
- register struct exec *ep;
- int paged, nargc, uid, gid;
-{
- segsz_t ts, ds, ss;
- register struct ucred *cred = p->p_ucred;
- off_t toff;
- int error = 0;
- vm_offset_t addr;
- vm_size_t size;
- struct vmspace *vm = p->p_vmspace;