xref: /csrg-svn/sys/kern/kern_proc.c (revision 307)
1 /*	kern_proc.c	3.12	06/24/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(argmap, 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(argdev,
103 				    (daddr_t)(dbtofsb(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(argdev, dbtofsb(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(argdev,
149 				    (daddr_t)(dbtofsb(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(argmap, 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 	p->p_aveflt = 0;
443 	for(i=0; i<NSIG; i++)
444 		u.u_signal[i] = SIG_IGN;
445 	/*
446 	 * Release virtual memory.  If we resulted from
447 	 * a vfork(), instead give the resources back to
448 	 * the parent.
449 	 */
450 	if ((p->p_flag & SVFORK) == 0)
451 		vrelvm();
452 	else {
453 		p->p_flag &= ~SVFORK;
454 		wakeup((caddr_t)p);
455 		while ((p->p_flag & SVFDONE) == 0)
456 			sleep((caddr_t)p, PZERO - 1);
457 		p->p_flag &= ~SVFDONE;
458 	}
459 	for(i=0; i<NOFILE; i++) {
460 		f = u.u_ofile[i];
461 		u.u_ofile[i] = NULL;
462 		closef(f);
463 	}
464 	plock(u.u_cdir);
465 	iput(u.u_cdir);
466 	if (u.u_rdir) {
467 		plock(u.u_rdir);
468 		iput(u.u_rdir);
469 	}
470 	acct();
471 	vrelpt(u.u_procp);
472 	vrelu(u.u_procp, 0);
473 	multprog--;
474 /*	spl7();			/* clock will get mad because of overlaying */
475 	noproc = 1;
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 			spgrp(q, -1);
518 		}
519 	wakeup((caddr_t)p->p_pptr);
520 	psignal(p->p_pptr, SIGCHLD);
521 	swtch();
522 }
523 
524 wait()
525 {
526 	struct vtimes vm;
527 	struct vtimes *vp;
528 
529 	if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) {
530 		wait1(0, (struct vtimes *)0);
531 		return;
532 	}
533 	vp = (struct vtimes *)u.u_ar0[R1];
534 	wait1(u.u_ar0[R0], &vm);
535 	if (u.u_error)
536 		return;
537 	(void) copyout((caddr_t)&vm, (caddr_t)vp, sizeof (struct vtimes));
538 }
539 
540 /*
541  * Wait system call.
542  * Search for a terminated (zombie) child,
543  * finally lay it to rest, and collect its status.
544  * Look also for stopped (traced) children,
545  * and pass back status from them.
546  */
547 wait1(options, vp)
548 	register options;
549 	struct vtimes *vp;
550 {
551 	register f;
552 	register struct proc *p;
553 
554 	f = 0;
555 loop:
556 	for(p = &proc[0]; p < &proc[NPROC]; p++)
557 	if(p->p_pptr == u.u_procp) {
558 		f++;
559 		if(p->p_stat == SZOMB) {
560 			u.u_r.r_val1 = p->p_pid;
561 			u.u_r.r_val2 = ((struct xproc *)p)->xp_xstat;
562 			((struct xproc *)p)->xp_xstat = 0;
563 			if (vp)
564 				*vp = ((struct xproc *)p)->xp_vm;
565 			vmsadd(&u.u_cvm, &((struct xproc *)p)->xp_vm);
566 			((struct xproc *)p)->xp_vm = zvms;
567 			p->p_stat = NULL;
568 			p->p_pid = 0;
569 			p->p_ppid = 0;
570 			p->p_pptr = 0;
571 			p->p_sig = 0;
572 			p->p_siga0 = 0;
573 			p->p_siga1 = 0;
574 			p->p_pgrp = 0;
575 			p->p_flag = 0;
576 			p->p_wchan = 0;
577 			p->p_cursig = 0;
578 			return;
579 		}
580 		if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 &&
581 		    (p->p_flag&STRC || options&WUNTRACED)) {
582 			p->p_flag |= SWTED;
583 			u.u_r.r_val1 = p->p_pid;
584 			u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED;
585 			return;
586 		}
587 	}
588 	if (f==0) {
589 		u.u_error = ECHILD;
590 		return;
591 	}
592 	if (options&WNOHANG) {
593 		u.u_r.r_val1 = 0;
594 		return;
595 	}
596 /*
597 	if (setjmp(u.u_qsav)) {
598 		u.u_eosys = RESTARTSYS;
599 		return;
600 	}
601 */
602 	sleep((caddr_t)u.u_procp, PWAIT);
603 	goto loop;
604 }
605 
606 /*
607  * fork system call.
608  */
609 fork()
610 {
611 
612 	u.u_cdmap = zdmap;
613 	u.u_csmap = zdmap;
614 	if (swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap) == 0) {
615 		u.u_r.r_val2 = 0;
616 		return;
617 	}
618 	fork1(0);
619 }
620 
621 fork1(isvfork)
622 {
623 	register struct proc *p1, *p2;
624 	register a;
625 
626 	a = 0;
627 	p2 = NULL;
628 	for(p1 = &proc[0]; p1 < &proc[NPROC]; p1++) {
629 		if (p1->p_stat==NULL && p2==NULL)
630 			p2 = p1;
631 		else {
632 			if (p1->p_uid==u.u_uid && p1->p_stat!=NULL)
633 				a++;
634 		}
635 	}
636 	/*
637 	 * Disallow if
638 	 *  No processes at all;
639 	 *  not su and too many procs owned; or
640 	 *  not su and would take last slot.
641 	 */
642 	if (p2==NULL || (u.u_uid!=0 && (p2==&proc[NPROC-1] || a>MAXUPRC))) {
643 		u.u_error = EAGAIN;
644 		if (!isvfork) {
645 			(void) vsexpand(0, &u.u_cdmap, 1);
646 			(void) vsexpand(0, &u.u_csmap, 1);
647 		}
648 		goto out;
649 	}
650 	p1 = u.u_procp;
651 	if(newproc(isvfork)) {
652 		u.u_r.r_val1 = p1->p_pid;
653 		u.u_r.r_val2 = 1;  /* child */
654 		u.u_start = time;
655 		u.u_acflag = AFORK;
656 		return;
657 	}
658 	u.u_r.r_val1 = p2->p_pid;
659 
660 out:
661 	u.u_r.r_val2 = 0;
662 }
663 
664 /*
665  * break system call.
666  *  -- bad planning: "break" is a dirty word in C.
667  */
668 sbreak()
669 {
670 	struct a {
671 		char	*nsiz;
672 	};
673 	register int n, d;
674 
675 	/*
676 	 * set n to new data size
677 	 * set d to new-old
678 	 */
679 
680 	n = btoc(((struct a *)u.u_ap)->nsiz);
681 	if (!u.u_sep)
682 		n -= ctos(u.u_tsize) * stoc(1);
683 	if (n < 0)
684 		n = 0;
685 	d = clrnd(n - u.u_dsize);
686 	if (chksize(u.u_tsize, u.u_dsize+d, u.u_ssize))
687 		return;
688 	if (swpexpand(u.u_dsize+d, u.u_ssize, &u.u_dmap, &u.u_smap)==0)
689 		return;
690 	expand(d, P0BR);
691 }
692