home *** CD-ROM | disk | FTP | other *** search
- #
- /*
- */
-
- #include "../param.h"
- #include "../systm.h"
- #include "../user.h"
- #include "../proc.h"
- #include "../inode.h"
- #include "../reg.h"
-
- /*
- * Priority for tracing
- */
- #define IPCPRI (-1)
-
- /*
- * Structure to access an array of integers.
- */
- struct
- {
- int inta[];
- };
-
- /*
- * 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 'tp' as its
- * controlling teletype.
- * Called by tty.c for quits and
- * interrupts.
- */
- signal(tp, sig)
- {
- register struct proc *p;
-
- for(p = &proc[0]; p < &proc[NPROC]; p++)
- if(p->p_ttyp == tp)
- psignal(p, sig);
- }
-
- /*
- * Send the specified signal to
- * the specified process.
- */
- psignal(p, sig)
- int *p;
- {
- register *rp;
-
- if(sig >= NSIG)
- return;
- rp = p;
- if(rp->p_sig != SIGKIL)
- rp->p_sig = sig;
- if(rp->p_stat > PUSER)
- rp->p_stat = PUSER;
- if(rp->p_stat == SWAIT)
- setrun(rp);
- }
-
- /*
- * 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;
- if(n = p->p_sig) {
- if (p->p_flag&STRC) {
- stop();
- if ((n = p->p_sig) == 0)
- return(0);
- }
- if((u.u_signal[n]&1) == 0)
- return(n);
- }
- 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(pp);
- cp->p_stat = SSTOP;
- swtch();
- if ((cp->p_flag&STRC)==0 || procxmt())
- return;
- goto loop;
- }
- exit();
- }
-
- /*
- * Perform the action specified by
- * the current signal.
- * The usual sequence is:
- * if(issig())
- * psig();
- */
- psig()
- {
- register n, p;
- register *rp;
-
- rp = u.u_procp;
- n = rp->p_sig;
- rp->p_sig = 0;
- if((p=u.u_signal[n]) != 0) {
- u.u_error = 0;
- if(n != SIGINS && n != SIGTRC)
- u.u_signal[n] = 0;
- n = u.u_ar0[R6] - 4;
- grow(n);
- suword(n+2, u.u_ar0[RPS]);
- suword(n, u.u_ar0[R7]);
- u.u_ar0[R6] = n;
- u.u_ar0[RPS] =& ~TBIT;
- u.u_ar0[R7] = p;
- return;
- }
- switch(n) {
-
- case SIGQIT:
- case SIGINS:
- case SIGTRC:
- case SIGIOT:
- case SIGEMT:
- case SIGFPT:
- case SIGBUS:
- case SIGSEG:
- case SIGSYS:
- u.u_arg[0] = n;
- if(core())
- n =+ 0200;
- }
- u.u_arg[0] = (u.u_ar0[R0]<<8) | n;
- exit();
- }
-
- /*
- * 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 s, *ip;
- 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) == 0 &&
- u.u_uid == u.u_ruid) {
- itrunc(ip);
- u.u_offset[0] = 0;
- u.u_offset[1] = 0;
- u.u_base = &u;
- u.u_count = USIZE*64;
- u.u_segflg = 1;
- writei(ip);
- s = u.u_procp->p_size - USIZE;
- estabur(0, s, 0, 0);
- u.u_base = 0;
- u.u_count = s*64;
- 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)
- char *sp;
- {
- register a, si, i;
-
- if(sp >= -u.u_ssize*64)
- return(0);
- si = ldiv(-sp, 64) - u.u_ssize + SINCR;
- if(si <= 0)
- return(0);
- if(estabur(u.u_tsize, u.u_dsize, u.u_ssize+si, u.u_sep))
- return(0);
- expand(u.u_procp->p_size+si);
- a = u.u_procp->p_addr + u.u_procp->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;
-
- if (u.u_arg[2] <= 0) {
- u.u_procp->p_flag =| STRC;
- return;
- }
- for (p=proc; p < &proc[NPROC]; p++)
- if (p->p_stat==SSTOP
- && p->p_pid==u.u_arg[0]
- && p->p_ppid==u.u_procp->p_pid)
- goto found;
- u.u_error = ESRCH;
- return;
-
- found:
- while (ipc.ip_lock)
- sleep(&ipc, IPCPRI);
- ipc.ip_lock = p->p_pid;
- ipc.ip_data = u.u_ar0[R0];
- ipc.ip_addr = u.u_arg[1] & ~01;
- ipc.ip_req = u.u_arg[2];
- p->p_flag =& ~SWTED;
- setrun(p);
- while (ipc.ip_req > 0)
- sleep(&ipc, IPCPRI);
- u.u_ar0[R0] = ipc.ip_data;
- if (ipc.ip_req < 0)
- u.u_error = EIO;
- ipc.ip_lock = 0;
- wakeup(&ipc);
- }
-
- /*
- * Code that the child process
- * executes to implement the command
- * of the parent process in tracing.
- */
- procxmt()
- {
- register int i;
- register int *p;
-
- if (ipc.ip_lock != u.u_procp->p_pid)
- return(0);
- i = ipc.ip_req;
- ipc.ip_req = 0;
- wakeup(&ipc);
- switch (i) {
-
- /* read user I */
- case 1:
- if (fuibyte(ipc.ip_addr) == -1)
- goto error;
- ipc.ip_data = fuiword(ipc.ip_addr);
- break;
-
- /* read user D */
- case 2:
- if (fubyte(ipc.ip_addr) == -1)
- goto error;
- ipc.ip_data = fuword(ipc.ip_addr);
- break;
-
- /* read u */
- case 3:
- i = ipc.ip_addr;
- if (i<0 || i >= (USIZE<<6))
- goto error;
- ipc.ip_data = u.inta[i>>1];
- break;
-
- /* write user I (for now, always an error) */
- case 4:
- if (suiword(ipc.ip_addr, 0) < 0)
- goto error;
- suiword(ipc.ip_addr, ipc.ip_data);
- break;
-
- /* write user D */
- case 5:
- if (suword(ipc.ip_addr, 0) < 0)
- goto error;
- suword(ipc.ip_addr, ipc.ip_data);
- break;
-
- /* write u */
- case 6:
- p = &u.inta[ipc.ip_addr>>1];
- if (p >= u.u_fsav && p < &u.u_fsav[25])
- goto ok;
- for (i=0; i<9; i++)
- if (p == &u.u_ar0[regloc[i]])
- goto ok;
- goto error;
- ok:
- if (p == &u.u_ar0[RPS]) {
- ipc.ip_data =| 0170000; /* assure user space */
- ipc.ip_data =& ~0340; /* priority 0 */
- }
- *p = ipc.ip_data;
- break;
-
- /* set signal and continue */
- case 7:
- u.u_procp->p_sig = ipc.ip_data;
- return(1);
-
- /* force exit */
- case 8:
- exit();
-
- default:
- error:
- ipc.ip_req = -1;
- }
- return(0);
- }
-