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