xref: /original-bsd/sys/kern/kern_exec.c (revision 536b6355)
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.11 (Berkeley) 07/03/89
18  */
19 
20 #include "param.h"
21 #include "systm.h"
22 #include "map.h"
23 #include "user.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 /*
45  * exec system call, with and without environments.
46  */
47 struct execa {
48 	char	*fname;
49 	char	**argp;
50 	char	**envp;
51 };
52 
53 execv()
54 {
55 	((struct execa *)u.u_ap)->envp = NULL;
56 	execve();
57 }
58 
59 execve()
60 {
61 	register nc;
62 	register char *cp;
63 	register struct buf *bp;
64 	struct buf *tbp;
65 	register struct execa *uap;
66 	int na, ne, ucp, ap, cc;
67 	unsigned len;
68 	int indir, uid, gid;
69 	char *sharg;
70 	struct vnode *vp;
71 	swblk_t bno;
72 	struct vattr vattr;
73 	char cfname[MAXCOMLEN + 1];
74 	char cfarg[MAXINTERP];
75 	union {
76 		char	ex_shell[MAXINTERP];	/* #! and interpreter name */
77 		struct	exec ex_exec;
78 	} exdata;
79 	register struct nameidata *ndp = &u.u_nd;
80 	int resid, error;
81 
82 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
83 	ndp->ni_segflg = UIO_USERSPACE;
84 	ndp->ni_dirp = ((struct execa *)u.u_ap)->fname;
85 	if (u.u_error = namei(ndp)) {
86 		return;
87 	}
88 	vp = ndp->ni_vp;
89 	bno = 0;
90 	bp = 0;
91 	indir = 0;
92 	uid = u.u_uid;
93 	gid = u.u_gid;
94 	if (u.u_error = VOP_GETATTR(vp, &vattr, u.u_cred))
95 		goto bad;
96 	if (vp->v_mount->m_flag & M_NOEXEC) {
97 		u.u_error = ENOEXEC;
98 		goto bad;
99 	}
100 	if ((vp->v_mount->m_flag & M_NOSUID) == 0) {
101 		if (vattr.va_mode & VSUID)
102 			uid = vattr.va_uid;
103 		if (vattr.va_mode & VSGID)
104 			gid = vattr.va_gid;
105 	}
106 
107   again:
108 	if (u.u_error = VOP_ACCESS(vp, VEXEC, u.u_cred))
109 		goto bad;
110 	if ((u.u_procp->p_flag & STRC) &&
111 	    (u.u_error = VOP_ACCESS(vp, VREAD, u.u_cred)))
112 		goto bad;
113 	if (vp->v_type != VREG ||
114 	    (vattr.va_mode & (VEXEC|(VEXEC>>3)|(VEXEC>>6))) == 0) {
115 		u.u_error = EACCES;
116 		goto bad;
117 	}
118 
119 	/*
120 	 * Read in first few bytes of file for segment sizes, magic number:
121 	 *	OMAGIC = plain executable
122 	 *	NMAGIC = RO text
123 	 *	ZMAGIC = demand paged RO text
124 	 * Also an ASCII line beginning with #! is
125 	 * the file name of a ``shell'' and arguments may be prepended
126 	 * to the argument list if given here.
127 	 *
128 	 * SHELL NAMES ARE LIMITED IN LENGTH.
129 	 *
130 	 * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM
131 	 * THE ASCII LINE.
132 	 */
133 	exdata.ex_shell[0] = '\0';	/* for zero length files */
134 	u.u_error = vn_rdwr(UIO_READ, vp, (caddr_t)&exdata, sizeof (exdata),
135 	    (off_t)0, UIO_SYSSPACE, (IO_UNIT|IO_NODELOCKED), u.u_cred, &resid);
136 	if (u.u_error)
137 		goto bad;
138 #ifndef lint
139 	if (resid > sizeof(exdata) - sizeof(exdata.ex_exec) &&
140 	    exdata.ex_shell[0] != '#') {
141 		u.u_error = ENOEXEC;
142 		goto bad;
143 	}
144 #endif
145 	switch ((int)exdata.ex_exec.a_magic) {
146 
147 	case OMAGIC:
148 		exdata.ex_exec.a_data += exdata.ex_exec.a_text;
149 		exdata.ex_exec.a_text = 0;
150 		break;
151 
152 	case ZMAGIC:
153 	case NMAGIC:
154 		if (exdata.ex_exec.a_text == 0) {
155 			u.u_error = ENOEXEC;
156 			goto bad;
157 		}
158 		break;
159 
160 	default:
161 		if (exdata.ex_shell[0] != '#' ||
162 		    exdata.ex_shell[1] != '!' ||
163 		    indir) {
164 			u.u_error = ENOEXEC;
165 			goto bad;
166 		}
167 		for (cp = &exdata.ex_shell[2];; ++cp) {
168 			if (cp >= &exdata.ex_shell[MAXINTERP]) {
169 				u.u_error = ENOEXEC;
170 				goto bad;
171 			}
172 			if (*cp == '\n') {
173 				*cp = '\0';
174 				break;
175 			}
176 			if (*cp == '\t')
177 				*cp = ' ';
178 		}
179 		cp = &exdata.ex_shell[2];
180 		while (*cp == ' ')
181 			cp++;
182 		ndp->ni_dirp = cp;
183 		while (*cp && *cp != ' ')
184 			cp++;
185 		cfarg[0] = '\0';
186 		if (*cp) {
187 			*cp++ = '\0';
188 			while (*cp == ' ')
189 				cp++;
190 			if (*cp)
191 				bcopy((caddr_t)cp, (caddr_t)cfarg, MAXINTERP);
192 		}
193 		indir = 1;
194 		vput(vp);
195 		ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
196 		ndp->ni_segflg = UIO_SYSSPACE;
197 		if (u.u_error = namei(ndp))
198 			return;
199 		vp = ndp->ni_vp;
200 		if (u.u_error = VOP_GETATTR(vp, &vattr, u.u_cred))
201 			goto bad;
202 		bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)cfname,
203 		    MAXCOMLEN);
204 		cfname[MAXCOMLEN] = '\0';
205 		uid = u.u_uid;		/* shell scripts can't be setuid */
206 		gid = u.u_gid;
207 		goto again;
208 	}
209 
210 	/*
211 	 * Collect arguments on "file" in swap space.
212 	 */
213 	na = 0;
214 	ne = 0;
215 	nc = 0;
216 	cc = 0;
217 	uap = (struct execa *)u.u_ap;
218 	bno = rmalloc(argmap, (long)ctod(clrnd((int)btoc(NCARGS))));
219 	if (bno == 0) {
220 		swkill(u.u_procp, "exec: no swap space");
221 		goto bad;
222 	}
223 	if (bno % CLSIZE)
224 		panic("execa rmalloc");
225 	/*
226 	 * Copy arguments into file in argdev area.
227 	 */
228 	if (uap->argp) for (;;) {
229 		ap = NULL;
230 		sharg = NULL;
231 		if (indir && na == 0) {
232 			sharg = cfname;
233 			ap = (int)sharg;
234 			uap->argp++;		/* ignore argv[0] */
235 		} else if (indir && (na == 1 && cfarg[0])) {
236 			sharg = cfarg;
237 			ap = (int)sharg;
238 		} else if (indir && (na == 1 || na == 2 && cfarg[0]))
239 			ap = (int)uap->fname;
240 		else if (uap->argp) {
241 			ap = fuword((caddr_t)uap->argp);
242 			uap->argp++;
243 		}
244 		if (ap == NULL && uap->envp) {
245 			uap->argp = NULL;
246 			if ((ap = fuword((caddr_t)uap->envp)) != NULL)
247 				uap->envp++, ne++;
248 		}
249 		if (ap == NULL)
250 			break;
251 		na++;
252 		if (ap == -1) {
253 			u.u_error = EFAULT;
254 			break;
255 		}
256 		do {
257 			if (cc <= 0) {
258 				/*
259 				 * We depend on NCARGS being a multiple of
260 				 * CLBYTES.  This way we need only check
261 				 * overflow before each buffer allocation.
262 				 */
263 				if (nc >= NCARGS-1) {
264 					error = E2BIG;
265 					break;
266 				}
267 				if (bp)
268 					bdwrite(bp);
269 				cc = CLBYTES;
270 				bp = getblk(argdev_vp, bno + ctod(nc/NBPG), cc);
271 				cp = bp->b_un.b_addr;
272 			}
273 			if (sharg) {
274 				error = copystr(sharg, cp, (unsigned)cc, &len);
275 				sharg += len;
276 			} else {
277 				error = copyinstr((caddr_t)ap, cp, (unsigned)cc,
278 				    &len);
279 				ap += len;
280 			}
281 			cp += len;
282 			nc += len;
283 			cc -= len;
284 		} while (error == ENOENT);
285 		if (error) {
286 			u.u_error = error;
287 			if (bp)
288 				brelse(bp);
289 			bp = 0;
290 			goto badarg;
291 		}
292 	}
293 	if (bp)
294 		bdwrite(bp);
295 	bp = 0;
296 	nc = (nc + NBPW-1) & ~(NBPW-1);
297 	getxfile(vp, &exdata.ex_exec, nc + (na+4)*NBPW, uid, gid, u.u_cred);
298 	if (u.u_error) {
299 badarg:
300 		for (cc = 0; cc < nc; cc += CLBYTES) {
301 			u.u_error = baddr(argdev_vp, bno + ctod(cc/NBPG),
302 				CLBYTES, &tbp);
303 			bp = tbp;
304 			if (bp) {
305 				bp->b_flags |= B_AGE;		/* throw away */
306 				bp->b_flags &= ~B_DELWRI;	/* cancel io */
307 				brelse(bp);
308 				bp = 0;
309 			}
310 		}
311 		goto bad;
312 	}
313 	vput(vp);
314 	vp = NULL;
315 
316 	/*
317 	 * Copy back arglist.
318 	 */
319 	ucp = USRSTACK - nc - NBPW;
320 	ap = ucp - na*NBPW - 3*NBPW;
321 	u.u_ar0[SP] = ap;
322 	(void) suword((caddr_t)ap, na-ne);
323 	nc = 0;
324 	cc = 0;
325 	for (;;) {
326 		ap += NBPW;
327 		if (na == ne) {
328 			(void) suword((caddr_t)ap, 0);
329 			ap += NBPW;
330 		}
331 		if (--na < 0)
332 			break;
333 		(void) suword((caddr_t)ap, ucp);
334 		do {
335 			if (cc <= 0) {
336 				if (bp)
337 					brelse(bp);
338 				cc = CLBYTES;
339 				error = bread(argdev_vp,
340 				    (daddr_t)(bno + ctod(nc / NBPG)), cc, &tbp);
341 				bp = tbp;
342 				bp->b_flags |= B_AGE;		/* throw away */
343 				bp->b_flags &= ~B_DELWRI;	/* cancel io */
344 				cp = bp->b_un.b_addr;
345 			}
346 			error = copyoutstr(cp, (caddr_t)ucp, (unsigned)cc,
347 			    &len);
348 			ucp += len;
349 			cp += len;
350 			nc += len;
351 			cc -= len;
352 		} while (error == ENOENT);
353 		if (error == EFAULT)
354 			panic("exec: EFAULT");
355 	}
356 	(void) suword((caddr_t)ap, 0);
357 
358 	/*
359 	 * Reset caught signals.  Held signals
360 	 * remain held through p_sigmask.
361 	 */
362 	while (u.u_procp->p_sigcatch) {
363 		nc = ffs((long)u.u_procp->p_sigcatch);
364 		u.u_procp->p_sigcatch &= ~sigmask(nc);
365 		u.u_signal[nc] = SIG_DFL;
366 	}
367 	/*
368 	 * Reset stack state to the user stack.
369 	 * Clear set of signals caught on the signal stack.
370 	 */
371 	u.u_onstack = 0;
372 	u.u_sigsp = 0;
373 	u.u_sigonstack = 0;
374 
375 	for (nc = u.u_lastfile; nc >= 0; --nc) {
376 		if (u.u_pofile[nc] & UF_EXCLOSE) {
377 			closef(u.u_ofile[nc]);
378 			u.u_ofile[nc] = NULL;
379 			u.u_pofile[nc] = 0;
380 		}
381 		u.u_pofile[nc] &= ~UF_MAPPED;
382 	}
383 	while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL)
384 		u.u_lastfile--;
385 	setregs(exdata.ex_exec.a_entry);
386 	/*
387 	 * Remember file name for accounting.
388 	 */
389 	u.u_acflag &= ~AFORK;
390 	if (indir)
391 		bcopy((caddr_t)cfname, (caddr_t)u.u_comm, MAXCOMLEN);
392 	else {
393 		if (ndp->ni_dent.d_namlen > MAXCOMLEN)
394 			ndp->ni_dent.d_namlen = MAXCOMLEN;
395 		bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)u.u_comm,
396 		    (unsigned)(ndp->ni_dent.d_namlen + 1));
397 	}
398 bad:
399 	if (bp)
400 		brelse(bp);
401 	if (bno)
402 		rmfree(argmap, (long)ctod(clrnd((int) btoc(NCARGS))), bno);
403 	if (vp)
404 		vput(vp);
405 }
406 
407 /*
408  * Read in and set up memory for executed file.
409  */
410 getxfile(vp, ep, nargc, uid, gid, cred)
411 	register struct vnode *vp;
412 	register struct exec *ep;
413 	int nargc, uid, gid;
414 	struct ucred *cred;
415 {
416 	size_t ts, ds, ids, uds, ss;
417 	int pagi;
418 
419 	if (ep->a_magic == ZMAGIC)
420 		pagi = SPAGV;
421 	else
422 		pagi = 0;
423 	if (vp->v_text && (vp->v_text->x_flag & XTRC)) {
424 		u.u_error = ETXTBSY;
425 		goto bad;
426 	}
427 	if (ep->a_text != 0 && (vp->v_flag & VTEXT) == 0 &&
428 	    vp->v_count != 1) {
429 		register struct file *fp;
430 
431 		for (fp = file; fp < fileNFILE; fp++) {
432 			if (fp->f_type == DTYPE_VNODE &&
433 			    fp->f_count > 0 &&
434 			    (struct vnode *)fp->f_data == vp &&
435 			    (fp->f_flag & FWRITE)) {
436 				u.u_error = ETXTBSY;
437 				goto bad;
438 			}
439 		}
440 	}
441 
442 	/*
443 	 * Compute text and data sizes and make sure not too large.
444 	 * NB - Check data and bss separately as they may overflow
445 	 * when summed together.
446 	 */
447 	ts = clrnd(btoc(ep->a_text));
448 	ids = clrnd(btoc(ep->a_data));
449 	uds = clrnd(btoc(ep->a_bss));
450 	ds = clrnd(btoc(ep->a_data + ep->a_bss));
451 	ss = clrnd(SSIZE + btoc(nargc));
452 	if (chksize((unsigned)ts, (unsigned)ids, (unsigned)uds, (unsigned)ss))
453 		goto bad;
454 
455 	/*
456 	 * Make sure enough space to start process.
457 	 */
458 	u.u_cdmap = zdmap;
459 	u.u_csmap = zdmap;
460 	if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL)
461 		goto bad;
462 
463 	/*
464 	 * At this point, we are committed to the new image!
465 	 * Release virtual memory resources of old process, and
466 	 * initialize the virtual memory of the new process.
467 	 * If we resulted from vfork(), instead wakeup our
468 	 * parent who will set SVFDONE when he has taken back
469 	 * our resources.
470 	 */
471 	if ((u.u_procp->p_flag & SVFORK) == 0)
472 		vrelvm();
473 	else {
474 		u.u_procp->p_flag &= ~SVFORK;
475 		u.u_procp->p_flag |= SKEEP;
476 		wakeup((caddr_t)u.u_procp);
477 		while ((u.u_procp->p_flag & SVFDONE) == 0)
478 			sleep((caddr_t)u.u_procp, PZERO - 1);
479 		u.u_procp->p_flag &= ~(SVFDONE|SKEEP);
480 	}
481 	u.u_procp->p_flag &= ~(SPAGV|SSEQL|SUANOM|SOUSIG);
482 	u.u_procp->p_flag |= pagi | SEXEC;
483 	u.u_dmap = u.u_cdmap;
484 	u.u_smap = u.u_csmap;
485 	vgetvm(ts, ds, ss);
486 
487 	if (pagi == 0)
488 		u.u_error = vn_rdwr(UIO_READ, vp,
489 			(char *)ctob(dptov(u.u_procp, 0)),
490 			(int)ep->a_data,
491 			(off_t)(sizeof (struct exec) + ep->a_text),
492 			UIO_USERSPACE, (IO_UNIT|IO_NODELOCKED), cred, (int *)0);
493 	xalloc(vp, ep, pagi, cred);
494 #if defined(tahoe)
495 	/*
496 	 * Define new keys.
497 	 */
498 	if (u.u_procp->p_textp == 0) {	/* use existing code key if shared */
499 		ckeyrelease(u.u_procp->p_ckey);
500 		u.u_procp->p_ckey = getcodekey();
501 	}
502 	mtpr(CCK, u.u_procp->p_ckey);
503 	dkeyrelease(u.u_procp->p_dkey);
504 	u.u_procp->p_dkey = getdatakey();
505 	mtpr(DCK, u.u_procp->p_dkey);
506 #endif
507 	if (pagi && u.u_procp->p_textp)
508 		vinifod((struct fpte *)dptopte(u.u_procp, 0),
509 		    PG_FTEXT, u.u_procp->p_textp->x_vptr,
510 		    (long)(1 + ts/CLSIZE), (size_t)btoc(ep->a_data));
511 
512 #if defined(vax) || defined(tahoe)
513 	/* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */
514 	mtpr(TBIA, 0);
515 #endif
516 
517 	if (u.u_error)
518 		swkill(u.u_procp, "exec: I/O error mapping pages");
519 	/*
520 	 * set SUID/SGID protections, if no tracing
521 	 */
522 	if ((u.u_procp->p_flag&STRC)==0) {
523 		if (uid != u.u_uid || gid != u.u_gid)
524 			u.u_cred = crcopy(u.u_cred);
525 		u.u_uid = uid;
526 		u.u_procp->p_uid = uid;
527 		u.u_gid = gid;
528 	} else
529 		psignal(u.u_procp, SIGTRAP);
530 	u.u_tsize = ts;
531 	u.u_dsize = ds;
532 	u.u_ssize = ss;
533 	u.u_prof.pr_scale = 0;
534 #if defined(tahoe)
535 	u.u_pcb.pcb_savacc.faddr = (float *)NULL;
536 #endif
537 bad:
538 	return;
539 }
540