xref: /csrg-svn/sys/kern/kern_exec.c (revision 59353)
1 /*-
2  * Copyright (c) 1982, 1986, 1991 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.proprietary.c%
6  *
7  *	@(#)kern_exec.c	7.73 (Berkeley) 04/27/93
8  */
9 
10 #include <sys/param.h>
11 #include <sys/systm.h>
12 #include <sys/filedesc.h>
13 #include <sys/kernel.h>
14 #include <sys/proc.h>
15 #include <sys/mount.h>
16 #include <sys/malloc.h>
17 #include <sys/namei.h>
18 #include <sys/vnode.h>
19 #include <sys/file.h>
20 #include <sys/acct.h>
21 #include <sys/exec.h>
22 #include <sys/ktrace.h>
23 #include <sys/resourcevar.h>
24 
25 #include <machine/cpu.h>
26 #include <machine/reg.h>
27 
28 #include <sys/mman.h>
29 #include <vm/vm.h>
30 #include <vm/vm_param.h>
31 #include <vm/vm_map.h>
32 #include <vm/vm_kern.h>
33 #include <vm/vm_pager.h>
34 
35 #include <sys/signalvar.h>
36 
37 #ifdef HPUXCOMPAT
38 #include <sys/user.h>			/* for pcb */
39 #include <hp/hpux/hpux_exec.h>
40 #endif
41 
42 #ifdef COPY_SIGCODE
43 extern char sigcode[], esigcode[];
44 #define	szsigcode	(esigcode - sigcode)
45 #else
46 #define	szsigcode	0
47 #endif
48 
49 /*
50  * exec system call
51  */
52 struct execve_args {
53 	char	*fname;
54 	char	**argp;
55 	char	**envp;
56 };
57 /* ARGSUSED */
58 execve(p, uap, retval)
59 	register struct proc *p;
60 	register struct execve_args *uap;
61 	int *retval;
62 {
63 	register struct ucred *cred = p->p_ucred;
64 	register struct filedesc *fdp = p->p_fd;
65 	int na, ne, ucp, ap, cc, ssize;
66 	register char *cp;
67 	register int nc;
68 	unsigned len;
69 	int indir, uid, gid;
70 	char *sharg;
71 	struct vnode *vp;
72 	int resid, error, paged = 0;
73 	vm_offset_t execargs = 0;
74 	struct vattr vattr;
75 	char cfarg[MAXINTERP];
76 	union {
77 		char	ex_shell[MAXINTERP];	/* #! and interpreter name */
78 		struct	exec ex_exec;
79 #ifdef HPUXCOMPAT
80 		struct	hpux_exec ex_hexec;
81 #endif
82 	} exdata;
83 #ifdef HPUXCOMPAT
84 	struct hpux_exec hhead;
85 #endif
86 	struct nameidata nd;
87 	struct ps_strings ps;
88 
89 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | SAVENAME, UIO_USERSPACE,
90 		uap->fname, p);
91 	if (error = namei(&nd))
92 		return (error);
93 	vp = nd.ni_vp;
94 	indir = 0;
95 	uid = cred->cr_uid;
96 	gid = cred->cr_gid;
97 	if (error = VOP_GETATTR(vp, &vattr, cred, p))
98 		goto bad;
99 	if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
100 		error = EACCES;
101 		goto bad;
102 	}
103 	if ((vp->v_mount->mnt_flag & MNT_NOSUID) == 0) {
104 		if (vattr.va_mode & VSUID)
105 			uid = vattr.va_uid;
106 		if (vattr.va_mode & VSGID)
107 			gid = vattr.va_gid;
108 	}
109 
110   again:
111 	if (error = VOP_ACCESS(vp, VEXEC, cred, p))
112 		goto bad;
113 	if ((p->p_flag & STRC) && (error = VOP_ACCESS(vp, VREAD, cred, p)))
114 		goto bad;
115 	if (vp->v_type != VREG ||
116 	    (vattr.va_mode & (VEXEC|(VEXEC>>3)|(VEXEC>>6))) == 0) {
117 		error = EACCES;
118 		goto bad;
119 	}
120 
121 	/*
122 	 * Read in first few bytes of file for segment sizes, magic number:
123 	 *	OMAGIC = plain executable
124 	 *	NMAGIC = RO text
125 	 *	ZMAGIC = demand paged RO text
126 	 * Also an ASCII line beginning with #! is
127 	 * the file name of a ``shell'' and arguments may be prepended
128 	 * to the argument list if given here.
129 	 *
130 	 * SHELL NAMES ARE LIMITED IN LENGTH.
131 	 *
132 	 * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM
133 	 * THE ASCII LINE.
134 	 */
135 	exdata.ex_shell[0] = '\0';	/* for zero length files */
136 	error = vn_rdwr(UIO_READ, vp, (caddr_t)&exdata, sizeof (exdata),
137 	    (off_t)0, UIO_SYSSPACE, (IO_UNIT|IO_NODELOCKED), cred, &resid,
138 	    (struct proc *)0);
139 	if (error)
140 		goto bad;
141 #ifndef lint
142 	if (resid > sizeof(exdata) - sizeof(exdata.ex_exec) &&
143 	    exdata.ex_shell[0] != '#') {
144 		error = ENOEXEC;
145 		goto bad;
146 	}
147 #endif
148 #if defined(hp300) || defined(luna68k)
149 	switch ((int)exdata.ex_exec.a_mid) {
150 
151 	/*
152 	 * An ancient hp200 or hp300 binary, shouldn't happen anymore.
153 	 * Mark as invalid.
154 	 */
155 	case MID_ZERO:
156 		exdata.ex_exec.a_magic = 0;
157 		break;
158 
159 	/*
160 	 * HP200 series has a smaller page size so we cannot
161 	 * demand-load or even write protect text, so we just
162 	 * treat as OMAGIC.
163 	 */
164 	case MID_HP200:
165 		exdata.ex_exec.a_magic = OMAGIC;
166 		break;
167 
168 	case MID_HP300:
169 		break;
170 
171 #ifdef HPUXCOMPAT
172 	case MID_HPUX:
173 		/*
174 		 * Save a.out header.  This is eventually saved in the pcb,
175 		 * but we cannot do that yet in case the exec fails before
176 		 * the image is overlayed.
177 		 */
178 		bcopy((caddr_t)&exdata.ex_hexec,
179 		      (caddr_t)&hhead, sizeof hhead);
180 		/*
181 		 * Shuffle important fields to their BSD locations.
182 		 * Note that the order in which this is done is important.
183 		 */
184 		exdata.ex_exec.a_text = exdata.ex_hexec.ha_text;
185 		exdata.ex_exec.a_data = exdata.ex_hexec.ha_data;
186 		exdata.ex_exec.a_bss = exdata.ex_hexec.ha_bss;
187 		exdata.ex_exec.a_entry = exdata.ex_hexec.ha_entry;
188 		/*
189 		 * For ZMAGIC files, make sizes consistant with those
190 		 * generated by BSD ld.
191 		 */
192 		if (exdata.ex_exec.a_magic == ZMAGIC) {
193 			exdata.ex_exec.a_text =
194 				ctob(btoc(exdata.ex_exec.a_text));
195 			nc = exdata.ex_exec.a_data + exdata.ex_exec.a_bss;
196 			exdata.ex_exec.a_data =
197 				ctob(btoc(exdata.ex_exec.a_data));
198 			nc -= (int)exdata.ex_exec.a_data;
199 			exdata.ex_exec.a_bss = (nc < 0) ? 0 : nc;
200 		}
201 		break;
202 #endif
203 	}
204 #endif
205 	switch ((int)exdata.ex_exec.a_magic) {
206 
207 	case OMAGIC:
208 #ifdef COFF
209 		if (exdata.ex_exec.ex_fhdr.magic != COFF_MAGIC) {
210 			error = ENOEXEC;
211 			goto bad;
212 		}
213 #endif
214 #ifdef sparc
215 		if (exdata.ex_exec.a_mid != MID_SUN_SPARC) {
216 			error = ENOEXEC;
217 			goto bad;
218 		}
219 #endif
220 		exdata.ex_exec.a_data += exdata.ex_exec.a_text;
221 		exdata.ex_exec.a_text = 0;
222 		break;
223 
224 	case ZMAGIC:
225 		paged = 1;
226 		/* FALLTHROUGH */
227 
228 	case NMAGIC:
229 #ifdef COFF
230 		if (exdata.ex_exec.ex_fhdr.magic != COFF_MAGIC) {
231 			error = ENOEXEC;
232 			goto bad;
233 		}
234 #endif
235 #ifdef sparc
236 		if (exdata.ex_exec.a_mid != MID_SUN_SPARC) {
237 			error = ENOEXEC;
238 			goto bad;
239 		}
240 #endif
241 		if (exdata.ex_exec.a_text == 0) {
242 			error = ENOEXEC;
243 			goto bad;
244 		}
245 		break;
246 
247 	default:
248 		if (exdata.ex_shell[0] != '#' ||
249 		    exdata.ex_shell[1] != '!' ||
250 		    indir) {
251 			error = ENOEXEC;
252 			goto bad;
253 		}
254 		for (cp = &exdata.ex_shell[2];; ++cp) {
255 			if (cp >= &exdata.ex_shell[MAXINTERP]) {
256 				error = ENOEXEC;
257 				goto bad;
258 			}
259 			if (*cp == '\n') {
260 				*cp = '\0';
261 				break;
262 			}
263 			if (*cp == '\t')
264 				*cp = ' ';
265 		}
266 		cp = &exdata.ex_shell[2];
267 		while (*cp == ' ')
268 			cp++;
269 		nd.ni_dirp = cp;
270 		while (*cp && *cp != ' ')
271 			cp++;
272 		cfarg[0] = '\0';
273 		if (*cp) {
274 			*cp++ = '\0';
275 			while (*cp == ' ')
276 				cp++;
277 			if (*cp)
278 				bcopy((caddr_t)cp, (caddr_t)cfarg, MAXINTERP);
279 		}
280 		indir = 1;
281 		vput(vp);
282 		nd.ni_segflg = UIO_SYSSPACE;
283 		if (error = namei(&nd))
284 			return (error);
285 		vp = nd.ni_vp;
286 		if (error = VOP_GETATTR(vp, &vattr, cred, p))
287 			goto bad;
288 		uid = cred->cr_uid;	/* shell scripts can't be setuid */
289 		gid = cred->cr_gid;
290 		goto again;
291 	}
292 
293 	/*
294 	 * Collect arguments on "file" in swap space.
295 	 */
296 	na = 0;
297 	ne = 0;
298 	nc = 0;
299 	cc = NCARGS;
300 	execargs = kmem_alloc_wait(exec_map, NCARGS);
301 #ifdef DIAGNOSTIC
302 	if (execargs == (vm_offset_t)0)
303 		panic("execve: kmem_alloc_wait");
304 #endif
305 	cp = (char *) execargs;
306 	/*
307 	 * Copy arguments into file in argdev area.
308 	 */
309 	if (uap->argp) for (;;) {
310 		ap = NULL;
311 		sharg = NULL;
312 		if (indir && na == 0) {
313 			sharg = nd.ni_cnd.cn_nameptr;
314 			ap = (int)sharg;
315 			uap->argp++;		/* ignore argv[0] */
316 		} else if (indir && (na == 1 && cfarg[0])) {
317 			sharg = cfarg;
318 			ap = (int)sharg;
319 		} else if (indir && (na == 1 || na == 2 && cfarg[0]))
320 			ap = (int)uap->fname;
321 		else if (uap->argp) {
322 			ap = fuword((caddr_t)uap->argp);
323 			uap->argp++;
324 		}
325 		if (ap == NULL && uap->envp) {
326 			uap->argp = NULL;
327 			if ((ap = fuword((caddr_t)uap->envp)) != NULL)
328 				uap->envp++, ne++;
329 		}
330 		if (ap == NULL)
331 			break;
332 		na++;
333 		if (ap == -1) {
334 			error = EFAULT;
335 			goto bad;
336 		}
337 		do {
338 			if (nc >= NCARGS-1) {
339 				error = E2BIG;
340 				break;
341 			}
342 			if (sharg) {
343 				error = copystr(sharg, cp, (unsigned)cc, &len);
344 				sharg += len;
345 			} else {
346 				error = copyinstr((caddr_t)ap, cp, (unsigned)cc,
347 				    &len);
348 				ap += len;
349 			}
350 			cp += len;
351 			nc += len;
352 			cc -= len;
353 		} while (error == ENAMETOOLONG);
354 		if (error)
355 			goto bad;
356 	}
357 
358 	/*
359 	 * XXX the following is excessively bogus
360 	 *
361 	 * Compute initial process stack size and location of argc
362 	 * and character strings.  `nc' is currently just the number
363 	 * of characters of arg and env strings.
364 	 *
365 	 * nc = size of ps_strings structure +
366 	 *	size of signal code +
367 	 *	4 bytes of NULL pointer +
368 	 *	nc,
369 	 * rounded to nearest integer;
370 	 * ucp = USRSTACK - nc;		[user characters pointer]
371 	 * apsize = padding (if any) +
372 	 *	4 bytes of NULL pointer +
373 	 *	ne 4-byte pointers to env strings +
374 	 *	4 bytes of NULL pointer +
375 	 *	(na-ne) 4-byte pointers to arg strings +
376 	 *	4 bytes of argc;
377 	 * (this is the same as nc + (na+3)*4)
378 	 * ap = ucp - apsize;	[user address of argc]
379 	 * ssize = ssize + nc + machine-dependent space;
380 	 */
381 	nc = (sizeof(ps) + szsigcode + 4 + nc + NBPW-1) & ~(NBPW - 1);
382 #if defined(sparc) || defined(mips)
383 	ucp = USRSTACK;
384 	ssize = ALIGN(nc + (na + 3) * NBPW);
385 	ap = ucp - ssize;
386 	ucp -= nc;
387 #ifdef sparc
388 	ssize += sizeof(struct rwindow);
389 #endif
390 #else
391 	ssize = (na + 3) * NBPW;
392 	ucp = USRSTACK - nc;
393 	ap = ucp - ssize;
394 	ssize += nc;
395 #endif
396 	error = getxfile(p, vp, &exdata.ex_exec, paged, ssize, uid, gid);
397 	if (error)
398 		goto bad;
399 	vput(vp);
400 	vp = NULL;
401 
402 #ifdef HPUXCOMPAT
403 	/*
404 	 * We are now committed to the exec so we can save the exec
405 	 * header in the pcb where we can dump it if necessary in core()
406 	 */
407 	if (p->p_md.md_flags & MDP_HPUX)
408 		bcopy((caddr_t)&hhead,
409 		      (caddr_t)p->p_addr->u_md.md_exec, sizeof hhead);
410 #endif
411 
412 	/*
413 	 * Copy back arglist.
414 	 */
415 	cpu_setstack(p, ap);
416 	(void) suword((caddr_t)ap, na-ne);
417 	nc = 0;
418 	cp = (char *) execargs;
419 	cc = NCARGS;
420 	ps.ps_argvstr = (char *)ucp;	/* first argv string */
421 	ps.ps_nargvstr = na - ne;	/* argc */
422 	for (;;) {
423 		ap += NBPW;
424 		if (na == ne) {
425 			(void) suword((caddr_t)ap, 0);
426 			ap += NBPW;
427 			ps.ps_envstr = (char *)ucp;
428 			ps.ps_nenvstr = ne;
429 		}
430 		if (--na < 0)
431 			break;
432 		(void) suword((caddr_t)ap, ucp);
433 		do {
434 			error = copyoutstr(cp, (caddr_t)ucp, (unsigned)cc,
435 			    &len);
436 			ucp += len;
437 			cp += len;
438 			nc += len;
439 			cc -= len;
440 		} while (error == ENAMETOOLONG);
441 		if (error == EFAULT)
442 			panic("exec: EFAULT");
443 	}
444 	(void) suword((caddr_t)ap, 0);
445 	(void) copyout((caddr_t)&ps, (caddr_t)PS_STRINGS, sizeof(ps));
446 
447 	execsigs(p);
448 
449 	for (nc = fdp->fd_lastfile; nc >= 0; --nc) {
450 		if (fdp->fd_ofileflags[nc] & UF_EXCLOSE) {
451 			(void) closef(fdp->fd_ofiles[nc], p);
452 			fdp->fd_ofiles[nc] = NULL;
453 			fdp->fd_ofileflags[nc] = 0;
454 			if (nc < fdp->fd_freefile)
455 				fdp->fd_freefile = nc;
456 		}
457 		fdp->fd_ofileflags[nc] &= ~UF_MAPPED;
458 	}
459 	/*
460 	 * Adjust fd_lastfile to account for descriptors closed above.
461 	 * Don't decrement fd_lastfile past 0, as it's unsigned.
462 	 */
463 	while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
464 		fdp->fd_lastfile--;
465 	setregs(p, exdata.ex_exec.a_entry, retval);
466 #ifdef COPY_SIGCODE
467 	/*
468 	 * Install sigcode at top of user stack.
469 	 */
470 	copyout((caddr_t)sigcode, (caddr_t)PS_STRINGS - szsigcode, szsigcode);
471 #endif
472 	/*
473 	 * Remember file name for accounting.
474 	 */
475 	p->p_acflag &= ~AFORK;
476 	if (nd.ni_cnd.cn_namelen > MAXCOMLEN)
477 		nd.ni_cnd.cn_namelen = MAXCOMLEN;
478 	bcopy((caddr_t)nd.ni_cnd.cn_nameptr, (caddr_t)p->p_comm,
479 	    (unsigned)nd.ni_cnd.cn_namelen);
480 	p->p_comm[nd.ni_cnd.cn_namelen] = '\0';
481 	cpu_exec(p);
482 bad:
483 	FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);
484 	if (execargs)
485 		kmem_free_wakeup(exec_map, execargs, NCARGS);
486 	if (vp)
487 		vput(vp);
488 	return (error);
489 }
490 
491 /*
492  * Read in and set up memory for executed file.
493  */
494 getxfile(p, vp, ep, paged, ssize, uid, gid)
495 	register struct proc *p;
496 	register struct vnode *vp;
497 	register struct exec *ep;
498 	int paged, ssize, uid, gid;
499 {
500 	register struct ucred *cred = p->p_ucred;
501 	register struct vmspace *vm = p->p_vmspace;
502 	vm_offset_t addr;
503 	vm_size_t xts, size;
504 	segsz_t ds;
505 	off_t toff;
506 	int error = 0;
507 
508 #ifdef HPUXCOMPAT
509 	if (ep->a_mid == MID_HPUX)
510 		toff = paged ? CLBYTES : sizeof(struct hpux_exec);
511 	else
512 #endif
513 #ifdef COFF
514 	toff = N_TXTOFF(*ep);
515 #else
516 #ifdef sparc
517 	if (ep->a_mid == MID_SUN_SPARC)
518 		toff = paged ? 0 : sizeof(struct exec);
519 	else
520 #endif
521 	if (paged)
522 #ifdef mips
523 		toff = 0;
524 #else
525 		toff = CLBYTES;
526 #endif
527 	else
528 		toff = sizeof (struct exec);
529 #endif
530 	if (ep->a_text != 0 && (vp->v_flag & VTEXT) == 0 &&
531 	    vp->v_writecount != 0)
532 		return (ETXTBSY);
533 
534 	/*
535 	 * Compute text and data sizes and make sure not too large.
536 	 * Text size is rounded to an ``ld page''; data+bss is left
537 	 * in machine pages.  Check data and bss separately as they
538 	 * may overflow when summed together.  (XXX not done yet)
539 	 */
540 	xts = roundup(ep->a_text, __LDPGSZ);
541 	ds = clrnd(btoc(ep->a_data + ep->a_bss));
542 
543 	/*
544 	 * If we're sharing the address space, allocate a new space
545 	 * and release our reference to the old one.  Otherwise,
546 	 * empty out the existing vmspace.
547 	 */
548 #ifdef sparc
549 	kill_user_windows(p);		/* before addrs go away */
550 #endif
551 	if (vm->vm_refcnt > 1) {
552 		p->p_vmspace = vmspace_alloc(VM_MIN_ADDRESS,
553 		    VM_MAXUSER_ADDRESS, 1);
554 		vmspace_free(vm);
555 		vm = p->p_vmspace;
556 	} else {
557 #ifdef SYSVSHM
558 		if (vm->vm_shm)
559 			shmexit(p);
560 #endif
561 		(void) vm_map_remove(&vm->vm_map, VM_MIN_ADDRESS,
562 		    VM_MAXUSER_ADDRESS);
563 	}
564 	/*
565 	 * If parent is waiting for us to exec or exit,
566 	 * SPPWAIT will be set; clear it and wakeup parent.
567 	 */
568 	if (p->p_flag & SPPWAIT) {
569 		p->p_flag &= ~SPPWAIT;
570 		wakeup((caddr_t) p->p_pptr);
571 	}
572 #if defined(HP380)
573 	/* default to copyback caching on 68040 */
574 	if (mmutype == MMU_68040)
575 		p->p_md.md_flags |= (MDP_CCBDATA|MDP_CCBSTACK);
576 #endif
577 #ifdef HPUXCOMPAT
578 	p->p_md.md_flags &= ~(MDP_HPUX|MDP_HPUXMMAP);
579 	/* note that we are an HP-UX binary */
580 	if (ep->a_mid == MID_HPUX)
581 		p->p_md.md_flags |= MDP_HPUX;
582 	/* deal with miscellaneous attributes */
583 	if (ep->a_trsize & HPUXM_VALID) {
584 		if (ep->a_trsize & HPUXM_DATAWT)
585 			p->p_md.md_flags &= ~MDP_CCBDATA;
586 		if (ep->a_trsize & HPUXM_STKWT)
587 			p->p_md.md_flags &= ~MDP_CCBSTACK;
588 	}
589 #endif
590 #ifdef ULTRIXCOMPAT
591 	/*
592 	 * Always start out as an ULTRIX process.
593 	 * A system call in crt0.o will change us to BSD system calls later.
594 	 */
595 	p->p_md.md_flags |= MDP_ULTRIX;
596 #endif
597 	p->p_flag |= SEXEC;
598 #ifndef COFF
599 	addr = VM_MIN_ADDRESS;
600 	if (vm_allocate(&vm->vm_map, &addr, xts + ctob(ds), FALSE)) {
601 		uprintf("Cannot allocate text+data space\n");
602 		error = ENOMEM;			/* XXX */
603 		goto badmap;
604 	}
605 	vm->vm_taddr = (caddr_t)VM_MIN_ADDRESS;
606 	vm->vm_daddr = (caddr_t)(VM_MIN_ADDRESS + xts);
607 #else /* COFF */
608 	addr = (vm_offset_t)ep->ex_aout.codeStart;
609 	vm->vm_taddr = (caddr_t)addr;
610 	if (vm_allocate(&vm->vm_map, &addr, xts, FALSE)) {
611 		uprintf("Cannot allocate text space\n");
612 		error = ENOMEM;			/* XXX */
613 		goto badmap;
614 	}
615 	addr = (vm_offset_t)ep->ex_aout.heapStart;
616 	vm->vm_daddr = (caddr_t)addr;
617 	if (vm_allocate(&vm->vm_map, &addr, round_page(ctob(ds)), FALSE)) {
618 		uprintf("Cannot allocate data space\n");
619 		error = ENOMEM;			/* XXX */
620 		goto badmap;
621 	}
622 #endif /* COFF */
623 	size = round_page(MAXSSIZ);		/* XXX */
624 #ifdef	i386
625 	addr = trunc_page(USRSTACK - size) - NBPG;	/* XXX */
626 #else
627 	addr = trunc_page(USRSTACK - size);
628 #endif
629 	if (vm_allocate(&vm->vm_map, &addr, size, FALSE)) {
630 		uprintf("Cannot allocate stack space\n");
631 		error = ENOMEM;			/* XXX */
632 		goto badmap;
633 	}
634 	size -= round_page(p->p_rlimit[RLIMIT_STACK].rlim_cur);
635 	if (vm_map_protect(&vm->vm_map, addr, addr+size, VM_PROT_NONE, FALSE)) {
636 		uprintf("Cannot protect stack space\n");
637 		error = ENOMEM;
638 		goto badmap;
639 	}
640 	vm->vm_maxsaddr = (caddr_t)addr;
641 
642 	if (paged == 0) {
643 		/*
644 		 * Read in data segment.
645 		 */
646 		(void) vn_rdwr(UIO_READ, vp, vm->vm_daddr, (int) ep->a_data,
647 			(off_t)(toff + ep->a_text), UIO_USERSPACE,
648 			(IO_UNIT|IO_NODELOCKED), cred, (int *)0, p);
649 		/*
650 		 * Read in text segment if necessary (0410),
651 		 * and read-protect it.
652 		 */
653 		if (ep->a_text > 0) {
654 			error = vn_rdwr(UIO_READ, vp, vm->vm_taddr,
655 			    (int)ep->a_text, toff, UIO_USERSPACE,
656 			    (IO_UNIT|IO_NODELOCKED), cred, (int *)0, p);
657 			(void) vm_map_protect(&vm->vm_map,
658 			    (vm_offset_t)vm->vm_taddr,
659 			    (vm_offset_t)vm->vm_taddr + trunc_page(ep->a_text),
660 			    VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
661 		}
662 	} else {
663 		/*
664 		 * Allocate a region backed by the exec'ed vnode.
665 		 */
666 #ifndef COFF
667 		addr = VM_MIN_ADDRESS;
668 		size = round_page(xts + ep->a_data);
669 		error = vm_mmap(&vm->vm_map, &addr, size,
670 			VM_PROT_ALL, VM_PROT_ALL,
671 			MAP_COPY|MAP_FIXED,
672 			(caddr_t)vp, (vm_offset_t)toff);
673 		(void) vm_map_protect(&vm->vm_map, addr, addr + xts,
674 			VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
675 #else /* COFF */
676 		addr = (vm_offset_t)vm->vm_taddr;
677 		size = xts;
678 		error = vm_mmap(&vm->vm_map, &addr, size,
679 			VM_PROT_READ|VM_PROT_EXECUTE, VM_PROT_ALL,
680 			MAP_COPY|MAP_FIXED,
681 			(caddr_t)vp, (vm_offset_t)toff);
682 		toff += size;
683 		addr = (vm_offset_t)vm->vm_daddr;
684 		size = round_page(ep->a_data);
685 		error = vm_mmap(&vm->vm_map, &addr, size,
686 			VM_PROT_ALL, VM_PROT_ALL,
687 			MAP_COPY|MAP_FIXED,
688 			(caddr_t)vp, (vm_offset_t)toff);
689 #endif /* COFF */
690 		vp->v_flag |= VTEXT;
691 	}
692 	if (error) {
693 badmap:
694 		killproc(p, "VM allocation in exec");
695 		p->p_flag |= SKEEP;
696 		return(error);
697 	}
698 
699 	/*
700 	 * set SUID/SGID protections, if no tracing
701 	 */
702 	p->p_flag &= ~SUGID;
703 	if ((p->p_flag & STRC) == 0) {
704 		if (uid != cred->cr_uid || gid != cred->cr_gid) {
705 			p->p_ucred = cred = crcopy(cred);
706 			/*
707 			 * If process is being ktraced, turn off - unless
708 			 * root set it.
709 			 */
710 			if (p->p_tracep && !(p->p_traceflag & KTRFAC_ROOT)) {
711 				vrele(p->p_tracep);
712 				p->p_tracep = NULL;
713 				p->p_traceflag = 0;
714 			}
715 			cred->cr_uid = uid;
716 			cred->cr_gid = gid;
717 			p->p_flag |= SUGID;
718 		}
719 	} else
720 		psignal(p, SIGTRAP);
721 	p->p_cred->p_svuid = cred->cr_uid;
722 	p->p_cred->p_svgid = cred->cr_gid;
723 	vm->vm_tsize = btoc(xts);
724 	vm->vm_dsize = ds;
725 	vm->vm_ssize = btoc(ssize);
726 	if (p->p_flag & SPROFIL)
727 		stopprofclock(p);
728 #if defined(tahoe)
729 	/* move this when tahoe cpu_exec is created */
730 	p->p_addr->u_pcb.pcb_savacc.faddr = (float *)NULL;
731 #endif
732 	return (0);
733 }
734