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