xref: /original-bsd/sys/kern/kern_exec.c (revision 92ab646d)
1 /*
2  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)kern_exec.c	7.30 (Berkeley) 06/30/90
8  */
9 
10 #include "param.h"
11 #include "systm.h"
12 #include "map.h"
13 #include "user.h"
14 #include "kernel.h"
15 #include "proc.h"
16 #include "mount.h"
17 #include "ucred.h"
18 #include "malloc.h"
19 #include "buf.h"
20 #include "vnode.h"
21 #include "seg.h"
22 #include "vm.h"
23 #include "text.h"
24 #include "file.h"
25 #include "uio.h"
26 #include "acct.h"
27 #include "exec.h"
28 
29 #include "machine/reg.h"
30 #include "machine/pte.h"
31 #include "machine/psl.h"
32 #include "machine/mtpr.h"
33 
34 #ifdef HPUXCOMPAT
35 #include "../hpux/hpux_exec.h"
36 #endif
37 
38 /*
39  * exec system call, with and without environments.
40  */
41 execv(p, uap, retval)
42 	struct proc *p;
43 	struct args {
44 		char	*fname;
45 		char	**argp;
46 		char	**envp;
47 	} *uap;
48 	int *retval;
49 {
50 
51 	uap->envp = NULL;
52 	return (execve(p, uap, retval));
53 }
54 
55 /* ARGSUSED */
56 execve(p, uap, retval)
57 	register struct proc *p;
58 	register struct args {
59 		char	*fname;
60 		char	**argp;
61 		char	**envp;
62 	} *uap;
63 	int *retval;
64 {
65 	register nc;
66 	register char *cp;
67 	register struct buf *bp;
68 	struct buf *tbp;
69 	int na, ne, ucp, ap, cc;
70 	unsigned len;
71 	int indir, uid, gid;
72 	char *sharg;
73 	struct vnode *vp;
74 	swblk_t bno;
75 	struct vattr vattr;
76 	char cfname[MAXCOMLEN + 1];
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 	register struct ucred *cred = u.u_cred;
89 	register struct nameidata *ndp = &u.u_nd;
90 	int resid, error, flags = 0;
91 
92   start:
93 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
94 	ndp->ni_segflg = UIO_USERSPACE;
95 	ndp->ni_dirp = uap->fname;
96 	if (error = namei(ndp))
97 		return (error);
98 	vp = ndp->ni_vp;
99 	bno = 0;
100 	bp = 0;
101 	indir = 0;
102 	uid = cred->cr_uid;
103 	gid = cred->cr_gid;
104 	if (error = VOP_GETATTR(vp, &vattr, cred))
105 		goto bad;
106 	if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
107 		error = EACCES;
108 		goto bad;
109 	}
110 	if ((vp->v_mount->mnt_flag & MNT_NOSUID) == 0) {
111 		if (vattr.va_mode & VSUID)
112 			uid = vattr.va_uid;
113 		if (vattr.va_mode & VSGID)
114 			gid = vattr.va_gid;
115 	}
116 
117   again:
118 	if (error = VOP_ACCESS(vp, VEXEC, cred))
119 		goto bad;
120 	if ((p->p_flag & STRC) && (error = VOP_ACCESS(vp, VREAD, cred)))
121 		goto bad;
122 	if (vp->v_type != VREG ||
123 	    (vattr.va_mode & (VEXEC|(VEXEC>>3)|(VEXEC>>6))) == 0) {
124 		error = EACCES;
125 		goto bad;
126 	}
127 
128 	/*
129 	 * Read in first few bytes of file for segment sizes, magic number:
130 	 *	OMAGIC = plain executable
131 	 *	NMAGIC = RO text
132 	 *	ZMAGIC = demand paged RO text
133 	 * Also an ASCII line beginning with #! is
134 	 * the file name of a ``shell'' and arguments may be prepended
135 	 * to the argument list if given here.
136 	 *
137 	 * SHELL NAMES ARE LIMITED IN LENGTH.
138 	 *
139 	 * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM
140 	 * THE ASCII LINE.
141 	 */
142 	exdata.ex_shell[0] = '\0';	/* for zero length files */
143 	error = vn_rdwr(UIO_READ, vp, (caddr_t)&exdata, sizeof (exdata),
144 	    (off_t)0, UIO_SYSSPACE, (IO_UNIT|IO_NODELOCKED), cred, &resid);
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)
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 		 * If version number is 0x2bad this is a native BSD
188 		 * binary created via the HPUX SGS.  Should not be
189 		 * treated as an HPUX binary.
190 		 */
191 		if (exdata.ex_hexec.ha_version != BSDVNUM)
192 			flags |= SHPUX;
193 		/*
194 		 * Shuffle important fields to their BSD locations.
195 		 * Note that the order in which this is done is important.
196 		 */
197 		exdata.ex_exec.a_text = exdata.ex_hexec.ha_text;
198 		exdata.ex_exec.a_data = exdata.ex_hexec.ha_data;
199 		exdata.ex_exec.a_bss = exdata.ex_hexec.ha_bss;
200 		exdata.ex_exec.a_entry = exdata.ex_hexec.ha_entry;
201 		/*
202 		 * For ZMAGIC files, make sizes consistant with those
203 		 * generated by BSD ld.
204 		 */
205 		if (exdata.ex_exec.a_magic == ZMAGIC) {
206 			exdata.ex_exec.a_text =
207 				ctob(btoc(exdata.ex_exec.a_text));
208 			nc = exdata.ex_exec.a_data + exdata.ex_exec.a_bss;
209 			exdata.ex_exec.a_data =
210 				ctob(btoc(exdata.ex_exec.a_data));
211 			nc -= (int)exdata.ex_exec.a_data;
212 			exdata.ex_exec.a_bss = (nc < 0) ? 0 : nc;
213 		}
214 		break;
215 #endif
216 	}
217 #endif
218 	switch ((int)exdata.ex_exec.a_magic) {
219 
220 	case OMAGIC:
221 		exdata.ex_exec.a_data += exdata.ex_exec.a_text;
222 		exdata.ex_exec.a_text = 0;
223 		break;
224 
225 	case ZMAGIC:
226 		flags |= SPAGV;
227 	case NMAGIC:
228 		if (exdata.ex_exec.a_text == 0) {
229 			error = ENOEXEC;
230 			goto bad;
231 		}
232 		break;
233 
234 	default:
235 		if (exdata.ex_shell[0] != '#' ||
236 		    exdata.ex_shell[1] != '!' ||
237 		    indir) {
238 			error = ENOEXEC;
239 			goto bad;
240 		}
241 		for (cp = &exdata.ex_shell[2];; ++cp) {
242 			if (cp >= &exdata.ex_shell[MAXINTERP]) {
243 				error = ENOEXEC;
244 				goto bad;
245 			}
246 			if (*cp == '\n') {
247 				*cp = '\0';
248 				break;
249 			}
250 			if (*cp == '\t')
251 				*cp = ' ';
252 		}
253 		cp = &exdata.ex_shell[2];
254 		while (*cp == ' ')
255 			cp++;
256 		ndp->ni_dirp = cp;
257 		while (*cp && *cp != ' ')
258 			cp++;
259 		cfarg[0] = '\0';
260 		if (*cp) {
261 			*cp++ = '\0';
262 			while (*cp == ' ')
263 				cp++;
264 			if (*cp)
265 				bcopy((caddr_t)cp, (caddr_t)cfarg, MAXINTERP);
266 		}
267 		indir = 1;
268 		vput(vp);
269 		ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
270 		ndp->ni_segflg = UIO_SYSSPACE;
271 		if (error = namei(ndp))
272 			return (error);
273 		vp = ndp->ni_vp;
274 		if (error = VOP_GETATTR(vp, &vattr, cred))
275 			goto bad;
276 		bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)cfname,
277 		    MAXCOMLEN);
278 		cfname[MAXCOMLEN] = '\0';
279 		uid = cred->cr_uid;	/* shell scripts can't be setuid */
280 		gid = cred->cr_gid;
281 		goto again;
282 	}
283 	/*
284 	 * If the vnode has been modified since we last used it,
285 	 * then throw away all its pages and its text table entry.
286 	 */
287 	if (vp->v_text && vp->v_text->x_mtime != vattr.va_mtime.tv_sec) {
288 		/*
289 		 * Try once to release, if it is still busy
290 		 * take more drastic action.
291 		 */
292 		xrele(vp);
293 		if (vp->v_flag & VTEXT) {
294 			vput(vp);
295 			vgone(vp);
296 			goto start;
297 		}
298 	}
299 
300 	/*
301 	 * Collect arguments on "file" in swap space.
302 	 */
303 	na = 0;
304 	ne = 0;
305 	nc = 0;
306 	cc = 0;
307 	bno = rmalloc(argmap, (long)ctod(clrnd((int)btoc(NCARGS))));
308 	if (bno == 0) {
309 		swkill(p, "exec: no swap space");
310 		goto bad;
311 	}
312 	if (bno % CLSIZE)
313 		panic("execa rmalloc");
314 #ifdef GENERIC
315 	if (rootdev == dumpdev)
316 		bno += 4096;
317 #endif
318 	/*
319 	 * Copy arguments into file in argdev area.
320 	 */
321 	if (uap->argp) for (;;) {
322 		ap = NULL;
323 		sharg = NULL;
324 		if (indir && na == 0) {
325 			sharg = cfname;
326 			ap = (int)sharg;
327 			uap->argp++;		/* ignore argv[0] */
328 		} else if (indir && (na == 1 && cfarg[0])) {
329 			sharg = cfarg;
330 			ap = (int)sharg;
331 		} else if (indir && (na == 1 || na == 2 && cfarg[0]))
332 			ap = (int)uap->fname;
333 		else if (uap->argp) {
334 			ap = fuword((caddr_t)uap->argp);
335 			uap->argp++;
336 		}
337 		if (ap == NULL && uap->envp) {
338 			uap->argp = NULL;
339 			if ((ap = fuword((caddr_t)uap->envp)) != NULL)
340 				uap->envp++, ne++;
341 		}
342 		if (ap == NULL)
343 			break;
344 		na++;
345 		if (ap == -1) {
346 			error = EFAULT;
347 			if (bp) {
348 				brelse(bp);
349 				bp = 0;
350 			}
351 			goto badarg;
352 		}
353 		do {
354 			if (cc <= 0) {
355 				/*
356 				 * We depend on NCARGS being a multiple of
357 				 * CLBYTES.  This way we need only check
358 				 * overflow before each buffer allocation.
359 				 */
360 				if (nc >= NCARGS-1) {
361 					error = E2BIG;
362 					break;
363 				}
364 				if (bp)
365 					bdwrite(bp);
366 				cc = CLBYTES;
367 				bp = getblk(argdev_vp, bno + ctod(nc/NBPG), cc);
368 				cp = bp->b_un.b_addr;
369 			}
370 			if (sharg) {
371 				error = copystr(sharg, cp, (unsigned)cc, &len);
372 				sharg += len;
373 			} else {
374 				error = copyinstr((caddr_t)ap, cp, (unsigned)cc,
375 				    &len);
376 				ap += len;
377 			}
378 			cp += len;
379 			nc += len;
380 			cc -= len;
381 		} while (error == ENOENT);
382 		if (error) {
383 			if (bp)
384 				brelse(bp);
385 			bp = 0;
386 			goto badarg;
387 		}
388 	}
389 	if (bp)
390 		bdwrite(bp);
391 	bp = 0;
392 	nc = (nc + NBPW-1) & ~(NBPW-1);
393 	error = getxfile(p, vp, &exdata.ex_exec, flags, nc + (na+4)*NBPW,
394 	    uid, gid);
395 	if (error) {
396 badarg:
397 		for (cc = 0; cc < nc; cc += CLBYTES) {
398 			(void) baddr(argdev_vp, bno + ctod(cc/NBPG),
399 				CLBYTES, NOCRED, &tbp);
400 			bp = tbp;
401 			if (bp) {
402 				bp->b_flags |= B_INVAL;		/* throw away */
403 				brelse(bp);
404 				bp = 0;
405 			}
406 		}
407 		goto bad;
408 	}
409 	if (vp->v_text)
410 		vp->v_text->x_mtime = vattr.va_mtime.tv_sec;
411 	vput(vp);
412 	vp = NULL;
413 
414 #ifdef HPUXCOMPAT
415 	/*
416 	 * We are now committed to the exec so we can save the exec
417 	 * header in the pcb where we can dump it if necessary in core()
418 	 */
419 	if (u.u_pcb.pcb_flags & PCB_HPUXBIN)
420 		bcopy((caddr_t)&hhead,
421 		      (caddr_t)u.u_pcb.pcb_exec, sizeof hhead);
422 #endif
423 
424 	/*
425 	 * Copy back arglist.
426 	 */
427 	ucp = USRSTACK - nc - NBPW;
428 	ap = ucp - na*NBPW - 3*NBPW;
429 	u.u_ar0[SP] = ap;
430 	(void) suword((caddr_t)ap, na-ne);
431 	nc = 0;
432 	cc = 0;
433 	for (;;) {
434 		ap += NBPW;
435 		if (na == ne) {
436 			(void) suword((caddr_t)ap, 0);
437 			ap += NBPW;
438 		}
439 		if (--na < 0)
440 			break;
441 		(void) suword((caddr_t)ap, ucp);
442 		do {
443 			if (cc <= 0) {
444 				if (bp)
445 					brelse(bp);
446 				cc = CLBYTES;
447 				error = bread(argdev_vp,
448 				    (daddr_t)(bno + ctod(nc / NBPG)), cc,
449 				    NOCRED, &tbp);
450 				bp = tbp;
451 				bp->b_flags |= B_INVAL;		/* throw away */
452 				cp = bp->b_un.b_addr;
453 			}
454 			error = copyoutstr(cp, (caddr_t)ucp, (unsigned)cc,
455 			    &len);
456 			ucp += len;
457 			cp += len;
458 			nc += len;
459 			cc -= len;
460 		} while (error == ENOENT);
461 		if (error == EFAULT)
462 			panic("exec: EFAULT");
463 	}
464 	(void) suword((caddr_t)ap, 0);
465 
466 	execsigs(p);
467 
468 	for (nc = u.u_lastfile; nc >= 0; --nc) {
469 		if (u.u_pofile[nc] & UF_EXCLOSE) {
470 			(void) closef(u.u_ofile[nc]);
471 			u.u_ofile[nc] = NULL;
472 			u.u_pofile[nc] = 0;
473 		}
474 		u.u_pofile[nc] &= ~UF_MAPPED;
475 	}
476 	while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL)
477 		u.u_lastfile--;
478 	setregs(exdata.ex_exec.a_entry, retval);
479 	/*
480 	 * Remember file name for accounting.
481 	 */
482 	u.u_acflag &= ~AFORK;
483 	if (indir)
484 		bcopy((caddr_t)cfname, (caddr_t)p->p_comm, MAXCOMLEN);
485 	else {
486 		if (ndp->ni_dent.d_namlen > MAXCOMLEN)
487 			ndp->ni_dent.d_namlen = MAXCOMLEN;
488 		bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)p->p_comm,
489 		    (unsigned)(ndp->ni_dent.d_namlen + 1));
490 	}
491 bad:
492 	if (bp)
493 		brelse(bp);
494 	if (bno)
495 		rmfree(argmap, (long)ctod(clrnd((int) btoc(NCARGS))), bno);
496 	if (vp)
497 		vput(vp);
498 	return (error);
499 }
500 
501 /*
502  * Read in and set up memory for executed file.
503  */
504 getxfile(p, vp, ep, flags, nargc, uid, gid)
505 	register struct proc *p;
506 	register struct vnode *vp;
507 	register struct exec *ep;
508 	int flags, nargc, uid, gid;
509 {
510 	segsz_t ts, ds, ids, uds, ss;
511 	register struct ucred *cred = u.u_cred;
512 	off_t toff;
513 	int error;
514 
515 #ifdef HPUXCOMPAT
516 	if (ep->a_mid == MID_HPUX)
517 		toff = sizeof (struct hpux_exec);
518 	else
519 #endif
520 	toff = sizeof (struct exec);
521 	if (vp->v_text && (vp->v_text->x_flag & XTRC))
522 		return (ETXTBSY);
523 	if (ep->a_text != 0 && (vp->v_flag & VTEXT) == 0 &&
524 	    vp->v_usecount != 1) {
525 		register struct file *fp;
526 
527 		for (fp = file; fp < fileNFILE; fp++) {
528 			if (fp->f_type == DTYPE_VNODE &&
529 			    fp->f_count > 0 &&
530 			    (struct vnode *)fp->f_data == vp &&
531 			    (fp->f_flag & FWRITE)) {
532 				return (ETXTBSY);
533 			}
534 		}
535 	}
536 
537 	/*
538 	 * Compute text and data sizes and make sure not too large.
539 	 * NB - Check data and bss separately as they may overflow
540 	 * when summed together.
541 	 */
542 	ts = clrnd(btoc(ep->a_text));
543 	ids = clrnd(btoc(ep->a_data));
544 	uds = clrnd(btoc(ep->a_bss));
545 	ds = clrnd(btoc(ep->a_data + ep->a_bss));
546 	ss = clrnd(SSIZE + btoc(nargc));
547 	if (error =
548 	    chksize((unsigned)ts, (unsigned)ids, (unsigned)uds, (unsigned)ss))
549 		return (error);
550 
551 	/*
552 	 * Make sure enough space to start process.
553 	 */
554 	u.u_cdmap = zdmap;
555 	u.u_csmap = zdmap;
556 	if (error = swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap))
557 		return (error);
558 
559 	/*
560 	 * At this point, we are committed to the new image!
561 	 * Release virtual memory resources of old process, and
562 	 * initialize the virtual memory of the new process.
563 	 * If we resulted from vfork(), instead wakeup our
564 	 * parent who will set SVFDONE when he has taken back
565 	 * our resources.
566 	 */
567 	if ((p->p_flag & SVFORK) == 0) {
568 #ifdef MAPMEM
569 		if (u.u_mmap && (error = mmexec(p)))
570 			return (error);
571 #endif
572 		vrelvm();
573 	} else {
574 		p->p_flag &= ~SVFORK;
575 		p->p_flag |= SKEEP;
576 		wakeup((caddr_t)p);
577 		while ((p->p_flag & SVFDONE) == 0)
578 			sleep((caddr_t)p, PZERO - 1);
579 		p->p_flag &= ~(SVFDONE|SKEEP);
580 	}
581 #ifdef hp300
582 	u.u_pcb.pcb_flags &= ~(PCB_AST|PCB_HPUXMMAP|PCB_HPUXBIN);
583 #ifdef HPUXCOMPAT
584 	/* remember that we were loaded from an HPUX format file */
585 	if (ep->a_mid == MID_HPUX)
586 		u.u_pcb.pcb_flags |= PCB_HPUXBIN;
587 #endif
588 #endif
589 	p->p_flag &= ~(SPAGV|SSEQL|SUANOM|SHPUX);
590 	p->p_flag |= flags | SEXEC;
591 	u.u_dmap = u.u_cdmap;
592 	u.u_smap = u.u_csmap;
593 	vgetvm(ts, ds, ss);
594 
595 	if ((flags & SPAGV) == 0)
596 		(void) vn_rdwr(UIO_READ, vp,
597 			(char *)ctob(dptov(p, 0)),
598 			(int)ep->a_data,
599 			(off_t)(toff + ep->a_text),
600 			UIO_USERSPACE, (IO_UNIT|IO_NODELOCKED), cred, (int *)0);
601 	xalloc(vp, ep, toff, cred);
602 #if defined(tahoe)
603 	/*
604 	 * Define new keys.
605 	 */
606 	if (p->p_textp == 0) {	/* use existing code key if shared */
607 		ckeyrelease(p->p_ckey);
608 		p->p_ckey = getcodekey();
609 	}
610 	mtpr(CCK, p->p_ckey);
611 	dkeyrelease(p->p_dkey);
612 	p->p_dkey = getdatakey();
613 	mtpr(DCK, p->p_dkey);
614 #endif
615 	if ((flags & SPAGV) && p->p_textp)
616 		vinifod(p, (struct fpte *)dptopte(p, 0),
617 		    PG_FTEXT, p->p_textp->x_vptr,
618 		    (long)(1 + ts/CLSIZE), (segsz_t)btoc(ep->a_data));
619 
620 #if defined(vax) || defined(tahoe)
621 	/* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */
622 	mtpr(TBIA, 0);
623 #endif
624 #ifdef hp300
625 	TBIAU();
626 #endif
627 #if defined(i386)
628 	tlbflush();
629 #endif
630 
631 	/*
632 	 * set SUID/SGID protections, if no tracing
633 	 */
634 	if ((p->p_flag&STRC)==0) {
635 		if (uid != cred->cr_uid || gid != cred->cr_gid)
636 			u.u_cred = cred = crcopy(cred);
637 		cred->cr_uid = uid;
638 		cred->cr_gid = gid;
639 		p->p_uid = uid;
640 	} else
641 		psignal(p, SIGTRAP);
642 	p->p_svuid = p->p_uid;
643 	p->p_svgid = cred->cr_gid;
644 	u.u_tsize = ts;
645 	u.u_dsize = ds;
646 	u.u_ssize = ss;
647 	u.u_prof.pr_scale = 0;
648 #if defined(tahoe)
649 	u.u_pcb.pcb_savacc.faddr = (float *)NULL;
650 #endif
651 	return (0);
652 }
653