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