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