xref: /csrg-svn/sys/kern/kern_exec.c (revision 69409)
149587Sbostic /*-
263173Sbostic  * Copyright (c) 1982, 1986, 1991, 1993
363173Sbostic  *	The Regents of the University of California.  All rights reserved.
465771Sbostic  * (c) UNIX System Laboratories, Inc.
565771Sbostic  * All or some portions of this file are derived from material licensed
665771Sbostic  * to the University of California by American Telephone and Telegraph
765771Sbostic  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
865771Sbostic  * the permission of UNIX System Laboratories, Inc.
923368Smckusick  *
1049587Sbostic  * %sccs.include.proprietary.c%
1149587Sbostic  *
12*69409Smckusick  *	@(#)kern_exec.c	8.10 (Berkeley) 05/14/95
1323368Smckusick  */
1412789Ssam 
1556517Sbostic #include <sys/param.h>
1656517Sbostic #include <sys/systm.h>
1756517Sbostic #include <sys/filedesc.h>
1856517Sbostic #include <sys/kernel.h>
1956517Sbostic #include <sys/proc.h>
2056517Sbostic #include <sys/mount.h>
2156517Sbostic #include <sys/malloc.h>
2256517Sbostic #include <sys/namei.h>
2356517Sbostic #include <sys/vnode.h>
2456517Sbostic #include <sys/file.h>
2556517Sbostic #include <sys/acct.h>
2656517Sbostic #include <sys/exec.h>
2756517Sbostic #include <sys/ktrace.h>
2856517Sbostic #include <sys/resourcevar.h>
2968296Scgd #include <sys/syscallargs.h>
3012789Ssam 
3156517Sbostic #include <machine/cpu.h>
3256517Sbostic #include <machine/reg.h>
3337520Smckusick 
3456517Sbostic #include <sys/mman.h>
3556517Sbostic #include <vm/vm.h>
3656517Sbostic #include <vm/vm_param.h>
3756517Sbostic #include <vm/vm_map.h>
3856517Sbostic #include <vm/vm_kern.h>
3956517Sbostic #include <vm/vm_pager.h>
4045726Smckusick 
4156517Sbostic #include <sys/signalvar.h>
4247652Skarels 
4342085Smckusick #ifdef HPUXCOMPAT
4456517Sbostic #include <sys/user.h>			/* for pcb */
4556517Sbostic #include <hp/hpux/hpux_exec.h>
4642085Smckusick #endif
4742085Smckusick 
4848900Skarels #ifdef COPY_SIGCODE
4948900Skarels extern char sigcode[], esigcode[];
5048900Skarels #define	szsigcode	(esigcode - sigcode)
5148900Skarels #else
5248900Skarels #define	szsigcode	0
5348900Skarels #endif
5448900Skarels 
5547540Skarels /*
5647540Skarels  * exec system call
5747540Skarels  */
execve(p,uap,retval)5842921Smckusick execve(p, uap, retval)
5942921Smckusick 	register struct proc *p;
6068296Scgd 	register struct execve_args /* {
6168296Scgd 		syscallarg(char *) path;
6268296Scgd 		syscallarg(char **) argp;
6368296Scgd 		syscallarg(char **) envp;
6468296Scgd 	} */ *uap;
6568296Scgd 	register_t *retval;
6612789Ssam {
6747540Skarels 	register struct ucred *cred = p->p_ucred;
6845914Smckusick 	register struct filedesc *fdp = p->p_fd;
6952539Storek 	int na, ne, ucp, ap, cc, ssize;
7012789Ssam 	register char *cp;
7145914Smckusick 	register int nc;
7226352Skarels 	unsigned len;
7312789Ssam 	int indir, uid, gid;
7412789Ssam 	char *sharg;
7537728Smckusick 	struct vnode *vp;
7647733Skarels 	int resid, error, paged = 0;
7751039Sralph 	vm_offset_t execargs = 0;
7837728Smckusick 	struct vattr vattr;
7930577Sbostic 	char cfarg[MAXINTERP];
8016746Ssam 	union {
8130577Sbostic 		char	ex_shell[MAXINTERP];	/* #! and interpreter name */
8216746Ssam 		struct	exec ex_exec;
8342085Smckusick #ifdef HPUXCOMPAT
8442085Smckusick 		struct	hpux_exec ex_hexec;
8542085Smckusick #endif
8616746Ssam 	} exdata;
8742085Smckusick #ifdef HPUXCOMPAT
8842085Smckusick 	struct hpux_exec hhead;
8942085Smckusick #endif
9047540Skarels 	struct nameidata nd;
9153124Smckusick 	struct ps_strings ps;
9212789Ssam 
9359378Smckusick 	NDINIT(&nd, LOOKUP, FOLLOW | SAVENAME, UIO_USERSPACE,
9468296Scgd 		SCARG(uap, path), p);
9552376Smckusick 	if (error = namei(&nd))
9644404Skarels 		return (error);
9752376Smckusick 	vp = nd.ni_vp;
9867655Smckusick 	VOP_LEASE(vp, p, cred, LEASE_READ);
99*69409Smckusick 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
10012789Ssam 	indir = 0;
10142921Smckusick 	uid = cred->cr_uid;
10242921Smckusick 	gid = cred->cr_gid;
10348019Smckusick 	if (error = VOP_GETATTR(vp, &vattr, cred, p))
10437728Smckusick 		goto bad;
10541400Smckusick 	if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
10642921Smckusick 		error = EACCES;
10737728Smckusick 		goto bad;
10837728Smckusick 	}
10941400Smckusick 	if ((vp->v_mount->mnt_flag & MNT_NOSUID) == 0) {
11037728Smckusick 		if (vattr.va_mode & VSUID)
11137728Smckusick 			uid = vattr.va_uid;
11237728Smckusick 		if (vattr.va_mode & VSGID)
11337728Smckusick 			gid = vattr.va_gid;
11437728Smckusick 	}
11512789Ssam 
11612789Ssam   again:
11748019Smckusick 	if (error = VOP_ACCESS(vp, VEXEC, cred, p))
11812789Ssam 		goto bad;
11964589Sbostic 	if ((p->p_flag & P_TRACED) && (error = VOP_ACCESS(vp, VREAD, cred, p)))
12012789Ssam 		goto bad;
12137728Smckusick 	if (vp->v_type != VREG ||
12237728Smckusick 	    (vattr.va_mode & (VEXEC|(VEXEC>>3)|(VEXEC>>6))) == 0) {
12342921Smckusick 		error = EACCES;
12412789Ssam 		goto bad;
12512789Ssam 	}
12612789Ssam 
12712789Ssam 	/*
12816750Ssam 	 * Read in first few bytes of file for segment sizes, magic number:
12937728Smckusick 	 *	OMAGIC = plain executable
13037728Smckusick 	 *	NMAGIC = RO text
13137728Smckusick 	 *	ZMAGIC = demand paged RO text
13212789Ssam 	 * Also an ASCII line beginning with #! is
13312789Ssam 	 * the file name of a ``shell'' and arguments may be prepended
13412789Ssam 	 * to the argument list if given here.
13512789Ssam 	 *
13612789Ssam 	 * SHELL NAMES ARE LIMITED IN LENGTH.
13712789Ssam 	 *
13812789Ssam 	 * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM
13912789Ssam 	 * THE ASCII LINE.
14012789Ssam 	 */
14116746Ssam 	exdata.ex_shell[0] = '\0';	/* for zero length files */
14242921Smckusick 	error = vn_rdwr(UIO_READ, vp, (caddr_t)&exdata, sizeof (exdata),
14348019Smckusick 	    (off_t)0, UIO_SYSSPACE, (IO_UNIT|IO_NODELOCKED), cred, &resid,
14448019Smckusick 	    (struct proc *)0);
14542921Smckusick 	if (error)
14612789Ssam 		goto bad;
14712789Ssam #ifndef lint
14821104Skarels 	if (resid > sizeof(exdata) - sizeof(exdata.ex_exec) &&
14916746Ssam 	    exdata.ex_shell[0] != '#') {
15042921Smckusick 		error = ENOEXEC;
15112789Ssam 		goto bad;
15212789Ssam 	}
15312789Ssam #endif
15453871Smckusick #if defined(hp300) || defined(luna68k)
15542085Smckusick 	switch ((int)exdata.ex_exec.a_mid) {
15642085Smckusick 
15742085Smckusick 	/*
15842085Smckusick 	 * An ancient hp200 or hp300 binary, shouldn't happen anymore.
15942085Smckusick 	 * Mark as invalid.
16042085Smckusick 	 */
16142085Smckusick 	case MID_ZERO:
16242085Smckusick 		exdata.ex_exec.a_magic = 0;
16342085Smckusick 		break;
16442085Smckusick 
16542085Smckusick 	/*
16642085Smckusick 	 * HP200 series has a smaller page size so we cannot
16742085Smckusick 	 * demand-load or even write protect text, so we just
16842085Smckusick 	 * treat as OMAGIC.
16942085Smckusick 	 */
17042085Smckusick 	case MID_HP200:
17142085Smckusick 		exdata.ex_exec.a_magic = OMAGIC;
17242085Smckusick 		break;
17342085Smckusick 
17442085Smckusick 	case MID_HP300:
17542085Smckusick 		break;
17642085Smckusick 
17742085Smckusick #ifdef HPUXCOMPAT
17842085Smckusick 	case MID_HPUX:
17942085Smckusick 		/*
18042085Smckusick 		 * Save a.out header.  This is eventually saved in the pcb,
18142085Smckusick 		 * but we cannot do that yet in case the exec fails before
18242085Smckusick 		 * the image is overlayed.
18342085Smckusick 		 */
18442085Smckusick 		bcopy((caddr_t)&exdata.ex_hexec,
18542085Smckusick 		      (caddr_t)&hhead, sizeof hhead);
18642085Smckusick 		/*
18742085Smckusick 		 * Shuffle important fields to their BSD locations.
18842085Smckusick 		 * Note that the order in which this is done is important.
18942085Smckusick 		 */
19042085Smckusick 		exdata.ex_exec.a_text = exdata.ex_hexec.ha_text;
19142085Smckusick 		exdata.ex_exec.a_data = exdata.ex_hexec.ha_data;
19242085Smckusick 		exdata.ex_exec.a_bss = exdata.ex_hexec.ha_bss;
19342085Smckusick 		exdata.ex_exec.a_entry = exdata.ex_hexec.ha_entry;
19442085Smckusick 		/*
19542085Smckusick 		 * For ZMAGIC files, make sizes consistant with those
19642085Smckusick 		 * generated by BSD ld.
19742085Smckusick 		 */
19842085Smckusick 		if (exdata.ex_exec.a_magic == ZMAGIC) {
19942085Smckusick 			exdata.ex_exec.a_text =
20042085Smckusick 				ctob(btoc(exdata.ex_exec.a_text));
20142085Smckusick 			nc = exdata.ex_exec.a_data + exdata.ex_exec.a_bss;
20242085Smckusick 			exdata.ex_exec.a_data =
20342085Smckusick 				ctob(btoc(exdata.ex_exec.a_data));
20442085Smckusick 			nc -= (int)exdata.ex_exec.a_data;
20542085Smckusick 			exdata.ex_exec.a_bss = (nc < 0) ? 0 : nc;
20642085Smckusick 		}
20742085Smckusick 		break;
20842085Smckusick #endif
20942085Smckusick 	}
21042085Smckusick #endif
21126252Skarels 	switch ((int)exdata.ex_exec.a_magic) {
21212789Ssam 
21337728Smckusick 	case OMAGIC:
21451039Sralph #ifdef COFF
21551039Sralph 		if (exdata.ex_exec.ex_fhdr.magic != COFF_MAGIC) {
21651039Sralph 			error = ENOEXEC;
21751039Sralph 			goto bad;
21851039Sralph 		}
21951039Sralph #endif
22052539Storek #ifdef sparc
22152539Storek 		if (exdata.ex_exec.a_mid != MID_SUN_SPARC) {
22252539Storek 			error = ENOEXEC;
22352539Storek 			goto bad;
22452539Storek 		}
22552539Storek #endif
22616746Ssam 		exdata.ex_exec.a_data += exdata.ex_exec.a_text;
22716746Ssam 		exdata.ex_exec.a_text = 0;
22812789Ssam 		break;
22912789Ssam 
23037728Smckusick 	case ZMAGIC:
23152539Storek 		paged = 1;
23247733Skarels 		/* FALLTHROUGH */
23352539Storek 
23437728Smckusick 	case NMAGIC:
23551039Sralph #ifdef COFF
23651039Sralph 		if (exdata.ex_exec.ex_fhdr.magic != COFF_MAGIC) {
23751039Sralph 			error = ENOEXEC;
23851039Sralph 			goto bad;
23951039Sralph 		}
24051039Sralph #endif
24152539Storek #ifdef sparc
24252539Storek 		if (exdata.ex_exec.a_mid != MID_SUN_SPARC) {
24352539Storek 			error = ENOEXEC;
24452539Storek 			goto bad;
24552539Storek 		}
24652539Storek #endif
24716746Ssam 		if (exdata.ex_exec.a_text == 0) {
24842921Smckusick 			error = ENOEXEC;
24912789Ssam 			goto bad;
25012789Ssam 		}
25112789Ssam 		break;
25212789Ssam 
25312789Ssam 	default:
25434477Skarels 		if (exdata.ex_shell[0] != '#' ||
25534477Skarels 		    exdata.ex_shell[1] != '!' ||
25634477Skarels 		    indir) {
25742921Smckusick 			error = ENOEXEC;
25812789Ssam 			goto bad;
25912789Ssam 		}
26034418Sbostic 		for (cp = &exdata.ex_shell[2];; ++cp) {
26134477Skarels 			if (cp >= &exdata.ex_shell[MAXINTERP]) {
26242921Smckusick 				error = ENOEXEC;
26334418Sbostic 				goto bad;
26434418Sbostic 			}
26534418Sbostic 			if (*cp == '\n') {
26612789Ssam 				*cp = '\0';
26712789Ssam 				break;
26812789Ssam 			}
26934418Sbostic 			if (*cp == '\t')
27034418Sbostic 				*cp = ' ';
27112789Ssam 		}
27234477Skarels 		cp = &exdata.ex_shell[2];
27334477Skarels 		while (*cp == ' ')
27434477Skarels 			cp++;
27552376Smckusick 		nd.ni_dirp = cp;
27634477Skarels 		while (*cp && *cp != ' ')
27734477Skarels 			cp++;
27834644Skarels 		cfarg[0] = '\0';
27912789Ssam 		if (*cp) {
28034477Skarels 			*cp++ = '\0';
28134477Skarels 			while (*cp == ' ')
28234477Skarels 				cp++;
28321104Skarels 			if (*cp)
28430577Sbostic 				bcopy((caddr_t)cp, (caddr_t)cfarg, MAXINTERP);
28534644Skarels 		}
28634477Skarels 		indir = 1;
28737728Smckusick 		vput(vp);
28852376Smckusick 		nd.ni_segflg = UIO_SYSSPACE;
28952376Smckusick 		if (error = namei(&nd))
29044404Skarels 			return (error);
29152376Smckusick 		vp = nd.ni_vp;
29267655Smckusick 		VOP_LEASE(vp, p, cred, LEASE_READ);
293*69409Smckusick 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
29448019Smckusick 		if (error = VOP_GETATTR(vp, &vattr, cred, p))
29537728Smckusick 			goto bad;
29642921Smckusick 		uid = cred->cr_uid;	/* shell scripts can't be setuid */
29742921Smckusick 		gid = cred->cr_gid;
29812789Ssam 		goto again;
29912789Ssam 	}
30012789Ssam 
30112789Ssam 	/*
30212789Ssam 	 * Collect arguments on "file" in swap space.
30312789Ssam 	 */
30412789Ssam 	na = 0;
30512789Ssam 	ne = 0;
30612789Ssam 	nc = 0;
30745726Smckusick 	cc = NCARGS;
30845726Smckusick 	execargs = kmem_alloc_wait(exec_map, NCARGS);
30951039Sralph #ifdef DIAGNOSTIC
31051039Sralph 	if (execargs == (vm_offset_t)0)
31151039Sralph 		panic("execve: kmem_alloc_wait");
31251039Sralph #endif
31345726Smckusick 	cp = (char *) execargs;
31416750Ssam 	/*
31516750Ssam 	 * Copy arguments into file in argdev area.
31616750Ssam 	 */
31768296Scgd 	if (SCARG(uap, argp)) for (;;) {
31812789Ssam 		ap = NULL;
31921104Skarels 		sharg = NULL;
32021104Skarels 		if (indir && na == 0) {
32152376Smckusick 			sharg = nd.ni_cnd.cn_nameptr;
32221104Skarels 			ap = (int)sharg;
32368296Scgd 			SCARG(uap, argp)++;		/* ignore argv[0] */
32421104Skarels 		} else if (indir && (na == 1 && cfarg[0])) {
32521104Skarels 			sharg = cfarg;
32621104Skarels 			ap = (int)sharg;
32721104Skarels 		} else if (indir && (na == 1 || na == 2 && cfarg[0]))
32868296Scgd 			ap = (int)SCARG(uap, path);
32968296Scgd 		else if (SCARG(uap, argp)) {
33068296Scgd 			ap = fuword((caddr_t)SCARG(uap, argp));
33168296Scgd 			SCARG(uap, argp)++;
33212789Ssam 		}
33368296Scgd 		if (ap == NULL && SCARG(uap, envp)) {
33468335Scgd 			SCARG(uap, argp) = NULL;
33568296Scgd 			if ((ap = fuword((caddr_t)SCARG(uap, envp))) != NULL)
33668296Scgd 				SCARG(uap, envp)++, ne++;
33712789Ssam 		}
33812789Ssam 		if (ap == NULL)
33912789Ssam 			break;
34012789Ssam 		na++;
34116750Ssam 		if (ap == -1) {
34242921Smckusick 			error = EFAULT;
34345726Smckusick 			goto bad;
34416750Ssam 		}
34512789Ssam 		do {
34645726Smckusick 			if (nc >= NCARGS-1) {
34745726Smckusick 				error = E2BIG;
34845726Smckusick 				break;
34912789Ssam 			}
35021104Skarels 			if (sharg) {
35126352Skarels 				error = copystr(sharg, cp, (unsigned)cc, &len);
35221104Skarels 				sharg += len;
35321104Skarels 			} else {
35426352Skarels 				error = copyinstr((caddr_t)ap, cp, (unsigned)cc,
35526352Skarels 				    &len);
35621104Skarels 				ap += len;
35721104Skarels 			}
35816750Ssam 			cp += len;
35916750Ssam 			nc += len;
36016750Ssam 			cc -= len;
36145356Smckusick 		} while (error == ENAMETOOLONG);
36245726Smckusick 		if (error)
36345726Smckusick 			goto bad;
36412789Ssam 	}
36552539Storek 
36652539Storek 	/*
36752539Storek 	 * XXX the following is excessively bogus
36852539Storek 	 *
36952539Storek 	 * Compute initial process stack size and location of argc
37052539Storek 	 * and character strings.  `nc' is currently just the number
37152539Storek 	 * of characters of arg and env strings.
37252539Storek 	 *
37353124Smckusick 	 * nc = size of ps_strings structure +
37453124Smckusick 	 *	size of signal code +
37553124Smckusick 	 *	4 bytes of NULL pointer +
37653124Smckusick 	 *	nc,
37753124Smckusick 	 * rounded to nearest integer;
37852539Storek 	 * ucp = USRSTACK - nc;		[user characters pointer]
37952539Storek 	 * apsize = padding (if any) +
38052539Storek 	 *	4 bytes of NULL pointer +
38152539Storek 	 *	ne 4-byte pointers to env strings +
38252539Storek 	 *	4 bytes of NULL pointer +
38352539Storek 	 *	(na-ne) 4-byte pointers to arg strings +
38452539Storek 	 *	4 bytes of argc;
38552539Storek 	 * (this is the same as nc + (na+3)*4)
38652539Storek 	 * ap = ucp - apsize;	[user address of argc]
38752539Storek 	 * ssize = ssize + nc + machine-dependent space;
38852539Storek 	 */
38953124Smckusick 	nc = (sizeof(ps) + szsigcode + 4 + nc + NBPW-1) & ~(NBPW - 1);
39057297Sbostic #if defined(sparc) || defined(mips)
39152539Storek 	ucp = USRSTACK;
39257297Sbostic 	ssize = ALIGN(nc + (na + 3) * NBPW);
39352539Storek 	ap = ucp - ssize;
39452539Storek 	ucp -= nc;
39557297Sbostic #ifdef sparc
39652539Storek 	ssize += sizeof(struct rwindow);
39757297Sbostic #endif
39852539Storek #else
39952539Storek 	ssize = (na + 3) * NBPW;
40052539Storek 	ucp = USRSTACK - nc;
40152539Storek 	ap = ucp - ssize;
40252539Storek 	ssize += nc;
40352539Storek #endif
40452539Storek 	error = getxfile(p, vp, &exdata.ex_exec, paged, ssize, uid, gid);
40545726Smckusick 	if (error)
40612789Ssam 		goto bad;
40765118Spendry 
40865118Spendry 	/* take a reference to the new text vnode (for procfs) */
40965118Spendry 	if (p->p_textvp)
41065118Spendry 		vrele(p->p_textvp);
41165118Spendry 	VREF(vp);
41265118Spendry 	p->p_textvp = vp;
41365118Spendry 
41437728Smckusick 	vput(vp);
41537728Smckusick 	vp = NULL;
41612789Ssam 
41742085Smckusick #ifdef HPUXCOMPAT
41812789Ssam 	/*
41942085Smckusick 	 * We are now committed to the exec so we can save the exec
42042085Smckusick 	 * header in the pcb where we can dump it if necessary in core()
42142085Smckusick 	 */
42257305Shibler 	if (p->p_md.md_flags & MDP_HPUX)
42342085Smckusick 		bcopy((caddr_t)&hhead,
42457305Shibler 		      (caddr_t)p->p_addr->u_md.md_exec, sizeof hhead);
42542085Smckusick #endif
42642085Smckusick 
42742085Smckusick 	/*
42816750Ssam 	 * Copy back arglist.
42912789Ssam 	 */
43052377Smckusick 	cpu_setstack(p, ap);
43112789Ssam 	(void) suword((caddr_t)ap, na-ne);
43212789Ssam 	nc = 0;
43345726Smckusick 	cp = (char *) execargs;
43445726Smckusick 	cc = NCARGS;
43553124Smckusick 	ps.ps_argvstr = (char *)ucp;	/* first argv string */
43653124Smckusick 	ps.ps_nargvstr = na - ne;	/* argc */
43712789Ssam 	for (;;) {
43812789Ssam 		ap += NBPW;
43916750Ssam 		if (na == ne) {
44012789Ssam 			(void) suword((caddr_t)ap, 0);
44112789Ssam 			ap += NBPW;
44253124Smckusick 			ps.ps_envstr = (char *)ucp;
44353124Smckusick 			ps.ps_nenvstr = ne;
44412789Ssam 		}
44512789Ssam 		if (--na < 0)
44612789Ssam 			break;
44712789Ssam 		(void) suword((caddr_t)ap, ucp);
44812789Ssam 		do {
44926352Skarels 			error = copyoutstr(cp, (caddr_t)ucp, (unsigned)cc,
45026352Skarels 			    &len);
45116786Ssam 			ucp += len;
45216786Ssam 			cp += len;
45316786Ssam 			nc += len;
45416786Ssam 			cc -= len;
45545356Smckusick 		} while (error == ENAMETOOLONG);
45616786Ssam 		if (error == EFAULT)
45716786Ssam 			panic("exec: EFAULT");
45812789Ssam 	}
45912789Ssam 	(void) suword((caddr_t)ap, 0);
46053124Smckusick 	(void) copyout((caddr_t)&ps, (caddr_t)PS_STRINGS, sizeof(ps));
46121104Skarels 
46242921Smckusick 	execsigs(p);
46321104Skarels 
46445914Smckusick 	for (nc = fdp->fd_lastfile; nc >= 0; --nc) {
46547652Skarels 		if (fdp->fd_ofileflags[nc] & UF_EXCLOSE) {
46647652Skarels 			(void) closef(fdp->fd_ofiles[nc], p);
46747652Skarels 			fdp->fd_ofiles[nc] = NULL;
46847652Skarels 			fdp->fd_ofileflags[nc] = 0;
46947540Skarels 			if (nc < fdp->fd_freefile)
47047540Skarels 				fdp->fd_freefile = nc;
47121104Skarels 		}
47247652Skarels 		fdp->fd_ofileflags[nc] &= ~UF_MAPPED;
47321104Skarels 	}
47447652Skarels 	/*
47547652Skarels 	 * Adjust fd_lastfile to account for descriptors closed above.
47647652Skarels 	 * Don't decrement fd_lastfile past 0, as it's unsigned.
47747652Skarels 	 */
47847652Skarels 	while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
47945914Smckusick 		fdp->fd_lastfile--;
48049562Swilliam 	setregs(p, exdata.ex_exec.a_entry, retval);
48148900Skarels #ifdef COPY_SIGCODE
48216696Smckusick 	/*
48345726Smckusick 	 * Install sigcode at top of user stack.
48445726Smckusick 	 */
48553124Smckusick 	copyout((caddr_t)sigcode, (caddr_t)PS_STRINGS - szsigcode, szsigcode);
48648900Skarels #endif
48745726Smckusick 	/*
48816696Smckusick 	 * Remember file name for accounting.
48916696Smckusick 	 */
49047540Skarels 	p->p_acflag &= ~AFORK;
49152376Smckusick 	if (nd.ni_cnd.cn_namelen > MAXCOMLEN)
49252376Smckusick 		nd.ni_cnd.cn_namelen = MAXCOMLEN;
49352376Smckusick 	bcopy((caddr_t)nd.ni_cnd.cn_nameptr, (caddr_t)p->p_comm,
49452539Storek 	    (unsigned)nd.ni_cnd.cn_namelen);
49552376Smckusick 	p->p_comm[nd.ni_cnd.cn_namelen] = '\0';
49648900Skarels 	cpu_exec(p);
49712789Ssam bad:
49852376Smckusick 	FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);
49945726Smckusick 	if (execargs)
50045726Smckusick 		kmem_free_wakeup(exec_map, execargs, NCARGS);
50137728Smckusick 	if (vp)
50237728Smckusick 		vput(vp);
50344404Skarels 	return (error);
50412789Ssam }
50512789Ssam 
50612789Ssam /*
50712789Ssam  * Read in and set up memory for executed file.
50812789Ssam  */
getxfile(p,vp,ep,paged,ssize,uid,gid)50952539Storek getxfile(p, vp, ep, paged, ssize, uid, gid)
51042921Smckusick 	register struct proc *p;
51137728Smckusick 	register struct vnode *vp;
51216746Ssam 	register struct exec *ep;
51352539Storek 	int paged, ssize, uid, gid;
51412789Ssam {
51547540Skarels 	register struct ucred *cred = p->p_ucred;
51652539Storek 	register struct vmspace *vm = p->p_vmspace;
51752539Storek 	vm_offset_t addr;
51852539Storek 	vm_size_t xts, size;
51952539Storek 	segsz_t ds;
52042085Smckusick 	off_t toff;
52145726Smckusick 	int error = 0;
52212789Ssam 
52342085Smckusick #ifdef HPUXCOMPAT
52452831Smckusick 	if (ep->a_mid == MID_HPUX)
52552831Smckusick 		toff = paged ? CLBYTES : sizeof(struct hpux_exec);
52652831Smckusick 	else
52745726Smckusick #endif
52851039Sralph #ifdef COFF
52951039Sralph 	toff = N_TXTOFF(*ep);
53051039Sralph #else
53152539Storek #ifdef sparc
53252539Storek 	if (ep->a_mid == MID_SUN_SPARC)
53352539Storek 		toff = paged ? 0 : sizeof(struct exec);
53452539Storek 	else
53552539Storek #endif
53647733Skarels 	if (paged)
53757974Sralph #ifdef mips
53857974Sralph 		toff = 0;
53957974Sralph #else
54045726Smckusick 		toff = CLBYTES;
54157974Sralph #endif
54212789Ssam 	else
54345726Smckusick 		toff = sizeof (struct exec);
54451039Sralph #endif
54537728Smckusick 	if (ep->a_text != 0 && (vp->v_flag & VTEXT) == 0 &&
54650108Smckusick 	    vp->v_writecount != 0)
54750108Smckusick 		return (ETXTBSY);
54812789Ssam 
54912789Ssam 	/*
55012789Ssam 	 * Compute text and data sizes and make sure not too large.
55152539Storek 	 * Text size is rounded to an ``ld page''; data+bss is left
55252539Storek 	 * in machine pages.  Check data and bss separately as they
55352539Storek 	 * may overflow when summed together.  (XXX not done yet)
55412789Ssam 	 */
55552539Storek 	xts = roundup(ep->a_text, __LDPGSZ);
55616750Ssam 	ds = clrnd(btoc(ep->a_data + ep->a_bss));
55747652Skarels 
55847652Skarels 	/*
55947652Skarels 	 * If we're sharing the address space, allocate a new space
56047652Skarels 	 * and release our reference to the old one.  Otherwise,
56147652Skarels 	 * empty out the existing vmspace.
56247652Skarels 	 */
56352539Storek #ifdef sparc
56452539Storek 	kill_user_windows(p);		/* before addrs go away */
56552539Storek #endif
56647652Skarels 	if (vm->vm_refcnt > 1) {
56749562Swilliam 		p->p_vmspace = vmspace_alloc(VM_MIN_ADDRESS,
56849562Swilliam 		    VM_MAXUSER_ADDRESS, 1);
56947652Skarels 		vmspace_free(vm);
57047652Skarels 		vm = p->p_vmspace;
57147652Skarels 	} else {
57245726Smckusick #ifdef SYSVSHM
57347652Skarels 		if (vm->vm_shm)
57447652Skarels 			shmexit(p);
57545726Smckusick #endif
57649562Swilliam 		(void) vm_map_remove(&vm->vm_map, VM_MIN_ADDRESS,
57749562Swilliam 		    VM_MAXUSER_ADDRESS);
57847652Skarels 	}
57912789Ssam 	/*
58047540Skarels 	 * If parent is waiting for us to exec or exit,
58164589Sbostic 	 * P_PPWAIT will be set; clear it and wakeup parent.
58212789Ssam 	 */
58364589Sbostic 	if (p->p_flag & P_PPWAIT) {
58464589Sbostic 		p->p_flag &= ~P_PPWAIT;
58547540Skarels 		wakeup((caddr_t) p->p_pptr);
58612789Ssam 	}
58759933Sakito #if defined(HP380) || defined(LUNA2)
58857305Shibler 	/* default to copyback caching on 68040 */
58957305Shibler 	if (mmutype == MMU_68040)
59057305Shibler 		p->p_md.md_flags |= (MDP_CCBDATA|MDP_CCBSTACK);
59157305Shibler #endif
59242085Smckusick #ifdef HPUXCOMPAT
59357305Shibler 	p->p_md.md_flags &= ~(MDP_HPUX|MDP_HPUXMMAP);
59457305Shibler 	/* note that we are an HP-UX binary */
59542085Smckusick 	if (ep->a_mid == MID_HPUX)
59657305Shibler 		p->p_md.md_flags |= MDP_HPUX;
59757305Shibler 	/* deal with miscellaneous attributes */
59857305Shibler 	if (ep->a_trsize & HPUXM_VALID) {
59957305Shibler 		if (ep->a_trsize & HPUXM_DATAWT)
60057305Shibler 			p->p_md.md_flags &= ~MDP_CCBDATA;
60157305Shibler 		if (ep->a_trsize & HPUXM_STKWT)
60257305Shibler 			p->p_md.md_flags &= ~MDP_CCBSTACK;
60357305Shibler 	}
60442085Smckusick #endif
60551039Sralph #ifdef ULTRIXCOMPAT
60651039Sralph 	/*
60751039Sralph 	 * Always start out as an ULTRIX process.
60851039Sralph 	 * A system call in crt0.o will change us to BSD system calls later.
60951039Sralph 	 */
61051039Sralph 	p->p_md.md_flags |= MDP_ULTRIX;
61151039Sralph #endif
61264589Sbostic 	p->p_flag |= P_EXEC;
61351039Sralph #ifndef COFF
61445726Smckusick 	addr = VM_MIN_ADDRESS;
61552539Storek 	if (vm_allocate(&vm->vm_map, &addr, xts + ctob(ds), FALSE)) {
61645726Smckusick 		uprintf("Cannot allocate text+data space\n");
61745726Smckusick 		error = ENOMEM;			/* XXX */
61845726Smckusick 		goto badmap;
61945726Smckusick 	}
62051039Sralph 	vm->vm_taddr = (caddr_t)VM_MIN_ADDRESS;
62152539Storek 	vm->vm_daddr = (caddr_t)(VM_MIN_ADDRESS + xts);
62251039Sralph #else /* COFF */
62351039Sralph 	addr = (vm_offset_t)ep->ex_aout.codeStart;
62451039Sralph 	vm->vm_taddr = (caddr_t)addr;
62552539Storek 	if (vm_allocate(&vm->vm_map, &addr, xts, FALSE)) {
62651039Sralph 		uprintf("Cannot allocate text space\n");
62751039Sralph 		error = ENOMEM;			/* XXX */
62851039Sralph 		goto badmap;
62951039Sralph 	}
63051039Sralph 	addr = (vm_offset_t)ep->ex_aout.heapStart;
63151039Sralph 	vm->vm_daddr = (caddr_t)addr;
63251039Sralph 	if (vm_allocate(&vm->vm_map, &addr, round_page(ctob(ds)), FALSE)) {
63351039Sralph 		uprintf("Cannot allocate data space\n");
63451039Sralph 		error = ENOMEM;			/* XXX */
63551039Sralph 		goto badmap;
63651039Sralph 	}
63751039Sralph #endif /* COFF */
63845726Smckusick 	size = round_page(MAXSSIZ);		/* XXX */
63949690Swilliam #ifdef	i386
64049690Swilliam 	addr = trunc_page(USRSTACK - size) - NBPG;	/* XXX */
64149690Swilliam #else
64249562Swilliam 	addr = trunc_page(USRSTACK - size);
64349690Swilliam #endif
64447540Skarels 	if (vm_allocate(&vm->vm_map, &addr, size, FALSE)) {
64545726Smckusick 		uprintf("Cannot allocate stack space\n");
64645726Smckusick 		error = ENOMEM;			/* XXX */
64745726Smckusick 		goto badmap;
64845726Smckusick 	}
64949562Swilliam 	size -= round_page(p->p_rlimit[RLIMIT_STACK].rlim_cur);
65049562Swilliam 	if (vm_map_protect(&vm->vm_map, addr, addr+size, VM_PROT_NONE, FALSE)) {
65149562Swilliam 		uprintf("Cannot protect stack space\n");
65249562Swilliam 		error = ENOMEM;
65349562Swilliam 		goto badmap;
65449562Swilliam 	}
65547540Skarels 	vm->vm_maxsaddr = (caddr_t)addr;
65612789Ssam 
65747733Skarels 	if (paged == 0) {
65847652Skarels 		/*
65947652Skarels 		 * Read in data segment.
66047652Skarels 		 */
66147540Skarels 		(void) vn_rdwr(UIO_READ, vp, vm->vm_daddr, (int) ep->a_data,
66247540Skarels 			(off_t)(toff + ep->a_text), UIO_USERSPACE,
66348019Smckusick 			(IO_UNIT|IO_NODELOCKED), cred, (int *)0, p);
66447652Skarels 		/*
66547652Skarels 		 * Read in text segment if necessary (0410),
66647652Skarels 		 * and read-protect it.
66747652Skarels 		 */
66845726Smckusick 		if (ep->a_text > 0) {
66947540Skarels 			error = vn_rdwr(UIO_READ, vp, vm->vm_taddr,
67053311Smckusick 			    (int)ep->a_text, toff, UIO_USERSPACE,
67153311Smckusick 			    (IO_UNIT|IO_NODELOCKED), cred, (int *)0, p);
67253311Smckusick 			(void) vm_map_protect(&vm->vm_map,
67353311Smckusick 			    (vm_offset_t)vm->vm_taddr,
67453311Smckusick 			    (vm_offset_t)vm->vm_taddr + trunc_page(ep->a_text),
67553311Smckusick 			    VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
67645726Smckusick 		}
67745726Smckusick 	} else {
67845726Smckusick 		/*
67945726Smckusick 		 * Allocate a region backed by the exec'ed vnode.
68045726Smckusick 		 */
68151039Sralph #ifndef COFF
68245726Smckusick 		addr = VM_MIN_ADDRESS;
68352539Storek 		size = round_page(xts + ep->a_data);
68458594Shibler 		error = vm_mmap(&vm->vm_map, &addr, size,
68558594Shibler 			VM_PROT_ALL, VM_PROT_ALL,
68654296Smckusick 			MAP_COPY|MAP_FIXED,
68747540Skarels 			(caddr_t)vp, (vm_offset_t)toff);
68852539Storek 		(void) vm_map_protect(&vm->vm_map, addr, addr + xts,
68947540Skarels 			VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
69051039Sralph #else /* COFF */
69151039Sralph 		addr = (vm_offset_t)vm->vm_taddr;
69252539Storek 		size = xts;
69351039Sralph 		error = vm_mmap(&vm->vm_map, &addr, size,
69458594Shibler 			VM_PROT_READ|VM_PROT_EXECUTE, VM_PROT_ALL,
69554296Smckusick 			MAP_COPY|MAP_FIXED,
69651039Sralph 			(caddr_t)vp, (vm_offset_t)toff);
69751039Sralph 		toff += size;
69851039Sralph 		addr = (vm_offset_t)vm->vm_daddr;
69951039Sralph 		size = round_page(ep->a_data);
70058594Shibler 		error = vm_mmap(&vm->vm_map, &addr, size,
70158594Shibler 			VM_PROT_ALL, VM_PROT_ALL,
70254296Smckusick 			MAP_COPY|MAP_FIXED,
70351039Sralph 			(caddr_t)vp, (vm_offset_t)toff);
70451039Sralph #endif /* COFF */
70547652Skarels 		vp->v_flag |= VTEXT;
70629946Skarels 	}
70752539Storek 	if (error) {
70845726Smckusick badmap:
70957533Smckusick 		killproc(p, "VM allocation in exec");
71064589Sbostic 		p->p_flag |= P_NOSWAP;
71145726Smckusick 		return(error);
71245726Smckusick 	}
71312789Ssam 
71412789Ssam 	/*
71512789Ssam 	 * set SUID/SGID protections, if no tracing
71612789Ssam 	 */
71764589Sbostic 	p->p_flag &= ~P_SUGID;
71864589Sbostic 	if ((p->p_flag & P_TRACED) == 0) {
71945355Smarc 		if (uid != cred->cr_uid || gid != cred->cr_gid) {
72047540Skarels 			p->p_ucred = cred = crcopy(cred);
72165746Shibler #ifdef KTRACE
72245355Smarc 			/*
72345355Smarc 			 * If process is being ktraced, turn off - unless
72445355Smarc 			 * root set it.
72545355Smarc 			 */
72645355Smarc 			if (p->p_tracep && !(p->p_traceflag & KTRFAC_ROOT)) {
72745355Smarc 				vrele(p->p_tracep);
72845355Smarc 				p->p_tracep = NULL;
72945355Smarc 				p->p_traceflag = 0;
73045355Smarc 			}
73165746Shibler #endif
73252539Storek 			cred->cr_uid = uid;
73352539Storek 			cred->cr_gid = gid;
73464589Sbostic 			p->p_flag |= P_SUGID;
73545355Smarc 		}
73612789Ssam 	} else
73738928Skarels 		psignal(p, SIGTRAP);
73847540Skarels 	p->p_cred->p_svuid = cred->cr_uid;
73947540Skarels 	p->p_cred->p_svgid = cred->cr_gid;
74052539Storek 	vm->vm_tsize = btoc(xts);
74147540Skarels 	vm->vm_dsize = ds;
74253743Smccanne 	vm->vm_ssize = btoc(ssize);
74364589Sbostic 	if (p->p_flag & P_PROFIL)
74454134Smckusick 		stopprofclock(p);
74529946Skarels #if defined(tahoe)
74648900Skarels 	/* move this when tahoe cpu_exec is created */
74748900Skarels 	p->p_addr->u_pcb.pcb_savacc.faddr = (float *)NULL;
74829946Skarels #endif
74942921Smckusick 	return (0);
75012789Ssam }
751