xref: /csrg-svn/sys/kern/kern_exec.c (revision 52376)
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.50 (Berkeley) 02/05/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 "hp300/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 	register struct ucred *cred = p->p_ucred;
64 	register struct filedesc *fdp = p->p_fd;
65 	int na, ne, ucp, ap, cc;
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 
88 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | SAVENAME, UIO_USERSPACE,
89 		uap->fname, p);
90 	if (error = namei(&nd))
91 		return (error);
92 	vp = nd.ni_vp;
93 	indir = 0;
94 	uid = cred->cr_uid;
95 	gid = cred->cr_gid;
96 	if (error = VOP_GETATTR(vp, &vattr, cred, p))
97 		goto bad;
98 	if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
99 		error = EACCES;
100 		goto bad;
101 	}
102 	if ((vp->v_mount->mnt_flag & MNT_NOSUID) == 0) {
103 		if (vattr.va_mode & VSUID)
104 			uid = vattr.va_uid;
105 		if (vattr.va_mode & VSGID)
106 			gid = vattr.va_gid;
107 	}
108 
109   again:
110 	if (error = VOP_ACCESS(vp, VEXEC, cred, p))
111 		goto bad;
112 	if ((p->p_flag & STRC) && (error = VOP_ACCESS(vp, VREAD, cred, p)))
113 		goto bad;
114 	if (vp->v_type != VREG ||
115 	    (vattr.va_mode & (VEXEC|(VEXEC>>3)|(VEXEC>>6))) == 0) {
116 		error = EACCES;
117 		goto bad;
118 	}
119 
120 	/*
121 	 * Read in first few bytes of file for segment sizes, magic number:
122 	 *	OMAGIC = plain executable
123 	 *	NMAGIC = RO text
124 	 *	ZMAGIC = demand paged RO text
125 	 * Also an ASCII line beginning with #! is
126 	 * the file name of a ``shell'' and arguments may be prepended
127 	 * to the argument list if given here.
128 	 *
129 	 * SHELL NAMES ARE LIMITED IN LENGTH.
130 	 *
131 	 * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM
132 	 * THE ASCII LINE.
133 	 */
134 	exdata.ex_shell[0] = '\0';	/* for zero length files */
135 	error = vn_rdwr(UIO_READ, vp, (caddr_t)&exdata, sizeof (exdata),
136 	    (off_t)0, UIO_SYSSPACE, (IO_UNIT|IO_NODELOCKED), cred, &resid,
137 	    (struct proc *)0);
138 	if (error)
139 		goto bad;
140 #ifndef lint
141 	if (resid > sizeof(exdata) - sizeof(exdata.ex_exec) &&
142 	    exdata.ex_shell[0] != '#') {
143 		error = ENOEXEC;
144 		goto bad;
145 	}
146 #endif
147 #if defined(hp300)
148 	switch ((int)exdata.ex_exec.a_mid) {
149 
150 	/*
151 	 * An ancient hp200 or hp300 binary, shouldn't happen anymore.
152 	 * Mark as invalid.
153 	 */
154 	case MID_ZERO:
155 		exdata.ex_exec.a_magic = 0;
156 		break;
157 
158 	/*
159 	 * HP200 series has a smaller page size so we cannot
160 	 * demand-load or even write protect text, so we just
161 	 * treat as OMAGIC.
162 	 */
163 	case MID_HP200:
164 		exdata.ex_exec.a_magic = OMAGIC;
165 		break;
166 
167 	case MID_HP300:
168 		break;
169 
170 #ifdef HPUXCOMPAT
171 	case MID_HPUX:
172 		/*
173 		 * Save a.out header.  This is eventually saved in the pcb,
174 		 * but we cannot do that yet in case the exec fails before
175 		 * the image is overlayed.
176 		 */
177 		bcopy((caddr_t)&exdata.ex_hexec,
178 		      (caddr_t)&hhead, sizeof hhead);
179 		/*
180 		 * If version number is 0x2bad this is a native BSD
181 		 * binary created via the HPUX SGS.  Should not be
182 		 * treated as an HPUX binary.
183 		 */
184 		if (exdata.ex_hexec.ha_version != BSDVNUM)
185 			paged |= SHPUX;				/* XXX */
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 		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++;
226 		/* FALLTHROUGH */
227 	case NMAGIC:
228 #ifdef COFF
229 		if (exdata.ex_exec.ex_fhdr.magic != COFF_MAGIC) {
230 			error = ENOEXEC;
231 			goto bad;
232 		}
233 #endif
234 		if (exdata.ex_exec.a_text == 0) {
235 			error = ENOEXEC;
236 			goto bad;
237 		}
238 		break;
239 
240 	default:
241 		if (exdata.ex_shell[0] != '#' ||
242 		    exdata.ex_shell[1] != '!' ||
243 		    indir) {
244 			error = ENOEXEC;
245 			goto bad;
246 		}
247 		for (cp = &exdata.ex_shell[2];; ++cp) {
248 			if (cp >= &exdata.ex_shell[MAXINTERP]) {
249 				error = ENOEXEC;
250 				goto bad;
251 			}
252 			if (*cp == '\n') {
253 				*cp = '\0';
254 				break;
255 			}
256 			if (*cp == '\t')
257 				*cp = ' ';
258 		}
259 		cp = &exdata.ex_shell[2];
260 		while (*cp == ' ')
261 			cp++;
262 		nd.ni_dirp = cp;
263 		while (*cp && *cp != ' ')
264 			cp++;
265 		cfarg[0] = '\0';
266 		if (*cp) {
267 			*cp++ = '\0';
268 			while (*cp == ' ')
269 				cp++;
270 			if (*cp)
271 				bcopy((caddr_t)cp, (caddr_t)cfarg, MAXINTERP);
272 		}
273 		indir = 1;
274 		vput(vp);
275 		nd.ni_segflg = UIO_SYSSPACE;
276 		if (error = namei(&nd))
277 			return (error);
278 		vp = nd.ni_vp;
279 		if (error = VOP_GETATTR(vp, &vattr, cred, p))
280 			goto bad;
281 		uid = cred->cr_uid;	/* shell scripts can't be setuid */
282 		gid = cred->cr_gid;
283 		goto again;
284 	}
285 
286 	/*
287 	 * Collect arguments on "file" in swap space.
288 	 */
289 	na = 0;
290 	ne = 0;
291 	nc = 0;
292 	cc = NCARGS;
293 	execargs = kmem_alloc_wait(exec_map, NCARGS);
294 #ifdef DIAGNOSTIC
295 	if (execargs == (vm_offset_t)0)
296 		panic("execve: kmem_alloc_wait");
297 #endif
298 	cp = (char *) execargs;
299 	/*
300 	 * Copy arguments into file in argdev area.
301 	 */
302 	if (uap->argp) for (;;) {
303 		ap = NULL;
304 		sharg = NULL;
305 		if (indir && na == 0) {
306 			sharg = nd.ni_cnd.cn_nameptr;
307 			ap = (int)sharg;
308 			uap->argp++;		/* ignore argv[0] */
309 		} else if (indir && (na == 1 && cfarg[0])) {
310 			sharg = cfarg;
311 			ap = (int)sharg;
312 		} else if (indir && (na == 1 || na == 2 && cfarg[0]))
313 			ap = (int)uap->fname;
314 		else if (uap->argp) {
315 			ap = fuword((caddr_t)uap->argp);
316 			uap->argp++;
317 		}
318 		if (ap == NULL && uap->envp) {
319 			uap->argp = NULL;
320 			if ((ap = fuword((caddr_t)uap->envp)) != NULL)
321 				uap->envp++, ne++;
322 		}
323 		if (ap == NULL)
324 			break;
325 		na++;
326 		if (ap == -1) {
327 			error = EFAULT;
328 			goto bad;
329 		}
330 		do {
331 			if (nc >= NCARGS-1) {
332 				error = E2BIG;
333 				break;
334 			}
335 			if (sharg) {
336 				error = copystr(sharg, cp, (unsigned)cc, &len);
337 				sharg += len;
338 			} else {
339 				error = copyinstr((caddr_t)ap, cp, (unsigned)cc,
340 				    &len);
341 				ap += len;
342 			}
343 			cp += len;
344 			nc += len;
345 			cc -= len;
346 		} while (error == ENAMETOOLONG);
347 		if (error)
348 			goto bad;
349 	}
350 	nc = (nc + NBPW-1) & ~(NBPW-1);
351 	error = getxfile(p, vp, &exdata.ex_exec, paged, nc + (na+4)*NBPW,
352 	    uid, gid);
353 	if (error)
354 		goto bad;
355 	vput(vp);
356 	vp = NULL;
357 
358 #ifdef HPUXCOMPAT
359 	/*
360 	 * We are now committed to the exec so we can save the exec
361 	 * header in the pcb where we can dump it if necessary in core()
362 	 */
363 	if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXBIN)
364 		bcopy((caddr_t)&hhead,
365 		      (caddr_t)p->p_addr->u_pcb.pcb_exec, sizeof hhead);
366 #endif
367 
368 	/*
369 	 * Copy back arglist.
370 	 */
371 	ucp = USRSTACK - szsigcode - nc - NBPW;
372 	ap = ucp - na*NBPW - 3*NBPW;
373 	p->p_regs[SP] = ap;
374 	(void) suword((caddr_t)ap, na-ne);
375 	nc = 0;
376 	cp = (char *) execargs;
377 	cc = NCARGS;
378 	for (;;) {
379 		ap += NBPW;
380 		if (na == ne) {
381 			(void) suword((caddr_t)ap, 0);
382 			ap += NBPW;
383 		}
384 		if (--na < 0)
385 			break;
386 		(void) suword((caddr_t)ap, ucp);
387 		do {
388 			error = copyoutstr(cp, (caddr_t)ucp, (unsigned)cc,
389 			    &len);
390 			ucp += len;
391 			cp += len;
392 			nc += len;
393 			cc -= len;
394 		} while (error == ENAMETOOLONG);
395 		if (error == EFAULT)
396 			panic("exec: EFAULT");
397 	}
398 	(void) suword((caddr_t)ap, 0);
399 
400 	execsigs(p);
401 
402 	for (nc = fdp->fd_lastfile; nc >= 0; --nc) {
403 		if (fdp->fd_ofileflags[nc] & UF_EXCLOSE) {
404 			(void) closef(fdp->fd_ofiles[nc], p);
405 			fdp->fd_ofiles[nc] = NULL;
406 			fdp->fd_ofileflags[nc] = 0;
407 			if (nc < fdp->fd_freefile)
408 				fdp->fd_freefile = nc;
409 		}
410 		fdp->fd_ofileflags[nc] &= ~UF_MAPPED;
411 	}
412 	/*
413 	 * Adjust fd_lastfile to account for descriptors closed above.
414 	 * Don't decrement fd_lastfile past 0, as it's unsigned.
415 	 */
416 	while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
417 		fdp->fd_lastfile--;
418 	setregs(p, exdata.ex_exec.a_entry, retval);
419 #ifdef COPY_SIGCODE
420 	/*
421 	 * Install sigcode at top of user stack.
422 	 */
423 	copyout((caddr_t)sigcode, (caddr_t)(USRSTACK - szsigcode), szsigcode);
424 #endif
425 	/*
426 	 * Remember file name for accounting.
427 	 */
428 	p->p_acflag &= ~AFORK;
429 	if (nd.ni_cnd.cn_namelen > MAXCOMLEN)
430 		nd.ni_cnd.cn_namelen = MAXCOMLEN;
431 	bcopy((caddr_t)nd.ni_cnd.cn_nameptr, (caddr_t)p->p_comm,
432 	    (unsigned)(nd.ni_cnd.cn_namelen));
433 	p->p_comm[nd.ni_cnd.cn_namelen] = '\0';
434 	cpu_exec(p);
435 bad:
436 	FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);
437 	if (execargs)
438 		kmem_free_wakeup(exec_map, execargs, NCARGS);
439 	if (vp)
440 		vput(vp);
441 	return (error);
442 }
443 
444 /*
445  * Read in and set up memory for executed file.
446  */
447 getxfile(p, vp, ep, paged, nargc, uid, gid)
448 	register struct proc *p;
449 	register struct vnode *vp;
450 	register struct exec *ep;
451 	int paged, nargc, uid, gid;
452 {
453 	segsz_t ts, ds, ss;
454 	register struct ucred *cred = p->p_ucred;
455 	off_t toff;
456 	int error = 0;
457 	vm_offset_t addr;
458 	vm_size_t size;
459 	struct vmspace *vm = p->p_vmspace;
460 
461 #ifdef HPUXCOMPAT
462 	int hpux = (paged & SHPUX);
463 	paged &= ~SHPUX;
464 	if (ep->a_mid == MID_HPUX) {
465 		if (paged)
466 			toff = CLBYTES;
467 		else
468 			toff = sizeof (struct hpux_exec);
469 	} else
470 #endif
471 #ifdef COFF
472 	toff = N_TXTOFF(*ep);
473 #else
474 	if (paged)
475 		toff = CLBYTES;
476 	else
477 		toff = sizeof (struct exec);
478 #endif
479 	if (ep->a_text != 0 && (vp->v_flag & VTEXT) == 0 &&
480 	    vp->v_writecount != 0)
481 		return (ETXTBSY);
482 
483 	/*
484 	 * Compute text and data sizes and make sure not too large.
485 	 * NB - Check data and bss separately as they may overflow
486 	 * when summed together.
487 	 */
488 	ts = clrnd(btoc(ep->a_text));
489 	ds = clrnd(btoc(ep->a_data + ep->a_bss));
490 	ss = clrnd(SSIZE + btoc(nargc + szsigcode));
491 
492 	/*
493 	 * If we're sharing the address space, allocate a new space
494 	 * and release our reference to the old one.  Otherwise,
495 	 * empty out the existing vmspace.
496 	 */
497 	if (vm->vm_refcnt > 1) {
498 		p->p_vmspace = vmspace_alloc(VM_MIN_ADDRESS,
499 		    VM_MAXUSER_ADDRESS, 1);
500 		vmspace_free(vm);
501 		vm = p->p_vmspace;
502 	} else {
503 #ifdef SYSVSHM
504 		if (vm->vm_shm)
505 			shmexit(p);
506 #endif
507 		(void) vm_map_remove(&vm->vm_map, VM_MIN_ADDRESS,
508 		    VM_MAXUSER_ADDRESS);
509 	}
510 	/*
511 	 * If parent is waiting for us to exec or exit,
512 	 * SPPWAIT will be set; clear it and wakeup parent.
513 	 */
514 	if (p->p_flag & SPPWAIT) {
515 		p->p_flag &= ~SPPWAIT;
516 		wakeup((caddr_t) p->p_pptr);
517 	}
518 #ifdef HPUXCOMPAT
519 	p->p_addr->u_pcb.pcb_flags &= ~(PCB_HPUXMMAP|PCB_HPUXBIN);
520 	/* remember that we were loaded from an HPUX format file */
521 	if (ep->a_mid == MID_HPUX)
522 		p->p_addr->u_pcb.pcb_flags |= PCB_HPUXBIN;
523 	if (hpux)
524 		p->p_flag |= SHPUX;
525 	else
526 		p->p_flag &= ~SHPUX;
527 #endif
528 #ifdef ULTRIXCOMPAT
529 	/*
530 	 * Always start out as an ULTRIX process.
531 	 * A system call in crt0.o will change us to BSD system calls later.
532 	 */
533 	p->p_md.md_flags |= MDP_ULTRIX;
534 #endif
535 	p->p_flag |= SEXEC;
536 #ifndef COFF
537 	addr = VM_MIN_ADDRESS;
538 	if (vm_allocate(&vm->vm_map, &addr, round_page(ctob(ts + ds)), FALSE)) {
539 		uprintf("Cannot allocate text+data space\n");
540 		error = ENOMEM;			/* XXX */
541 		goto badmap;
542 	}
543 	vm->vm_taddr = (caddr_t)VM_MIN_ADDRESS;
544 	vm->vm_daddr = (caddr_t)(VM_MIN_ADDRESS + ctob(ts));
545 #else /* COFF */
546 	addr = (vm_offset_t)ep->ex_aout.codeStart;
547 	vm->vm_taddr = (caddr_t)addr;
548 	if (vm_allocate(&vm->vm_map, &addr, round_page(ctob(ts)), FALSE)) {
549 		uprintf("Cannot allocate text space\n");
550 		error = ENOMEM;			/* XXX */
551 		goto badmap;
552 	}
553 	addr = (vm_offset_t)ep->ex_aout.heapStart;
554 	vm->vm_daddr = (caddr_t)addr;
555 	if (vm_allocate(&vm->vm_map, &addr, round_page(ctob(ds)), FALSE)) {
556 		uprintf("Cannot allocate data space\n");
557 		error = ENOMEM;			/* XXX */
558 		goto badmap;
559 	}
560 #endif /* COFF */
561 	size = round_page(MAXSSIZ);		/* XXX */
562 #ifdef	i386
563 	addr = trunc_page(USRSTACK - size) - NBPG;	/* XXX */
564 #else
565 	addr = trunc_page(USRSTACK - size);
566 #endif
567 	if (vm_allocate(&vm->vm_map, &addr, size, FALSE)) {
568 		uprintf("Cannot allocate stack space\n");
569 		error = ENOMEM;			/* XXX */
570 		goto badmap;
571 	}
572 	size -= round_page(p->p_rlimit[RLIMIT_STACK].rlim_cur);
573 	if (vm_map_protect(&vm->vm_map, addr, addr+size, VM_PROT_NONE, FALSE)) {
574 		uprintf("Cannot protect stack space\n");
575 		error = ENOMEM;
576 		goto badmap;
577 	}
578 	vm->vm_maxsaddr = (caddr_t)addr;
579 
580 	if (paged == 0) {
581 		/*
582 		 * Read in data segment.
583 		 */
584 		(void) vn_rdwr(UIO_READ, vp, vm->vm_daddr, (int) ep->a_data,
585 			(off_t)(toff + ep->a_text), UIO_USERSPACE,
586 			(IO_UNIT|IO_NODELOCKED), cred, (int *)0, p);
587 		/*
588 		 * Read in text segment if necessary (0410),
589 		 * and read-protect it.
590 		 */
591 		if (ep->a_text > 0) {
592 			error = vn_rdwr(UIO_READ, vp, vm->vm_taddr,
593 				(int)ep->a_text, toff, UIO_USERSPACE,
594 				(IO_UNIT|IO_NODELOCKED), cred, (int *)0, p);
595 			(void) vm_map_protect(&vm->vm_map, vm->vm_taddr,
596 				vm->vm_taddr + trunc_page(ep->a_text),
597 				VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
598 		}
599 	} else {
600 		/*
601 		 * Allocate a region backed by the exec'ed vnode.
602 		 */
603 #ifndef COFF
604 		addr = VM_MIN_ADDRESS;
605 		size = round_page(ep->a_text + ep->a_data);
606 		error = vm_mmap(&vm->vm_map, &addr, size, VM_PROT_ALL,
607 			MAP_FILE|MAP_COPY|MAP_FIXED,
608 			(caddr_t)vp, (vm_offset_t)toff);
609 		(void) vm_map_protect(&vm->vm_map, addr,
610 			addr + trunc_page(ep->a_text),
611 			VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
612 #else /* COFF */
613 		addr = (vm_offset_t)vm->vm_taddr;
614 		size = round_page(ep->a_text);
615 		error = vm_mmap(&vm->vm_map, &addr, size,
616 			VM_PROT_READ|VM_PROT_EXECUTE,
617 			MAP_FILE|MAP_COPY|MAP_FIXED,
618 			(caddr_t)vp, (vm_offset_t)toff);
619 		toff += size;
620 		addr = (vm_offset_t)vm->vm_daddr;
621 		size = round_page(ep->a_data);
622 		error = vm_mmap(&vm->vm_map, &addr, size, VM_PROT_ALL,
623 			MAP_FILE|MAP_COPY|MAP_FIXED,
624 			(caddr_t)vp, (vm_offset_t)toff);
625 #endif /* COFF */
626 		vp->v_flag |= VTEXT;
627 	}
628 badmap:
629 	if (error) {
630 		printf("pid %d: VM allocation failure\n", p->p_pid);
631 		uprintf("sorry, pid %d was killed in exec: VM allocation\n",
632 			p->p_pid);
633 		psignal(p, SIGKILL);
634 		p->p_flag |= SKEEP;
635 		return(error);
636 	}
637 
638 	/*
639 	 * set SUID/SGID protections, if no tracing
640 	 */
641 	if ((p->p_flag&STRC)==0) {
642 		if (uid != cred->cr_uid || gid != cred->cr_gid) {
643 			p->p_ucred = cred = crcopy(cred);
644 			/*
645 			 * If process is being ktraced, turn off - unless
646 			 * root set it.
647 			 */
648 			if (p->p_tracep && !(p->p_traceflag & KTRFAC_ROOT)) {
649 				vrele(p->p_tracep);
650 				p->p_tracep = NULL;
651 				p->p_traceflag = 0;
652 			}
653 		}
654 		cred->cr_uid = uid;
655 		cred->cr_gid = gid;
656 	} else
657 		psignal(p, SIGTRAP);
658 	p->p_cred->p_svuid = cred->cr_uid;
659 	p->p_cred->p_svgid = cred->cr_gid;
660 	vm->vm_tsize = ts;
661 	vm->vm_dsize = ds;
662 	vm->vm_ssize = ss;
663 	p->p_stats->p_prof.pr_scale = 0;
664 #if defined(tahoe)
665 	/* move this when tahoe cpu_exec is created */
666 	p->p_addr->u_pcb.pcb_savacc.faddr = (float *)NULL;
667 #endif
668 	return (0);
669 }
670