Bell 32V development
authorTom London <tbl@research.uucp>
Mon, 5 Feb 1979 00:55:11 +0000 (19:55 -0500)
committerTom London <tbl@research.uucp>
Mon, 5 Feb 1979 00:55:11 +0000 (19:55 -0500)
Work on file usr/src/slowsys/sys/sig.c

Co-Authored-By: John Reiser <jfr@research.uucp>
Synthesized-from: 32v

usr/src/slowsys/sys/sig.c [new file with mode: 0644]

diff --git a/usr/src/slowsys/sys/sig.c b/usr/src/slowsys/sys/sig.c
new file mode 100644 (file)
index 0000000..3306248
--- /dev/null
@@ -0,0 +1,415 @@
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/proc.h"
+#include "../h/inode.h"
+#include "../h/reg.h"
+#include "../h/text.h"
+#include "../h/seg.h"
+#include "../h/mtpr.h"
+#include "../h/page.h"
+#include "../h/psl.h"
+
+/*
+ * Priority for tracing
+ */
+#define        IPCPRI  PZERO
+
+/*
+ * Tracing variables.
+ * Used to pass trace command from
+ * parent to child being traced.
+ * This data base cannot be
+ * shared and is locked
+ * per user.
+ */
+struct
+{
+       int     ip_lock;
+       int     ip_req;
+       int     *ip_addr;
+       int     ip_data;
+} ipc;
+
+/*
+ * Send the specified signal to
+ * all processes with 'pgrp' as
+ * process group.
+ * Called by tty.c for quits and
+ * interrupts.
+ */
+signal(pgrp, sig)
+register pgrp;
+{
+       register struct proc *p;
+
+       if(pgrp == 0)
+               return;
+       for(p = &proc[0]; p < &proc[NPROC]; p++)
+               if(p->p_pgrp == pgrp)
+                       psignal(p, sig);
+}
+
+/*
+ * Send the specified signal to
+ * the specified process.
+ */
+psignal(p, sig)
+register struct proc *p;
+register unsigned sig;
+{
+
+       if((unsigned)sig >= NSIG)
+               return;
+       if(sig)
+               p->p_sig |= 1<<(sig-1);
+       if(p->p_pri > PUSER)
+               p->p_pri = PUSER;
+       if(p->p_stat == SSLEEP && p->p_pri > PZERO)
+               setrun(p);
+}
+
+/*
+ * Returns true if the current
+ * process has a signal to process.
+ * This is asked at least once
+ * each time a process enters the
+ * system.
+ * A signal does not do anything
+ * directly to a process; it sets
+ * a flag that asks the process to
+ * do something to itself.
+ */
+issig()
+{
+       register n;
+       register struct proc *p;
+
+       p = u.u_procp;
+       while(p->p_sig) {
+               n = fsig(p);
+               if((u.u_signal[n]&1) == 0 || (p->p_flag&STRC))
+                       return(n);
+               p->p_sig &= ~(1<<(n-1));
+       }
+       return(0);
+}
+
+/*
+ * Enter the tracing STOP state.
+ * In this state, the parent is
+ * informed and the process is able to
+ * receive commands from the parent.
+ */
+stop()
+{
+       register struct proc *pp, *cp;
+
+loop:
+       cp = u.u_procp;
+       if(cp->p_ppid != 1)
+       for (pp = &proc[0]; pp < &proc[NPROC]; pp++)
+               if (pp->p_pid == cp->p_ppid) {
+                       wakeup((caddr_t)pp);
+                       cp->p_stat = SSTOP;
+                       swtch();
+                       if ((cp->p_flag&STRC)==0 || procxmt())
+                               return;
+                       goto loop;
+               }
+       exit(fsig(u.u_procp));
+}
+
+/*
+ * Perform the action specified by
+ * the current signal.
+ * The usual sequence is:
+ *     if(issig())
+ *             psig();
+ */
+psig()
+{
+       register n, p;
+       register struct proc *rp;
+
+       rp = u.u_procp;
+       if (rp->p_flag&STRC)
+               stop();
+       n = fsig(rp);
+       if (n==0)
+               return;
+       rp->p_sig &= ~(1<<(n-1));
+       if((p=u.u_signal[n]) != 0) {
+               u.u_error = 0;
+               if(n != SIGINS && n != SIGTRC)
+                       u.u_signal[n] = 0;
+               sendsig(p, n);
+               return;
+       }
+       switch(n) {
+
+       case SIGQUIT:
+       case SIGINS:
+       case SIGTRC:
+       case SIGIOT:
+       case SIGEMT:
+       case SIGFPT:
+       case SIGBUS:
+       case SIGSEG:
+       case SIGSYS:
+               if(core())
+                       n += 0200;
+       }
+       exit(n);
+}
+
+/*
+ * find the signal in bit-position
+ * representation in p_sig.
+ */
+fsig(p)
+struct proc *p;
+{
+       register n, i;
+
+       n = p->p_sig;
+       for(i=1; i<NSIG; i++) {
+               if(n & 1)
+                       return(i);
+               n >>= 1;
+       }
+       return(0);
+}
+
+/*
+ * Create a core image on the file "core"
+ * If you are looking for protection glitches,
+ * there are probably a wealth of them here
+ * when this occurs to a suid command.
+ *
+ * It writes USIZE block of the
+ * user.h area followed by the entire
+ * data+stack segments.
+ */
+core()
+{
+       register struct inode *ip;
+       register s;
+       extern schar();
+
+       u.u_error = 0;
+       u.u_dirp = "core";
+       ip = namei(schar, 1);
+       if(ip == NULL) {
+               if(u.u_error)
+                       return(0);
+               ip = maknode(0666);
+               if (ip==NULL)
+                       return(0);
+       }
+       if(!access(ip, IWRITE) &&
+          (ip->i_mode&IFMT) == IFREG &&
+          u.u_uid == u.u_ruid) {
+               itrunc(ip);
+               u.u_offset = 0;
+               u.u_base = (caddr_t)&u;
+               u.u_count = ctob(USIZE);
+               u.u_segflg = 1;
+               writei(ip);
+               s = u.u_procp->p_size - USIZE;
+               estabur((unsigned)0, s, (unsigned)0, 0, RO);
+               u.u_base = 0;
+               u.u_count = ctob(s);
+               u.u_segflg = 0;
+               writei(ip);
+       }
+       iput(ip);
+       return(u.u_error==0);
+}
+
+/*
+ * grow the stack to include the SP
+ * true return if successful.
+ */
+
+grow(sp)
+unsigned sp;
+{
+       register si, i;
+       register struct proc *p;
+       register a;
+
+       if(sp >= USRSTACK-ctob(u.u_ssize))
+               return(0);
+       si = btoc((USRSTACK-sp)) - u.u_ssize + SINCR;
+       if(si <= 0)
+               return(0);
+       if(estabur(u.u_tsize, u.u_dsize, u.u_ssize+si, u.u_sep, RO))
+               return(0);
+       p = u.u_procp;
+       expand(p->p_size+si);
+       a = p->p_addr + p->p_size;
+       for(i=u.u_ssize; i; i--) {
+               a--;
+               copyseg(a-si, a);
+       }
+       for(i=si; i; i--)
+               clearseg(--a);
+       u.u_ssize += si;
+       return(1);
+}
+
+/*
+ * sys-trace system call.
+ */
+ptrace()
+{
+       register struct proc *p;
+       register struct a {
+               int     req;
+               int     pid;
+               int     *addr;
+               int     data;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       if (uap->req <= 0) {
+               u.u_procp->p_flag |= STRC;
+               return;
+       }
+       for (p=proc; p < &proc[NPROC]; p++) 
+               if (p->p_stat==SSTOP
+                && p->p_pid==uap->pid
+                && p->p_ppid==u.u_procp->p_pid)
+                       goto found;
+       u.u_error = ESRCH;
+       return;
+
+    found:
+       while (ipc.ip_lock)
+               sleep((caddr_t)&ipc, IPCPRI);
+       ipc.ip_lock = p->p_pid;
+       ipc.ip_data = uap->data;
+       ipc.ip_addr = uap->addr;
+       ipc.ip_req = uap->req;
+       p->p_flag &= ~SWTED;
+       setrun(p);
+       while (ipc.ip_req > 0)
+               sleep((caddr_t)&ipc, IPCPRI);
+       u.u_r.r_val1 = ipc.ip_data;
+       if (ipc.ip_req < 0)
+               u.u_error = EIO;
+       ipc.ip_lock = 0;
+       wakeup((caddr_t)&ipc);
+}
+
+int ipcreg[] = {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, AP, FP, SP, PC};
+/*
+ * Code that the child process
+ * executes to implement the command
+ * of the parent process in tracing.
+ */
+procxmt()
+{
+       register int i;
+       register *p;
+       register struct text *xp;
+
+       if (ipc.ip_lock != u.u_procp->p_pid)
+               return(0);
+       i = ipc.ip_req;
+       ipc.ip_req = 0;
+       wakeup((caddr_t)&ipc);
+       switch (i) {
+
+       /* read user I */
+       case 1:
+               if ( !useracc((caddr_t)ipc.ip_addr, 4, 1))
+                       goto error;
+               ipc.ip_data = fuiword((caddr_t)ipc.ip_addr);
+               break;
+
+       /* read user D */
+       case 2:
+               if ( !useracc((caddr_t)ipc.ip_addr, 4, 1))
+                       goto error;
+               ipc.ip_data = fuword((caddr_t)ipc.ip_addr);
+               break;
+
+       /* read u */
+       case 3:
+               i = (int)ipc.ip_addr;
+               if (i<0 || i >= ctob(USIZE))
+                       goto error;
+               ipc.ip_data = ((physadr)&u)->r[i>>2];
+               break;
+
+       /* write user I */
+       /* Must set up to allow writing */
+       case 4:
+               /*
+                * If text, must assure exclusive use
+                */
+               if (xp = u.u_procp->p_textp) {
+                       if (xp->x_count!=1 || xp->x_iptr->i_mode&ISVTX)
+                               goto error;
+                       xp->x_iptr->i_flag &= ~ITEXT;
+               }
+               estabur(u.u_tsize, u.u_dsize, u.u_ssize, u.u_sep, RW);
+               i = suiword((caddr_t)ipc.ip_addr, 0);
+               suiword((caddr_t)ipc.ip_addr, ipc.ip_data);
+               estabur(u.u_tsize, u.u_dsize, u.u_ssize, u.u_sep, RO);
+               if (i<0)
+                       goto error;
+               if (xp)
+                       xp->x_flag |= XWRIT;
+               break;
+
+       /* write user D */
+       case 5:
+               if (suword((caddr_t)ipc.ip_addr, 0) < 0)
+                       goto error;
+               suword((caddr_t)ipc.ip_addr, ipc.ip_data);
+               break;
+
+       /* write u */
+       case 6:
+               i = (int)ipc.ip_addr;
+               p = (int *)&((physadr)&u)->r[i>>2];
+               for (i=0; i<16; i++)
+                       if (p == &u.u_ar0[ipcreg[i]])
+                               goto ok;
+               if (p == &u.u_ar0[PS]) {
+                       ipc.ip_data |= 0x3c00000; /* modes == user */
+                       ipc.ip_data &=  ~0x3c20ff00; /* IS, FPD,  ... */
+                       goto ok;
+               }
+               goto error;
+
+       ok:
+               *p = ipc.ip_data;
+               break;
+
+       /* set signal and continue */
+       /*  one version causes a trace-trap */
+       case 9:
+               u.u_ar0[PS] |= PSL_T;
+       case 7:
+               if ((int)ipc.ip_addr != 1)
+                       u.u_ar0[PC] = (int)ipc.ip_addr;
+               u.u_procp->p_sig = 0;
+               if (ipc.ip_data)
+                       psignal(u.u_procp, ipc.ip_data);
+               return(1);
+
+       /* force exit */
+       case 8:
+               exit(fsig(u.u_procp));
+
+       default:
+       error:
+               ipc.ip_req = -1;
+       }
+       return(0);
+}