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