X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/81263dbac5438382d44727be195f8a206dc7e766..4e6e38871c68cf8ddfa65c3f6a0d0b2f3a1b2caf:/usr/src/sys/kern/kern_proc.c diff --git a/usr/src/sys/kern/kern_proc.c b/usr/src/sys/kern/kern_proc.c index eb160d6e74..53cab4f7c7 100644 --- a/usr/src/sys/kern/kern_proc.c +++ b/usr/src/sys/kern/kern_proc.c @@ -1,4 +1,4 @@ -/* kern_proc.c 3.3 %H% */ +/* kern_proc.c 4.25 82/04/02 */ #include "../h/param.h" #include "../h/systm.h" @@ -12,9 +12,13 @@ #include "../h/inode.h" #include "../h/seg.h" #include "../h/acct.h" +#include "/usr/include/wait.h" #include "../h/pte.h" #include "../h/vm.h" #include "../h/text.h" +#include "../h/psl.h" +#include "../h/vlimit.h" +#include "../h/file.h" /* * exec system call, with and without environments. @@ -38,20 +42,124 @@ exece() register struct buf *bp; register struct execa *uap; int na, ne, ucp, ap, c; + int indir, uid, gid; + char *sharg; struct inode *ip; swblk_t bno; + char cfname[DIRSIZ]; + char cfarg[SHSIZE]; - if ((ip = namei(uchar, 0)) == NULL) + if ((ip = namei(uchar, 0, 1)) == NULL) return; bno = 0; bp = 0; - if(access(ip, IEXEC)) + indir = 0; + uid = u.u_uid; + gid = u.u_gid; + if (ip->i_mode & ISUID) + uid = ip->i_uid; + if (ip->i_mode & ISGID) + gid = ip->i_gid; + + again: + if (access(ip, IEXEC)) goto bad; - if((ip->i_mode & IFMT) != IFREG || + if ((u.u_procp->p_flag&STRC) && access(ip, IREAD)) + goto bad; + if ((ip->i_mode & IFMT) != IFREG || (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) { u.u_error = EACCES; goto bad; } + + /* + * Read in first few bytes of file for segment sizes, ux_mag: + * 407 = plain executable + * 410 = RO text + * 413 = demand paged RO text + * Also an ASCII line beginning with #! is + * the file name of a ``shell'' and arguments may be prepended + * to the argument list if given here. + * + * SHELL NAMES ARE LIMITED IN LENGTH. + * + * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM + * THE ASCII LINE. + */ + u.u_base = (caddr_t)&u.u_exdata; + u.u_count = sizeof(u.u_exdata); + u.u_offset = 0; + u.u_segflg = 1; + readi(ip); + u.u_segflg = 0; + if (u.u_error) + goto bad; + if (u.u_count > sizeof(u.u_exdata) - sizeof(u.u_exdata.Ux_A) && + u.u_exdata.ux_shell[0] != '#') { + u.u_error = ENOEXEC; + goto bad; + } + switch (u.u_exdata.ux_mag) { + + case 0407: + u.u_exdata.ux_dsize += u.u_exdata.ux_tsize; + u.u_exdata.ux_tsize = 0; + break; + + case 0413: + case 0410: + if (u.u_exdata.ux_tsize == 0) { + u.u_error = ENOEXEC; + goto bad; + } + break; + + default: + if (u.u_exdata.ux_shell[0] != '#' || + u.u_exdata.ux_shell[1] != '!' || + indir) { + u.u_error = ENOEXEC; + goto bad; + } + cp = &u.u_exdata.ux_shell[2]; /* skip "#!" */ + while (cp < &u.u_exdata.ux_shell[SHSIZE]) { + if (*cp == '\t') + *cp = ' '; + else if (*cp == '\n') { + *cp = '\0'; + break; + } + cp++; + } + if (*cp != '\0') { + u.u_error = ENOEXEC; + goto bad; + } + cp = &u.u_exdata.ux_shell[2]; + while (*cp == ' ') + cp++; + u.u_dirp = cp; + while (*cp && *cp != ' ') + cp++; + sharg = NULL; + if (*cp) { + *cp++ = '\0'; + while (*cp == ' ') + cp++; + if (*cp) { + bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE); + sharg = cfarg; + } + } + bcopy((caddr_t)u.u_dbuf, (caddr_t)cfname, DIRSIZ); + indir = 1; + iput(ip); + ip = namei(schar, 0, 1); + if (ip == NULL) + return; + goto again; + } + /* * Collect arguments on "file" in swap space. */ @@ -59,15 +167,17 @@ exece() ne = 0; nc = 0; uap = (struct execa *)u.u_ap; - if ((bno = malloc(swapmap, ctod(clrnd((int) btoc(NCARGS))))) == 0) { + if ((bno = rmalloc(argmap, ctod(clrnd((int) btoc(NCARGS))))) == 0) { swkill(u.u_procp, "exece"); goto bad; } if (bno % CLSIZE) - panic("execa malloc"); + panic("execa rmalloc"); if (uap->argp) for (;;) { ap = NULL; - if (uap->argp) { + if (indir && (na == 1 || na == 2 && sharg)) + ap = (int)uap->fname; + else if (uap->argp) { ap = fuword((caddr_t)uap->argp); uap->argp++; } @@ -81,12 +191,14 @@ exece() if (ap==NULL) break; na++; - if(ap == -1) + if (ap == -1) u.u_error = EFAULT; do { if (nc >= NCARGS-1) u.u_error = E2BIG; - if ((c = fubyte((caddr_t)ap++)) < 0) + if (indir && na == 2 && sharg != NULL) + c = *sharg++ & 0377; + else if ((c = fubyte((caddr_t)ap++)) < 0) u.u_error = EFAULT; if (u.u_error) { if (bp) @@ -97,7 +209,8 @@ exece() if ((nc&BMASK) == 0) { if (bp) bdwrite(bp); - bp = getblk(swapdev, (daddr_t)(dbtofsb(swplo+bno)+(nc>>BSHIFT))); + bp = getblk(argdev, + (daddr_t)(dbtofsb(bno)+(nc>>BSHIFT))); cp = bp->b_un.b_addr; } nc++; @@ -108,10 +221,13 @@ exece() bdwrite(bp); bp = 0; nc = (nc + NBPW-1) & ~(NBPW-1); - if (getxfile(ip, nc) || u.u_error) { + if (indir) + bcopy((caddr_t)cfname, (caddr_t)u.u_dbuf, DIRSIZ); + getxfile(ip, nc + (na+4)*NBPW, uid, gid); + if (u.u_error) { badarg: for (c = 0; c < nc; c += BSIZE) - if (bp = baddr(swapdev, dbtofsb(swplo+bno)+(c>>BSHIFT))) { + if (bp = baddr(argdev, dbtofsb(bno)+(c>>BSHIFT))) { bp->b_flags |= B_AGE; /* throw away */ bp->b_flags &= ~B_DELWRI; /* cancel io */ brelse(bp); @@ -123,7 +239,6 @@ badarg: /* * copy back arglist */ - ucp = USRSTACK - nc - NBPW; ap = ucp - na*NBPW - 3*NBPW; u.u_ar0[SP] = ap; @@ -142,7 +257,8 @@ badarg: if ((nc&BMASK) == 0) { if (bp) brelse(bp); - bp = bread(swapdev, (daddr_t)(dbtofsb(swplo+bno)+(nc>>BSHIFT))); + bp = bread(argdev, + (daddr_t)(dbtofsb(bno)+(nc>>BSHIFT))); bp->b_flags |= B_AGE; /* throw away */ bp->b_flags &= ~B_DELWRI; /* cancel io */ cp = bp->b_un.b_addr; @@ -158,180 +274,112 @@ bad: if (bp) brelse(bp); if (bno) - mfree(swapmap, ctod(clrnd((int) btoc(NCARGS))), bno); + rmfree(argmap, ctod(clrnd((int) btoc(NCARGS))), bno); iput(ip); } /* * Read in and set up memory for executed file. - * Zero return is normal; - * non-zero means only the text is being replaced */ -getxfile(ip, nargc) +getxfile(ip, nargc, uid, gid) register struct inode *ip; { - register sep; register size_t ts, ds, ss; - register int overlay; - int pagi = 0; + int pagi; - /* - * read in first few bytes - * of file for segment - * sizes: - * ux_mag = 407/410/411/405 - * 407 is plain executable - * 410 is RO text - * 411 is separated ID - * 405 is overlaid text - * 412 is demand paged plain executable (NOT IMPLEMENTED) - * 413 is demand paged RO text - */ - - u.u_base = (caddr_t)&u.u_exdata; - u.u_count = sizeof(u.u_exdata); - u.u_offset = 0; - u.u_segflg = 1; - readi(ip); - u.u_segflg = 0; - if(u.u_error) - goto bad; - if (u.u_count!=0) { - u.u_error = ENOEXEC; - goto bad; - } - sep = 0; - overlay = 0; - switch (u.u_exdata.ux_mag) { - - case 0405: - overlay++; - break; - - case 0412: - u.u_error = ENOEXEC; - goto bad; - - case 0407: - u.u_exdata.ux_dsize += u.u_exdata.ux_tsize; - u.u_exdata.ux_tsize = 0; - break; - - case 0413: + if (u.u_exdata.ux_mag == 0413) pagi = SPAGI; - /* fall into ... */ - - case 0410: - if (u.u_exdata.ux_tsize == 0) { - u.u_error = ENOEXEC; - goto bad; + else + pagi = 0; + if (u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && + ip->i_count!=1) { + register struct file *fp; + + for (fp = file; fp < fileNFILE; fp++) { + if (fp->f_flag & FSOCKET) + continue; + if (fp->f_inode == ip && (fp->f_flag&FWRITE)) { + u.u_error = ETXTBSY; + goto bad; + } } - break; - - case 0411: - u.u_error = ENOEXEC; - goto bad; - - default: - u.u_error = ENOEXEC; - goto bad; - } - if(u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && ip->i_count!=1) { - u.u_error = ETXTBSY; - goto bad; } /* - * find text and data sizes - * try them out for possible - * exceed of max sizes + * Compute text and data sizes and make sure not too large. */ - ts = clrnd(btoc(u.u_exdata.ux_tsize)); ds = clrnd(btoc((u.u_exdata.ux_dsize+u.u_exdata.ux_bsize))); ss = clrnd(SSIZE + btoc(nargc)); - if (overlay) { - if ((u.u_procp->p_flag & SPAGI) || u.u_sep==0 && ctos(ts) != ctos(u.u_tsize) || nargc) { - u.u_error = ENOMEM; - goto bad; - } - ds = u.u_dsize; - ss = u.u_ssize; - sep = u.u_sep; - xfree(); - xalloc(ip, pagi); - u.u_ar0[PC] = u.u_exdata.ux_entloc + 2; /* skip over entry mask */ - } else { - if (chksize(ts, ds, ss)) - goto bad; - u.u_cdmap = zdmap; - u.u_csmap = zdmap; - if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL) - goto bad; - - /* - * At this point, committed to the new image! - * Release virtual memory resources of old process, and - * initialize the virtual memory of the new process. - * If we resulted from vfork(), instead wakeup our - * parent who will set SVFDONE when he has taken back - * our resources. - */ - u.u_prof.pr_scale = 0; - if ((u.u_procp->p_flag & SVFORK) == 0) - vrelvm(); - else { - u.u_procp->p_flag &= ~SVFORK; - u.u_procp->p_flag |= SKEEP; - wakeup((caddr_t)u.u_procp); - while ((u.u_procp->p_flag & SVFDONE) == 0) - sleep((caddr_t)u.u_procp, PZERO - 1); - u.u_procp->p_flag &= ~(SVFDONE|SKEEP); - } - u.u_procp->p_flag &= ~(SPAGI|SANOM|SUANOM); - u.u_procp->p_flag |= pagi; - u.u_dmap = u.u_cdmap; - u.u_smap = u.u_csmap; - vgetvm(ts, ds, ss); + if (chksize(ts, ds, ss)) + goto bad; - if (pagi == 0) { - /* - * Read in data segment. - */ - u.u_base = (char *)ctob(ts); - u.u_offset = sizeof(u.u_exdata)+u.u_exdata.ux_tsize; - u.u_count = u.u_exdata.ux_dsize; - readi(ip); - } - xalloc(ip, pagi); - if (pagi && u.u_procp->p_textp) - vinifod((struct fpte *)dptopte(u.u_procp, 0), - PG_FTEXT, u.u_procp->p_textp->x_iptr, - 1 + ts/CLSIZE, (int)btoc(u.u_exdata.ux_dsize)); + /* + * Make sure enough space to start process. + */ + u.u_cdmap = zdmap; + u.u_csmap = zdmap; + if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL) + goto bad; - /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */ - mtpr(TBIA,1); + /* + * At this point, committed to the new image! + * Release virtual memory resources of old process, and + * initialize the virtual memory of the new process. + * If we resulted from vfork(), instead wakeup our + * parent who will set SVFDONE when he has taken back + * our resources. + */ + u.u_prof.pr_scale = 0; + if ((u.u_procp->p_flag & SVFORK) == 0) + vrelvm(); + else { + u.u_procp->p_flag &= ~SVFORK; + u.u_procp->p_flag |= SKEEP; + wakeup((caddr_t)u.u_procp); + while ((u.u_procp->p_flag & SVFDONE) == 0) + sleep((caddr_t)u.u_procp, PZERO - 1); + u.u_procp->p_flag &= ~(SVFDONE|SKEEP); + } + u.u_procp->p_flag &= ~(SPAGI|SSEQL|SUANOM|SNUSIG); + u.u_procp->p_flag |= pagi; + u.u_dmap = u.u_cdmap; + u.u_smap = u.u_csmap; + vgetvm(ts, ds, ss); + if (pagi == 0) { /* - * set SUID/SGID protections, if no tracing + * Read in data segment. */ - if ((u.u_procp->p_flag&STRC)==0) { - if(ip->i_mode&ISUID) - if(u.u_uid != 0) { - u.u_uid = ip->i_uid; - u.u_procp->p_uid = ip->i_uid; - } - if(ip->i_mode&ISGID) - u.u_gid = ip->i_gid; - } else - psignal(u.u_procp, SIGTRC); + u.u_base = (char *)ctob(ts); + u.u_offset = sizeof(u.u_exdata)+u.u_exdata.ux_tsize; + u.u_count = u.u_exdata.ux_dsize; + readi(ip); } + xalloc(ip, pagi); + if (pagi && u.u_procp->p_textp) + vinifod((struct fpte *)dptopte(u.u_procp, 0), + PG_FTEXT, u.u_procp->p_textp->x_iptr, + 1 + ts/CLSIZE, (int)btoc(u.u_exdata.ux_dsize)); + + /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */ + mtpr(TBIA, 0); + + /* + * set SUID/SGID protections, if no tracing + */ + if ((u.u_procp->p_flag&STRC)==0) { + u.u_uid = uid; + u.u_procp->p_uid = uid; + u.u_gid = gid; + u.u_grps[gid/(sizeof(int)*8)] |= 1 << (gid%(sizeof(int)*8)); + } else + psignal(u.u_procp, SIGTRAP); u.u_tsize = ts; u.u_dsize = ds; u.u_ssize = ss; - u.u_sep = sep; bad: - return(overlay); + return; } /* @@ -339,24 +387,50 @@ bad: */ setregs() { - register int *rp; + register int (**rp)(); register i; + long sigmask; + + for (rp = &u.u_signal[1], sigmask = 1L; rp < &u.u_signal[NSIG]; + sigmask <<= 1, rp++) { + switch (*rp) { - for(rp = &u.u_signal[0]; rp < &u.u_signal[NSIG]; rp++) - if((*rp & 1) == 0) - *rp = 0; + case SIG_IGN: + case SIG_DFL: + case SIG_HOLD: + continue; + + default: + /* + * Normal or deferring catch; revert to default. + */ + (void) spl6(); + *rp = SIG_DFL; + if ((int)*rp & 1) + u.u_procp->p_siga0 |= sigmask; + else + u.u_procp->p_siga0 &= ~sigmask; + if ((int)*rp & 2) + u.u_procp->p_siga1 |= sigmask; + else + u.u_procp->p_siga1 &= ~sigmask; + (void) spl0(); + continue; + } + } /* - for(rp = &u.u_ar0[0]; rp < &u.u_ar0[16];) + for (rp = &u.u_ar0[0]; rp < &u.u_ar0[16];) *rp++ = 0; */ u.u_ar0[PC] = u.u_exdata.ux_entloc + 2; /* skip over entry mask */ - for(i=0; ip_flag &= ~(STRC|SULOCK); p->p_flag |= SWEXIT; p->p_clktim = 0; - rate.v_pgin -= p->p_aveflt; - p->p_aveflt = 0; - for(i=0; ip_siga0 = ~0; + else + p->p_siga0 = 0; + if ((int)SIG_IGN & 2) + p->p_siga1 = ~0; + else + p->p_siga1 = 0; + (void) spl0(); + p->p_cpticks = 0; + p->p_pctcpu = 0; + for (i=0; ip_flag &= ~SVFDONE; } - for(i=0; ip_stat = SZOMB; + noproc = 1; i = PIDHASH(p->p_pid); x = p - proc; if (pidhash[i] == x) @@ -446,27 +531,57 @@ exit(rv) } panic("exit"); } + if (p->p_pid == 1) + panic("init died"); done: ((struct xproc *)p)->xp_xstat = rv; /* overlay */ ((struct xproc *)p)->xp_vm = u.u_vm; /* overlay */ vmsadd(&((struct xproc *)p)->xp_vm, &u.u_cvm); - for(q = &proc[0]; q < &proc[NPROC]; q++) - if(q->p_ppid == p->p_pid) { - wakeup((caddr_t)&proc[1]); + for (q = proc; q < procNPROC; q++) + if (q->p_pptr == p) { + q->p_pptr = &proc[1]; q->p_ppid = 1; - if (q->p_stat==SSTOP) - setrun(q); + wakeup((caddr_t)&proc[1]); + /* + * Traced processes are killed + * since their existence means someone is screwing up. + * Stopped processes are sent a hangup and a continue. + * This is designed to be ``safe'' for setuid + * processes since they must be willing to tolerate + * hangups anyways. + */ + if (q->p_flag&STRC) { + q->p_flag &= ~STRC; + psignal(q, SIGKILL); + } else if (q->p_stat == SSTOP) { + psignal(q, SIGHUP); + psignal(q, SIGCONT); + } + /* + * Protect this process from future + * tty signals, clear TSTP/TTIN/TTOU if pending. + */ + (void) spgrp(q, -1); } - q = pfind(p->p_ppid); - if (q) - wakeup((caddr_t)q); + psignal(p->p_pptr, SIGCHLD); + wakeup((caddr_t)p->p_pptr); swtch(); } wait() { + struct vtimes vm; + struct vtimes *vp; - wait1((struct vtimes *)0); + if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { + wait1(0, (struct vtimes *)0); + return; + } + vp = (struct vtimes *)u.u_ar0[R1]; + wait1(u.u_ar0[R0], &vm); + if (u.u_error) + return; + (void) copyout((caddr_t)&vm, (caddr_t)vp, sizeof (struct vtimes)); } /* @@ -476,19 +591,19 @@ wait() * Look also for stopped (traced) children, * and pass back status from them. */ -wait1(vp) +wait1(options, vp) + register options; struct vtimes *vp; { register f; register struct proc *p; f = 0; - loop: - for(p = &proc[0]; p < &proc[NPROC]; p++) - if(p->p_ppid == u.u_procp->p_pid) { + for (p = proc; p < procNPROC; p++) + if (p->p_pptr == u.u_procp) { f++; - if(p->p_stat == SZOMB) { + if (p->p_stat == SZOMB) { u.u_r.r_val1 = p->p_pid; u.u_r.r_val2 = ((struct xproc *)p)->xp_xstat; ((struct xproc *)p)->xp_xstat = 0; @@ -499,27 +614,38 @@ loop: p->p_stat = NULL; p->p_pid = 0; p->p_ppid = 0; + p->p_pptr = 0; p->p_sig = 0; + p->p_siga0 = 0; + p->p_siga1 = 0; p->p_pgrp = 0; p->p_flag = 0; p->p_wchan = 0; + p->p_cursig = 0; return; } - if(p->p_stat == SSTOP) { - if((p->p_flag&SWTED) == 0) { - p->p_flag |= SWTED; - u.u_r.r_val1 = p->p_pid; - u.u_r.r_val2 = (fsig(p)<<8) | 0177; - return; - } - continue; + if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 && + (p->p_flag&STRC || options&WUNTRACED)) { + p->p_flag |= SWTED; + u.u_r.r_val1 = p->p_pid; + u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED; + return; } } - if(f) { - sleep((caddr_t)u.u_procp, PWAIT); - goto loop; + if (f==0) { + u.u_error = ECHILD; + return; + } + if (options&WNOHANG) { + u.u_r.r_val1 = 0; + return; } - u.u_error = ECHILD; + if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { + u.u_eosys = RESTARTSYS; + return; + } + sleep((caddr_t)u.u_procp, PWAIT); + goto loop; } /* @@ -544,7 +670,7 @@ fork1(isvfork) a = 0; p2 = NULL; - for(p1 = &proc[0]; p1 < &proc[NPROC]; p1++) { + for (p1 = proc; p1 < procNPROC; p1++) { if (p1->p_stat==NULL && p2==NULL) p2 = p1; else { @@ -558,7 +684,9 @@ fork1(isvfork) * not su and too many procs owned; or * not su and would take last slot. */ - if (p2==NULL || (u.u_uid!=0 && (p2==&proc[NPROC-1] || a>MAXUPRC))) { + if (p2==NULL) + tablefull("proc"); + if (p2==NULL || (u.u_uid!=0 && (p2==procNPROC-1 || a>MAXUPRC))) { u.u_error = EAGAIN; if (!isvfork) { (void) vsexpand(0, &u.u_cdmap, 1); @@ -567,7 +695,7 @@ fork1(isvfork) goto out; } p1 = u.u_procp; - if(newproc(isvfork)) { + if (newproc(isvfork)) { u.u_r.r_val1 = p1->p_pid; u.u_r.r_val2 = 1; /* child */ u.u_start = time; @@ -602,6 +730,10 @@ sbreak() if (n < 0) n = 0; d = clrnd(n - u.u_dsize); + if (ctob(u.u_dsize+d) > u.u_limit[LIM_DATA]) { + u.u_error = ENOMEM; + return; + } if (chksize(u.u_tsize, u.u_dsize+d, u.u_ssize)) return; if (swpexpand(u.u_dsize+d, u.u_ssize, &u.u_dmap, &u.u_smap)==0)