1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)sys_process.c 7.4 (Berkeley) 12/10/87 7 */ 8 9 #define IPCREG 10 #include "../machine/reg.h" 11 #include "../machine/psl.h" 12 #include "../machine/pte.h" 13 14 #include "param.h" 15 #include "systm.h" 16 #include "dir.h" 17 #include "user.h" 18 #include "proc.h" 19 #include "inode.h" 20 #include "text.h" 21 #include "seg.h" 22 #include "vm.h" 23 #include "buf.h" 24 #include "acct.h" 25 #include "ptrace.h" 26 27 /* 28 * Priority for tracing 29 */ 30 #define IPCPRI PZERO 31 32 /* 33 * Tracing variables. 34 * Used to pass trace command from 35 * parent to child being traced. 36 * This data base cannot be 37 * shared and is locked 38 * per user. 39 */ 40 struct { 41 int ip_lock; 42 int ip_req; 43 int *ip_addr; 44 int ip_data; 45 } ipc; 46 47 /* 48 * sys-trace system call. 49 */ 50 ptrace() 51 { 52 register struct proc *p; 53 register struct a { 54 int req; 55 int pid; 56 int *addr; 57 int data; 58 } *uap; 59 60 uap = (struct a *)u.u_ap; 61 if (uap->req <= 0) { 62 u.u_procp->p_flag |= STRC; 63 return; 64 } 65 p = pfind(uap->pid); 66 if (p == 0 || p->p_stat != SSTOP || p->p_ppid != u.u_procp->p_pid || 67 !(p->p_flag & STRC)) { 68 u.u_error = ESRCH; 69 return; 70 } 71 while (ipc.ip_lock) 72 sleep((caddr_t)&ipc, IPCPRI); 73 ipc.ip_lock = p->p_pid; 74 ipc.ip_data = uap->data; 75 ipc.ip_addr = uap->addr; 76 ipc.ip_req = uap->req; 77 p->p_flag &= ~SWTED; 78 while (ipc.ip_req > 0) { 79 if (p->p_stat==SSTOP) 80 setrun(p); 81 sleep((caddr_t)&ipc, IPCPRI); 82 } 83 u.u_r.r_val1 = ipc.ip_data; 84 if (ipc.ip_req < 0) 85 u.u_error = EIO; 86 ipc.ip_lock = 0; 87 wakeup((caddr_t)&ipc); 88 } 89 90 #define PHYSOFF(p, o) \ 91 ((physadr)(p)+((o)/sizeof(((physadr)0)->r[0]))) 92 93 /* 94 * Code that the child process 95 * executes to implement the command 96 * of the parent process in tracing. 97 */ 98 procxmt() 99 { 100 register int i; 101 register *p; 102 register struct text *xp; 103 104 if (ipc.ip_lock != u.u_procp->p_pid) 105 return (0); 106 u.u_procp->p_slptime = 0; 107 i = ipc.ip_req; 108 ipc.ip_req = 0; 109 switch (i) { 110 111 case PT_READ_I: /* read the child's text space */ 112 if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 113 goto error; 114 ipc.ip_data = fuiword((caddr_t)ipc.ip_addr); 115 break; 116 117 case PT_READ_D: /* read the child's data space */ 118 if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 119 goto error; 120 ipc.ip_data = fuword((caddr_t)ipc.ip_addr); 121 break; 122 123 case PT_READ_U: /* read the child's u. */ 124 i = (int)ipc.ip_addr; 125 if (i<0 || i >= ctob(UPAGES)) 126 goto error; 127 ipc.ip_data = *(int *)PHYSOFF(&u, i); 128 break; 129 130 case PT_WRITE_I: /* write the child's text space */ 131 /* 132 * If text, must assure exclusive use 133 */ 134 if (xp = u.u_procp->p_textp) { 135 if (xp->x_count!=1 || xp->x_iptr->i_mode&ISVTX) 136 goto error; 137 xp->x_flag |= XTRC; 138 } 139 i = -1; 140 if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) { 141 if (chgprot((caddr_t)ipc.ip_addr, RW) && 142 chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RW)) 143 i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data); 144 (void) chgprot((caddr_t)ipc.ip_addr, RO); 145 (void) chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RO); 146 } 147 if (i < 0) 148 goto error; 149 #if defined(tahoe) 150 /* make sure the old value is not in cache */ 151 ckeyrelease(u.u_procp->p_ckey); 152 u.u_procp->p_ckey = getcodekey(); 153 #endif 154 if (xp) { 155 xp->x_flag |= XWRIT; 156 #if defined(tahoe) 157 xp->x_ckey = u.u_procp->p_ckey; 158 #endif 159 } 160 break; 161 162 case PT_WRITE_D: /* write the child's data space */ 163 if (suword((caddr_t)ipc.ip_addr, 0) < 0) 164 goto error; 165 (void) suword((caddr_t)ipc.ip_addr, ipc.ip_data); 166 break; 167 168 case PT_WRITE_U: /* write the child's u. */ 169 i = (int)ipc.ip_addr; 170 p = (int *)PHYSOFF(&u, i); 171 for (i=0; i<NIPCREG; i++) 172 if (p == &u.u_ar0[ipcreg[i]]) 173 goto ok; 174 if (p == &u.u_ar0[PS]) { 175 ipc.ip_data |= PSL_USERSET; 176 ipc.ip_data &= ~PSL_USERCLR; 177 #ifdef PSL_CM_CLR 178 if (ipc.ip_data & PSL_CM) 179 ipc.ip_data &= ~PSL_CM_CLR; 180 #endif 181 goto ok; 182 } 183 goto error; 184 185 ok: 186 *p = ipc.ip_data; 187 break; 188 189 case PT_STEP: /* single step the child */ 190 case PT_CONTINUE: /* continue the child */ 191 if ((int)ipc.ip_addr != 1) 192 u.u_ar0[PC] = (int)ipc.ip_addr; 193 if ((unsigned)ipc.ip_data > NSIG) 194 goto error; 195 u.u_procp->p_cursig = ipc.ip_data; /* see issig */ 196 if (i == PT_STEP) 197 u.u_ar0[PS] |= PSL_T; 198 wakeup((caddr_t)&ipc); 199 return (1); 200 201 case PT_KILL: /* kill the child process */ 202 wakeup((caddr_t)&ipc); 203 exit(u.u_procp->p_cursig); 204 205 default: 206 error: 207 ipc.ip_req = -1; 208 } 209 wakeup((caddr_t)&ipc); 210 return (0); 211 } 212