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