1 /*- 2 * Copyright (c) 1982, 1986, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.proprietary.c% 6 * 7 * @(#)sys_process.c 8.1 (Berkeley) 06/10/93 8 */ 9 10 #define IPCREG 11 #include <sys/param.h> 12 #include <sys/proc.h> 13 #include <sys/vnode.h> 14 #include <sys/buf.h> 15 #include <sys/ptrace.h> 16 17 #include <machine/reg.h> 18 #include <machine/psl.h> 19 #include <vm/vm.h> 20 #include <vm/vm_page.h> 21 22 #include <sys/user.h> 23 24 /* 25 * Priority for tracing 26 */ 27 #define IPCPRI PZERO 28 29 /* 30 * Tracing variables. 31 * Used to pass trace command from 32 * parent to child being traced. 33 * This data base cannot be 34 * shared and is locked 35 * per user. 36 */ 37 struct { 38 int ip_lock; 39 int ip_req; 40 caddr_t ip_addr; 41 int ip_data; 42 } ipc; 43 44 /* 45 * Process debugging system call. 46 */ 47 struct ptrace_args { 48 int req; 49 pid_t pid; 50 caddr_t addr; 51 int data; 52 }; 53 ptrace(curp, uap, retval) 54 struct proc *curp; 55 register struct ptrace_args *uap; 56 int *retval; 57 { 58 register struct proc *p; 59 int error; 60 61 if (uap->req <= 0) { 62 curp->p_flag |= STRC; 63 return (0); 64 } 65 p = pfind(uap->pid); 66 if (p == 0) 67 return (ESRCH); 68 if (uap->req == PT_ATTACH) { 69 /* 70 * Must be root if the process has used set user or group 71 * privileges or does not belong to the real user. Must 72 * not be already traced. Can't attach to ourselves. 73 */ 74 if ((p->p_flag & SUGID || 75 p->p_cred->p_ruid != curp->p_cred->p_ruid) && 76 (error = suser(p->p_ucred, &p->p_acflag)) != 0) 77 return (error); 78 if (p->p_flag & STRC) 79 return (EALREADY); /* ??? */ 80 if (p->p_pid == curp->p_pid) 81 return (EINVAL); 82 /* 83 * It would be nice if the tracing relationship was separate 84 * from the parent relationship but that would require 85 * another set of links in the proc struct or for "wait" 86 * to scan the entire proc table. To make life easier, 87 * we just re-parent the process we're trying to trace. 88 * The old parent is remembered so we can put things back 89 * on a "detach". 90 */ 91 p->p_flag |= STRC; 92 p->p_oppid = p->p_pptr->p_pid; 93 proc_reparent(p, curp); 94 psignal(p, SIGSTOP); 95 return (0); 96 } 97 if (p->p_stat != SSTOP || p->p_pptr != curp || !(p->p_flag & STRC)) 98 return (ESRCH); 99 while (ipc.ip_lock) 100 sleep((caddr_t)&ipc, IPCPRI); 101 ipc.ip_lock = p->p_pid; 102 ipc.ip_data = uap->data; 103 ipc.ip_addr = uap->addr; 104 ipc.ip_req = uap->req; 105 p->p_flag &= ~SWTED; 106 while (ipc.ip_req > 0) { 107 if (p->p_stat==SSTOP) 108 setrun(p); 109 sleep((caddr_t)&ipc, IPCPRI); 110 } 111 *retval = ipc.ip_data; 112 ipc.ip_lock = 0; 113 wakeup((caddr_t)&ipc); 114 if (ipc.ip_req < 0) 115 return (EIO); 116 return (0); 117 } 118 119 #define PHYSOFF(p, o) ((caddr_t)(p) + (o)) 120 #if defined(hp300) || defined(luna68k) 121 #define PHYSALIGNED(a) (((int)(a) & (sizeof(short) - 1)) == 0) 122 #else 123 #define PHYSALIGNED(a) (((int)(a) & (sizeof(int) - 1)) == 0) 124 #endif 125 126 #if defined(i386) 127 #undef PC 128 #undef SP 129 #undef PS 130 #undef R0 131 #undef R1 132 133 #define PC tEIP 134 #define SP tESP 135 #define PS tEFLAGS 136 #define R0 tEDX 137 #define R1 tECX 138 #endif 139 140 /* 141 * Transmit a tracing request from the parent to the child process 142 * being debugged. This code runs in the context of the child process 143 * to fulfill the command requested by the parent. 144 */ 145 procxmt(p) 146 register struct proc *p; 147 { 148 register int i, *poff, *regs; 149 extern char kstack[]; 150 151 if (ipc.ip_lock != p->p_pid) 152 return (0); 153 p->p_slptime = 0; 154 regs = p->p_md.md_regs; 155 p->p_addr->u_kproc.kp_proc.p_md.md_regs = regs; /* u.u_ar0 */ 156 i = ipc.ip_req; 157 ipc.ip_req = 0; 158 switch (i) { 159 160 case PT_READ_I: /* read the child's text space */ 161 if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 162 goto error; 163 ipc.ip_data = fuiword((caddr_t)ipc.ip_addr); 164 break; 165 166 case PT_READ_D: /* read the child's data space */ 167 if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ)) 168 goto error; 169 ipc.ip_data = fuword((caddr_t)ipc.ip_addr); 170 break; 171 172 case PT_READ_U: /* read the child's u. */ 173 i = (int)ipc.ip_addr; 174 if ((u_int) i > ctob(UPAGES)-sizeof(int) || !PHYSALIGNED(i)) 175 goto error; 176 ipc.ip_data = *(int *)PHYSOFF(p->p_addr, i); 177 break; 178 179 case PT_WRITE_I: /* write the child's text space */ 180 if ((i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data)) < 0) { 181 vm_offset_t sa, ea; 182 int rv; 183 184 sa = trunc_page((vm_offset_t)ipc.ip_addr); 185 ea = round_page((vm_offset_t)ipc.ip_addr+sizeof(int)); 186 rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea, 187 VM_PROT_DEFAULT, FALSE); 188 if (rv == KERN_SUCCESS) { 189 i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data); 190 (void) vm_map_protect(&p->p_vmspace->vm_map, 191 sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, 192 FALSE); 193 } 194 } 195 if (i < 0) 196 goto error; 197 break; 198 199 case PT_WRITE_D: /* write the child's data space */ 200 if (suword((caddr_t)ipc.ip_addr, 0) < 0) 201 goto error; 202 (void) suword((caddr_t)ipc.ip_addr, ipc.ip_data); 203 break; 204 205 case PT_WRITE_U: /* write the child's u. */ 206 i = (int)ipc.ip_addr; 207 #ifdef mips 208 poff = (int *)PHYSOFF(p->p_addr, i); 209 #else 210 poff = (int *)PHYSOFF(kstack, i); 211 #endif 212 for (i=0; i<NIPCREG; i++) 213 if (poff == ®s[ipcreg[i]]) 214 goto ok; 215 #if defined(hp300) || defined(luna68k) 216 /* 217 * In the new frame layout, PS/PC are skewed by 2 bytes. 218 */ 219 regs = (int *)((short *)regs + 1); 220 if (poff == ®s[PC]) 221 goto ok; 222 #endif 223 if (poff == ®s[PS]) { 224 ipc.ip_data |= PSL_USERSET; 225 ipc.ip_data &= ~PSL_USERCLR; 226 #ifdef PSL_CM_CLR 227 if (ipc.ip_data & PSL_CM) 228 ipc.ip_data &= ~PSL_CM_CLR; 229 #endif 230 goto ok; 231 } 232 #if defined(hp300) || defined(luna68k) 233 #ifdef FPCOPROC 234 if (poff >= (int *)&((struct user *)kstack)->u_pcb.pcb_fpregs.fpf_regs && 235 poff <= (int *)&((struct user *)kstack)->u_pcb.pcb_fpregs.fpf_fpiar) 236 goto ok; 237 #endif 238 #endif 239 goto error; 240 241 ok: 242 *poff = ipc.ip_data; 243 break; 244 245 case PT_STEP: /* single step the child */ 246 case PT_CONTINUE: /* continue the child */ 247 regs = (int *)((short *)regs + 1); 248 if ((unsigned)ipc.ip_data >= NSIG) 249 goto error; 250 if ((int)ipc.ip_addr != 1) 251 regs[PC] = (int)ipc.ip_addr; 252 p->p_xstat = ipc.ip_data; /* see issig */ 253 #ifdef PSL_T 254 /* need something more machine independent here... */ 255 if (i == PT_STEP) 256 regs[PS] |= PSL_T; 257 #endif 258 wakeup((caddr_t)&ipc); 259 return (1); 260 261 case PT_KILL: /* kill the child process */ 262 wakeup((caddr_t)&ipc); 263 exit1(p, (int)p->p_xstat); 264 265 case PT_DETACH: /* stop tracing the child */ 266 regs = (int *)((short *)regs + 1); 267 if ((unsigned)ipc.ip_data >= NSIG) 268 goto error; 269 if ((int)ipc.ip_addr != 1) 270 regs[PC] = (int)ipc.ip_addr; 271 p->p_xstat = ipc.ip_data; /* see issig */ 272 p->p_flag &= ~STRC; 273 if (p->p_oppid != p->p_pptr->p_pid) { 274 register struct proc *pp = pfind(p->p_oppid); 275 276 if (pp) 277 proc_reparent(p, pp); 278 } 279 p->p_oppid = 0; 280 wakeup((caddr_t)&ipc); 281 return (1); 282 283 default: 284 error: 285 ipc.ip_req = -1; 286 } 287 wakeup((caddr_t)&ipc); 288 return (0); 289 } 290