xref: /csrg-svn/sys/kern/kern_proc.c (revision 238)
1 /*	kern_proc.c	3.11	06/07/80	*/
2 
3 #include "../h/param.h"
4 #include "../h/systm.h"
5 #include "../h/map.h"
6 #include "../h/mtpr.h"
7 #include "../h/dir.h"
8 #include "../h/user.h"
9 #include "../h/proc.h"
10 #include "../h/buf.h"
11 #include "../h/reg.h"
12 #include "../h/inode.h"
13 #include "../h/seg.h"
14 #include "../h/acct.h"
15 #include "/usr/include/wait.h"
16 #include "../h/pte.h"
17 #include "../h/vm.h"
18 #include "../h/text.h"
19 #include "../h/psl.h"
20 
21 /*
22  * exec system call, with and without environments.
23  */
24 struct execa {
25 	char	*fname;
26 	char	**argp;
27 	char	**envp;
28 };
29 
30 exec()
31 {
32 	((struct execa *)u.u_ap)->envp = NULL;
33 	exece();
34 }
35 
36 exece()
37 {
38 	register nc;
39 	register char *cp;
40 	register struct buf *bp;
41 	register struct execa *uap;
42 	int na, ne, ucp, ap, c;
43 	struct inode *ip;
44 	swblk_t bno;
45 
46 	if ((ip = namei(uchar, 0)) == NULL)
47 		return;
48 	bno = 0;
49 	bp = 0;
50 	if(access(ip, IEXEC))
51 		goto bad;
52 	if((ip->i_mode & IFMT) != IFREG ||
53 	   (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) {
54 		u.u_error = EACCES;
55 		goto bad;
56 	}
57 	/*
58 	 * Collect arguments on "file" in swap space.
59 	 */
60 	na = 0;
61 	ne = 0;
62 	nc = 0;
63 	uap = (struct execa *)u.u_ap;
64 	if ((bno = malloc(swapmap, ctod(clrnd((int) btoc(NCARGS))))) == 0) {
65 		swkill(u.u_procp, "exece");
66 		goto bad;
67 	}
68 	if (bno % CLSIZE)
69 		panic("execa malloc");
70 	if (uap->argp) for (;;) {
71 		ap = NULL;
72 		if (uap->argp) {
73 			ap = fuword((caddr_t)uap->argp);
74 			uap->argp++;
75 		}
76 		if (ap==NULL && uap->envp) {
77 			uap->argp = NULL;
78 			if ((ap = fuword((caddr_t)uap->envp)) == NULL)
79 				break;
80 			uap->envp++;
81 			ne++;
82 		}
83 		if (ap==NULL)
84 			break;
85 		na++;
86 		if(ap == -1)
87 			u.u_error = EFAULT;
88 		do {
89 			if (nc >= NCARGS-1)
90 				u.u_error = E2BIG;
91 			if ((c = fubyte((caddr_t)ap++)) < 0)
92 				u.u_error = EFAULT;
93 			if (u.u_error) {
94 				if (bp)
95 					brelse(bp);
96 				bp = 0;
97 				goto badarg;
98 			}
99 			if ((nc&BMASK) == 0) {
100 				if (bp)
101 					bdwrite(bp);
102 				bp = getblk(swapdev,
103 				    (daddr_t)(dbtofsb(swplo+bno)+(nc>>BSHIFT)));
104 				cp = bp->b_un.b_addr;
105 			}
106 			nc++;
107 			*cp++ = c;
108 		} while (c>0);
109 	}
110 	if (bp)
111 		bdwrite(bp);
112 	bp = 0;
113 	nc = (nc + NBPW-1) & ~(NBPW-1);
114 	if (getxfile(ip, nc) || u.u_error) {
115 badarg:
116 		for (c = 0; c < nc; c += BSIZE)
117 			if (bp = baddr(swapdev, dbtofsb(swplo+bno)+(c>>BSHIFT))) {
118 				bp->b_flags |= B_AGE;		/* throw away */
119 				bp->b_flags &= ~B_DELWRI;	/* cancel io */
120 				brelse(bp);
121 				bp = 0;
122 			}
123 		goto bad;
124 	}
125 
126 	/*
127 	 * copy back arglist
128 	 */
129 
130 	ucp = USRSTACK - nc - NBPW;
131 	ap = ucp - na*NBPW - 3*NBPW;
132 	u.u_ar0[SP] = ap;
133 	(void) suword((caddr_t)ap, na-ne);
134 	nc = 0;
135 	for (;;) {
136 		ap += NBPW;
137 		if (na==ne) {
138 			(void) suword((caddr_t)ap, 0);
139 			ap += NBPW;
140 		}
141 		if (--na < 0)
142 			break;
143 		(void) suword((caddr_t)ap, ucp);
144 		do {
145 			if ((nc&BMASK) == 0) {
146 				if (bp)
147 					brelse(bp);
148 				bp = bread(swapdev,
149 				    (daddr_t)(dbtofsb(swplo+bno)+(nc>>BSHIFT)));
150 				bp->b_flags |= B_AGE;		/* throw away */
151 				bp->b_flags &= ~B_DELWRI;	/* cancel io */
152 				cp = bp->b_un.b_addr;
153 			}
154 			(void) subyte((caddr_t)ucp++, (c = *cp++));
155 			nc++;
156 		} while(c&0377);
157 	}
158 	(void) suword((caddr_t)ap, 0);
159 	(void) suword((caddr_t)ucp, 0);
160 	setregs();
161 bad:
162 	if (bp)
163 		brelse(bp);
164 	if (bno)
165 		mfree(swapmap, ctod(clrnd((int) btoc(NCARGS))), bno);
166 	iput(ip);
167 }
168 
169 /*
170  * Read in and set up memory for executed file.
171  * Zero return is normal;
172  * non-zero means only the text is being replaced
173  */
174 getxfile(ip, nargc)
175 register struct inode *ip;
176 {
177 	register sep;
178 	register size_t ts, ds, ss;
179 	register int overlay;
180 	int pagi = 0;
181 
182 	/*
183 	 * read in first few bytes
184 	 * of file for segment
185 	 * sizes:
186 	 * ux_mag = 407/410/411/405
187 	 *  407 is plain executable
188 	 *  410 is RO text
189 	 *  411 is separated ID
190 	 *  405 is overlaid text
191 	 *  412 is demand paged plain executable (NOT IMPLEMENTED)
192 	 *  413 is demand paged RO text
193 	 */
194 
195 	u.u_base = (caddr_t)&u.u_exdata;
196 	u.u_count = sizeof(u.u_exdata);
197 	u.u_offset = 0;
198 	u.u_segflg = 1;
199 	readi(ip);
200 	u.u_segflg = 0;
201 	if(u.u_error)
202 		goto bad;
203 	if (u.u_count!=0) {
204 		u.u_error = ENOEXEC;
205 		goto bad;
206 	}
207 	sep = 0;
208 	overlay = 0;
209 	switch (u.u_exdata.ux_mag) {
210 
211 	case 0405:
212 		overlay++;
213 		break;
214 
215 	case 0412:
216 		u.u_error = ENOEXEC;
217 		goto bad;
218 
219 	case 0407:
220 		u.u_exdata.ux_dsize += u.u_exdata.ux_tsize;
221 		u.u_exdata.ux_tsize = 0;
222 		break;
223 
224 	case 0413:
225 		pagi = SPAGI;
226 		/* fall into ... */
227 
228 	case 0410:
229 		if (u.u_exdata.ux_tsize == 0) {
230 			u.u_error = ENOEXEC;
231 			goto bad;
232 		}
233 		break;
234 
235 	case 0411:
236 		u.u_error = ENOEXEC;
237 		goto bad;
238 
239 	default:
240 		u.u_error = ENOEXEC;
241 		goto bad;
242 	}
243 	if(u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && ip->i_count!=1) {
244 		u.u_error = ETXTBSY;
245 		goto bad;
246 	}
247 
248 	/*
249 	 * find text and data sizes
250 	 * try them out for possible
251 	 * exceed of max sizes
252 	 */
253 
254 	ts = clrnd(btoc(u.u_exdata.ux_tsize));
255 	ds = clrnd(btoc((u.u_exdata.ux_dsize+u.u_exdata.ux_bsize)));
256 	ss = clrnd(SSIZE + btoc(nargc));
257 	if (overlay) {
258 		if ((u.u_procp->p_flag & SPAGI) ||
259 		    u.u_sep==0 && ctos(ts) != ctos(u.u_tsize) || nargc) {
260 			u.u_error = ENOMEM;
261 			goto bad;
262 		}
263 		ds = u.u_dsize;
264 		ss = u.u_ssize;
265 		sep = u.u_sep;
266 		xfree();
267 		xalloc(ip, pagi);
268 		u.u_ar0[PC] = u.u_exdata.ux_entloc + 2; /* skip over entry mask */
269 	} else {
270 		if (chksize(ts, ds, ss))
271 			goto bad;
272 		u.u_cdmap = zdmap;
273 		u.u_csmap = zdmap;
274 		if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL)
275 			goto bad;
276 
277 		/*
278 		 * At this point, committed to the new image!
279 		 * Release virtual memory resources of old process, and
280 		 * initialize the virtual memory of the new process.
281 		 * If we resulted from vfork(), instead wakeup our
282 		 * parent who will set SVFDONE when he has taken back
283 		 * our resources.
284 		 */
285 		u.u_prof.pr_scale = 0;
286 		if ((u.u_procp->p_flag & SVFORK) == 0)
287 			vrelvm();
288 		else {
289 			u.u_procp->p_flag &= ~SVFORK;
290 			u.u_procp->p_flag |= SKEEP;
291 			wakeup((caddr_t)u.u_procp);
292 			while ((u.u_procp->p_flag & SVFDONE) == 0)
293 				sleep((caddr_t)u.u_procp, PZERO - 1);
294 			u.u_procp->p_flag &= ~(SVFDONE|SKEEP);
295 		}
296 		u.u_procp->p_flag &= ~(SPAGI|SANOM|SUANOM);
297 		u.u_procp->p_flag |= pagi;
298 		u.u_dmap = u.u_cdmap;
299 		u.u_smap = u.u_csmap;
300 		vgetvm(ts, ds, ss);
301 
302 		if (pagi == 0) {
303 			/*
304 			 * Read in data segment.
305 			 */
306 			u.u_base = (char *)ctob(ts);
307 			u.u_offset = sizeof(u.u_exdata)+u.u_exdata.ux_tsize;
308 			u.u_count = u.u_exdata.ux_dsize;
309 			readi(ip);
310 		}
311 		xalloc(ip, pagi);
312 		if (pagi && u.u_procp->p_textp)
313 			vinifod((struct fpte *)dptopte(u.u_procp, 0),
314 			    PG_FTEXT, u.u_procp->p_textp->x_iptr,
315 			    1 + ts/CLSIZE, (int)btoc(u.u_exdata.ux_dsize));
316 
317 		/* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */
318 		mtpr(TBIA,1);
319 
320 		/*
321 		 * set SUID/SGID protections, if no tracing
322 		 */
323 		if ((u.u_procp->p_flag&STRC)==0) {
324 			if(ip->i_mode&ISUID)
325 				if(u.u_uid != 0) {
326 					u.u_uid = ip->i_uid;
327 					u.u_procp->p_uid = ip->i_uid;
328 				}
329 			if(ip->i_mode&ISGID)
330 				u.u_gid = ip->i_gid;
331 		} else
332 			psignal(u.u_procp, SIGTRAP);
333 	}
334 	u.u_tsize = ts;
335 	u.u_dsize = ds;
336 	u.u_ssize = ss;
337 	u.u_sep = sep;
338 bad:
339 	return(overlay);
340 }
341 
342 /*
343  * Clear registers on exec
344  */
345 setregs()
346 {
347 	register int (**rp)();
348 	register i;
349 	long sigmask;
350 
351 	for(rp = &u.u_signal[0], sigmask = 1L; rp < &u.u_signal[NSIG];
352 	    sigmask <<= 1, rp++) {
353 		switch (*rp) {
354 
355 		case SIG_IGN:
356 		case SIG_DFL:
357 		case SIG_HOLD:
358 			continue;
359 
360 		default:
361 			/*
362 			 * Normal or deferring catch; revert to default.
363 			 */
364 			(void) spl6();
365 			*rp = SIG_DFL;
366 			if ((int)*rp & 1)
367 				u.u_procp->p_siga0 |= sigmask;
368 			else
369 				u.u_procp->p_siga1 &= ~sigmask;
370 			if ((int)*rp & 2)
371 				u.u_procp->p_siga1 |= sigmask;
372 			else
373 				u.u_procp->p_siga1 &= ~sigmask;
374 			(void) spl0();
375 			continue;
376 		}
377 	}
378 /*
379 	for(rp = &u.u_ar0[0]; rp < &u.u_ar0[16];)
380 		*rp++ = 0;
381 */
382 	u.u_ar0[PC] = u.u_exdata.ux_entloc + 2; /* skip over entry mask */
383 	for(i=0; i<NOFILE; i++) {
384 		if (u.u_pofile[i]&EXCLOSE) {
385 			closef(u.u_ofile[i]);
386 			u.u_ofile[i] = NULL;
387 			u.u_pofile[i] &= ~EXCLOSE;
388 		}
389 	}
390 	/*
391 	 * Remember file name for accounting.
392 	 */
393 	u.u_acflag &= ~AFORK;
394 	bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_comm, DIRSIZ);
395 }
396 
397 /*
398  * exit system call:
399  * pass back caller's arg
400  */
401 rexit()
402 {
403 	register struct a {
404 		int	rval;
405 	} *uap;
406 
407 	uap = (struct a *)u.u_ap;
408 	exit((uap->rval & 0377) << 8);
409 }
410 
411 /*
412  * Release resources.
413  * Save u. area for parent to look at.
414  * Enter zombie state.
415  * Wake up parent and init processes,
416  * and dispose of children.
417  */
418 exit(rv)
419 {
420 	register int i;
421 	register struct proc *p, *q;
422 	register struct file *f;
423 	register int x;
424 
425 #ifdef PGINPROF
426 	vmsizmon();
427 #endif
428 	p = u.u_procp;
429 	p->p_flag &= ~(STRC|SULOCK);
430 	p->p_flag |= SWEXIT;
431 	p->p_clktim = 0;
432 	(void) spl6();
433 	if ((int)SIG_IGN & 1)
434 		p->p_siga0 = ~0;
435 	else
436 		p->p_siga0 = 0;
437 	if ((int)SIG_IGN & 2)
438 		p->p_siga1 = ~0;
439 	else
440 		p->p_siga1 = 0;
441 	(void) spl0();
442 	rate.v_pgin -= p->p_aveflt;
443 	p->p_aveflt = 0;
444 	for(i=0; i<NSIG; i++)
445 		u.u_signal[i] = SIG_IGN;
446 	/*
447 	 * Release virtual memory.  If we resulted from
448 	 * a vfork(), instead give the resources back to
449 	 * the parent.
450 	 */
451 	if ((p->p_flag & SVFORK) == 0)
452 		vrelvm();
453 	else {
454 		p->p_flag &= ~SVFORK;
455 		wakeup((caddr_t)p);
456 		while ((p->p_flag & SVFDONE) == 0)
457 			sleep((caddr_t)p, PZERO - 1);
458 		p->p_flag &= ~SVFDONE;
459 	}
460 	for(i=0; i<NOFILE; i++) {
461 		f = u.u_ofile[i];
462 		u.u_ofile[i] = NULL;
463 		closef(f);
464 	}
465 	plock(u.u_cdir);
466 	iput(u.u_cdir);
467 	if (u.u_rdir) {
468 		plock(u.u_rdir);
469 		iput(u.u_rdir);
470 	}
471 	acct();
472 	vrelpt(u.u_procp);
473 	vrelu(u.u_procp, 0);
474 	multprog--;
475 	spl7();			/* clock will get mad because of overlaying */
476 	p->p_stat = SZOMB;
477 	i = PIDHASH(p->p_pid);
478 	x = p - proc;
479 	if (pidhash[i] == x)
480 		pidhash[i] = p->p_idhash;
481 	else {
482 		for (i = pidhash[i]; i != 0; i = proc[i].p_idhash)
483 			if (proc[i].p_idhash == x) {
484 				proc[i].p_idhash = p->p_idhash;
485 				goto done;
486 			}
487 		panic("exit");
488 	}
489 done:
490 	((struct xproc *)p)->xp_xstat = rv;		/* overlay */
491 	((struct xproc *)p)->xp_vm = u.u_vm;		/* overlay */
492 	vmsadd(&((struct xproc *)p)->xp_vm, &u.u_cvm);
493 	for(q = &proc[0]; q < &proc[NPROC]; q++)
494 		if(q->p_pptr == p) {
495 			q->p_pptr = &proc[1];
496 			q->p_ppid = 1;
497 			wakeup((caddr_t)&proc[1]);
498 			/*
499 			 * Traced processes are killed
500 			 * since their existence means someone is screwing up.
501 			 * Traced processes are sent a hangup and a continue.
502 			 * This is designed to be ``safe'' for setuid
503 			 * processes since they must be willing to tolerate
504 			 * hangups anyways.
505 			 */
506 			if (q->p_flag&STRC) {
507 				q->p_flag &= ~STRC;
508 				psignal(q, SIGKILL);
509 			} else if (q->p_stat == SSTOP) {
510 				psignal(q, SIGHUP);
511 				psignal(q, SIGCONT);
512 			}
513 			/*
514 			 * Protect this process from future
515 			 * tty signals, and clear TSTP/TTIN/TTOU if pending.
516 			 */
517 			q->p_pgrp = q->p_pid;
518 #define	bit(a)	(1<<(a-1))
519 			q->p_sig &= ~(bit(SIGTSTP)|bit(SIGTTIN)|bit(SIGTTOU));
520 		}
521 	wakeup((caddr_t)p->p_pptr);
522 	psignal(p->p_pptr, SIGCHLD);
523 	swtch();
524 }
525 
526 wait()
527 {
528 	struct vtimes vm;
529 	struct vtimes *vp;
530 
531 	if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) {
532 		wait1(0, (struct vtimes *)0);
533 		return;
534 	}
535 	vp = (struct vtimes *)u.u_ar0[R1];
536 	wait1(u.u_ar0[R0], &vm);
537 	if (u.u_error)
538 		return;
539 	(void) copyout((caddr_t)&vm, (caddr_t)vp, sizeof (struct vtimes));
540 }
541 
542 /*
543  * Wait system call.
544  * Search for a terminated (zombie) child,
545  * finally lay it to rest, and collect its status.
546  * Look also for stopped (traced) children,
547  * and pass back status from them.
548  */
549 wait1(options, vp)
550 	register options;
551 	struct vtimes *vp;
552 {
553 	register f;
554 	register struct proc *p;
555 
556 	f = 0;
557 loop:
558 	for(p = &proc[0]; p < &proc[NPROC]; p++)
559 	if(p->p_pptr == u.u_procp) {
560 		f++;
561 		if(p->p_stat == SZOMB) {
562 			u.u_r.r_val1 = p->p_pid;
563 			u.u_r.r_val2 = ((struct xproc *)p)->xp_xstat;
564 			((struct xproc *)p)->xp_xstat = 0;
565 			if (vp)
566 				*vp = ((struct xproc *)p)->xp_vm;
567 			vmsadd(&u.u_cvm, &((struct xproc *)p)->xp_vm);
568 			((struct xproc *)p)->xp_vm = zvms;
569 			p->p_stat = NULL;
570 			p->p_pid = 0;
571 			p->p_ppid = 0;
572 			p->p_pptr = 0;
573 			p->p_sig = 0;
574 			p->p_siga0 = 0;
575 			p->p_siga1 = 0;
576 			p->p_pgrp = 0;
577 			p->p_flag = 0;
578 			p->p_wchan = 0;
579 			p->p_cursig = 0;
580 			return;
581 		}
582 		if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 &&
583 		    (p->p_flag&STRC || options&WUNTRACED)) {
584 			p->p_flag |= SWTED;
585 			u.u_r.r_val1 = p->p_pid;
586 			u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED;
587 			return;
588 		}
589 	}
590 	if (f==0) {
591 		u.u_error = ECHILD;
592 		return;
593 	}
594 	if (options&WNOHANG) {
595 		u.u_r.r_val1 = 0;
596 		return;
597 	}
598 /*
599 	if (setjmp(u.u_qsav)) {
600 		u.u_eosys = RESTARTSYS;
601 		return;
602 	}
603 */
604 	sleep((caddr_t)u.u_procp, PWAIT);
605 	goto loop;
606 }
607 
608 /*
609  * fork system call.
610  */
611 fork()
612 {
613 
614 	u.u_cdmap = zdmap;
615 	u.u_csmap = zdmap;
616 	if (swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap) == 0) {
617 		u.u_r.r_val2 = 0;
618 		return;
619 	}
620 	fork1(0);
621 }
622 
623 fork1(isvfork)
624 {
625 	register struct proc *p1, *p2;
626 	register a;
627 
628 	a = 0;
629 	p2 = NULL;
630 	for(p1 = &proc[0]; p1 < &proc[NPROC]; p1++) {
631 		if (p1->p_stat==NULL && p2==NULL)
632 			p2 = p1;
633 		else {
634 			if (p1->p_uid==u.u_uid && p1->p_stat!=NULL)
635 				a++;
636 		}
637 	}
638 	/*
639 	 * Disallow if
640 	 *  No processes at all;
641 	 *  not su and too many procs owned; or
642 	 *  not su and would take last slot.
643 	 */
644 	if (p2==NULL || (u.u_uid!=0 && (p2==&proc[NPROC-1] || a>MAXUPRC))) {
645 		u.u_error = EAGAIN;
646 		if (!isvfork) {
647 			(void) vsexpand(0, &u.u_cdmap, 1);
648 			(void) vsexpand(0, &u.u_csmap, 1);
649 		}
650 		goto out;
651 	}
652 	p1 = u.u_procp;
653 	if(newproc(isvfork)) {
654 		u.u_r.r_val1 = p1->p_pid;
655 		u.u_r.r_val2 = 1;  /* child */
656 		u.u_start = time;
657 		u.u_acflag = AFORK;
658 		return;
659 	}
660 	u.u_r.r_val1 = p2->p_pid;
661 
662 out:
663 	u.u_r.r_val2 = 0;
664 }
665 
666 /*
667  * break system call.
668  *  -- bad planning: "break" is a dirty word in C.
669  */
670 sbreak()
671 {
672 	struct a {
673 		char	*nsiz;
674 	};
675 	register int n, d;
676 
677 	/*
678 	 * set n to new data size
679 	 * set d to new-old
680 	 */
681 
682 	n = btoc(((struct a *)u.u_ap)->nsiz);
683 	if (!u.u_sep)
684 		n -= ctos(u.u_tsize) * stoc(1);
685 	if (n < 0)
686 		n = 0;
687 	d = clrnd(n - u.u_dsize);
688 	if (chksize(u.u_tsize, u.u_dsize+d, u.u_ssize))
689 		return;
690 	if (swpexpand(u.u_dsize+d, u.u_ssize, &u.u_dmap, &u.u_smap)==0)
691 		return;
692 	expand(d, P0BR);
693 }
694