|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
33: * from: @(#)sys_process.c 7.22 (Berkeley) 5/11/91
1.1.1.5 ! root 34: * sys_process.c,v 1.8 1993/07/13 22:13:33 cgd Exp
1.1 root 35: */
36:
37: #define IPCREG
38: #include "param.h"
1.1.1.5 ! root 39: #include "systm.h"
1.1 root 40: #include "proc.h"
41: #include "vnode.h"
42: #include "buf.h"
43: #include "ptrace.h"
44:
45: #include "machine/reg.h"
46: #include "machine/psl.h"
47: #include "vm/vm.h"
48: #include "vm/vm_page.h"
49:
50: #include "user.h"
51:
52: /*
1.1.1.3 root 53: * NOTES.
54: *
55: * The following ptrace calls have been defined in addition to
56: * the standard ones found in original <sys/ptrace.h>:
57: *
58: * PT_ATTACH - attach to running process
59: * PT_DETACH - detach from running process
60: * PT_SYSCALL - trace system calls
61: * PT_GETREG - get register file
62: * PT_SETREG - set register file
63: * PT_BREAD_[IDU] - block read from process (not yet implemented)
64: * PT_BWRITE_[IDU] - block write " "
65: * PT_INHERIT - make forked processes inherit trace flags
66: *
67: */
68:
69: /* Define to prevent extraneous clutter in source */
70: #ifndef SSTRC
71: #define SSTRC 0
72: #endif
73: #ifndef SFTRC
74: #define SFTRC 0
75: #endif
76:
77: struct {
78: int flag;
79: #define IPC_BUSY 1
80: #define IPC_WANT 2
81: #define IPC_DONE 4
82: int req; /* copy of ptrace request */
83: int *addr; /* copy of ptrace address */
84: int data; /* copy of ptrace data */
85: int error; /* errno from `procxmt' */
86: int regs[NIPCREG]; /* PT_[GS]ETREG */
87: caddr_t buf; /* PT_BREAD/WRITE */
88: int buflen; /* " */
89: } ipc;
90:
91: /*
1.1 root 92: * Process debugging system call.
93: */
1.1.1.5 ! root 94:
! 95: struct ptrace_args {
! 96: int req;
! 97: int pid;
! 98: int *addr;
! 99: int data;
! 100: };
! 101:
! 102: int
1.1 root 103: ptrace(curp, uap, retval)
104: struct proc *curp;
1.1.1.5 ! root 105: register struct ptrace_args *uap;
1.1 root 106: int *retval;
107: {
1.1.1.3 root 108: struct proc *p;
1.1.1.5 ! root 109: int error = 0;
1.1 root 110:
1.1.1.3 root 111: *retval = 0;
112: if (uap->req == PT_TRACE_ME) {
113: curp->p_flag |= STRC;
114: /*p->p_tptr = p->p_pptr; * What shall we do here ? */
115: return 0;
116: }
117: if ((p = pfind(uap->pid)) == NULL) {
118: return ESRCH;
119: }
120:
121: #ifdef notyet
122: if (uap->req != PT_ATTACH && (
123: (p->p_flag & STRC) == 0 ||
124: (p->p_tptr && curp != p->p_tptr) ||
125: (!p->p_tptr && curp != p->p_pptr)))
126:
127: return ESRCH;
128: #endif
129:
130:
131: #ifdef PT_ATTACH
132: switch (uap->req) {
133: case PT_ATTACH:
134: if (curp->p_ucred->cr_uid != 0 && (
135: curp->p_ucred->cr_uid != p->p_ucred->cr_uid ||
136: curp->p_ucred->cr_uid != p->p_cred->p_svuid))
137: return EACCES;
138:
139: p->p_tptr = curp;
140: p->p_flag |= STRC;
141: psignal(p, SIGTRAP);
142: return 0;
143:
144: case PT_DETACH:
145: if ((unsigned)uap->data >= NSIG)
146: return EINVAL;
147: p->p_flag &= ~(STRC|SSTRC|SFTRC);
148: p->p_tptr = NULL;
149: psignal(p->p_pptr, SIGCHLD);
150: wakeup((caddr_t)p->p_pptr);
151: s = splhigh();
152: if (p->p_stat == SSTOP) {
153: p->p_xstat = uap->data;
154: setrun(p);
155: } else if (uap->data) {
156: psignal(p, uap->data);
157: }
158: splx(s);
159: return 0;
160:
161: #ifdef PT_INHERIT
162: case PT_INHERIT:
163: if ((p->p_flag & STRC) == 0)
164: return ESRCH;
165: p->p_flag |= SFTRC;
166: return 0;
167: #endif
168:
169: default:
170: break;
171: }
172: #endif
173:
174: /* Other ptrace calls require target process to be in stopped state */
175: if ((p->p_flag & STRC) == 0 || p->p_stat != SSTOP) {
176: return ESRCH;
177: }
178:
179: /* Acquire the ipc structure */
180: while (ipc.flag & IPC_BUSY) {
181: ipc.flag |= IPC_WANT;
182: error = tsleep((caddr_t)&ipc, PWAIT|PCATCH, "ipc", 0);
183: if (error)
184: goto out;
185: }
186:
187: /* Got it, fill it */
188: ipc.flag = IPC_BUSY;
189: ipc.error = 0;
190: ipc.req = uap->req;
191: ipc.addr = uap->addr;
192: ipc.data = uap->data;
193:
194: #ifdef PT_GETREGS
195: switch (uap->req) {
196: case PT_SETREGS:
197: error = copyin((char *)ipc.addr, (char *)ipc.regs, sizeof(ipc.regs));
198: if (error)
199: goto out;
200: break;
201:
202: #ifdef notyet /* requires change in number of args to ptrace syscall */
203: case PT_BWRITE_I:
204: case PT_BWRITE_D:
205: ipc.buflen = uap->data;
206: ipc.buf = kmem_alloc_wait(kernelmap, uap->data);
207: error = copyin((char *)ipc.addr, (char *)ipc.buf, ipc.buflen);
208: if (error) {
209: kmem_free_wakeup(kernelmap, ipc.buf, ipc.buflen);
210: goto out;
211: }
212: #endif
213: default:
214: break;
215: }
216: #endif
217:
218: setrun(p);
219: while ((ipc.flag & IPC_DONE) == 0) {
220: error = tsleep((caddr_t)&ipc, PWAIT|PCATCH, "ipc", 0);
221: if (error)
222: goto out;
223: }
224:
225: *retval = ipc.data;
226: if (error = ipc.error)
227: goto out;
228:
229: #ifdef PT_GETREGS
230: switch (uap->req) {
231: case PT_GETREGS:
232: error = copyout((char *)ipc.regs, (char *)ipc.addr, sizeof(ipc.regs));
233: break;
234:
235: case PT_BREAD_I:
236: case PT_BREAD_D:
237: /* Not yet */
238: default:
239: break;
240: }
241: #endif
242:
243: out:
244: /* Release ipc structure */
245: ipc.flag &= ~IPC_BUSY;
246: if (ipc.flag & IPC_WANT) {
247: ipc.flag &= ~IPC_WANT;
248: wakeup((caddr_t)&ipc);
249: }
250: return error;
1.1 root 251: }
252:
1.1.1.5 ! root 253: int
1.1 root 254: procxmt(p)
255: register struct proc *p;
256: {
1.1.1.5 ! root 257: int rv = 0;
1.1 root 258:
1.1.1.3 root 259: /* Are we still being traced? */
260: if ((p->p_flag & STRC) == 0)
261: return 1;
262:
263: p->p_addr->u_kproc.kp_proc = *p;
264: fill_eproc(p, &p->p_addr->u_kproc.kp_eproc);
265:
266: switch (ipc.req) {
267: case PT_READ_I:
268: case PT_READ_D:
1.1.1.5 ! root 269: if (!useracc((caddr_t)ipc.addr, sizeof(ipc.data), B_READ)) {
1.1.1.4 root 270: ipc.error = EFAULT;
271: break;
272: }
1.1.1.3 root 273: ipc.error = copyin((char *)ipc.addr, (char *)&ipc.data, sizeof(ipc.data));
274: break;
275:
276: case PT_READ_U:
277: if ((u_int)ipc.addr > UPAGES * NBPG - sizeof(int)) {
278: ipc.error = EFAULT;
279: break;
280: }
281: ipc.data = *(int *)((u_int)p->p_addr + (u_int)ipc.addr);
282: break;
283:
284: case PT_WRITE_I:
1.1.1.4 root 285: case PT_WRITE_D: { /* 04 Sep 92*/
286: vm_prot_t prot; /* current protection of region */
287: int cow; /* ensure copy-on-write happens */
288:
1.1.1.5 ! root 289: if (cow = (useracc((caddr_t)ipc.addr, sizeof(ipc.data), B_WRITE)
! 290: == 0)) {
1.1.1.4 root 291: vm_offset_t addr = (vm_offset_t)ipc.addr;
292: vm_size_t size;
293: vm_prot_t max_prot;
294: vm_inherit_t inh;
295: boolean_t shared;
296: vm_object_t object;
297: vm_offset_t objoff;
298:
299: /*
300: * XXX - the useracc check is stronger than the vm
301: * checks because the user page tables are in the map.
302: */
1.1.1.5 ! root 303: if (!useracc((caddr_t)ipc.addr, sizeof(ipc.data), B_READ) ||
1.1.1.4 root 304: vm_region(&p->p_vmspace->vm_map, &addr, &size,
305: &prot, &max_prot, &inh, &shared,
306: &object, &objoff) != KERN_SUCCESS ||
307: vm_protect(&p->p_vmspace->vm_map, ipc.addr,
308: sizeof(ipc.data), FALSE,
309: prot|VM_PROT_WRITE) != KERN_SUCCESS ||
310: vm_fault(&p->p_vmspace->vm_map,trunc_page(ipc.addr),
311: VM_PROT_WRITE, FALSE) != KERN_SUCCESS) {
312:
313: ipc.error = EFAULT;
314: break;
315: }
316: }
317: ipc.error = copyout((char *)&ipc.data,
318: (char *)ipc.addr, sizeof(ipc.data));
319: if (cow)
320: if (vm_protect(&p->p_vmspace->vm_map, ipc.addr,
321: sizeof(ipc.data), FALSE,
322: prot) != KERN_SUCCESS)
323: printf("ptrace: oops\n");
1.1.1.3 root 324: break;
1.1.1.4 root 325: }
1.1.1.3 root 326:
327: case PT_WRITE_U:
328: if ((u_int)ipc.addr > UPAGES * NBPG - sizeof(int)) {
329: ipc.error = EFAULT;
330: break;
331: }
332: *(int *)((u_int)p->p_addr + (u_int)ipc.addr) = ipc.data;
333: break;
334:
335: case PT_CONTINUE:
336: if (ipc.addr != (int *)1) {
337: #ifdef i386
338: p->p_regs[(curpcb->pcb_flags&FM_TRAP)?tEIP:sEIP] = (int)ipc.addr;
339: #endif
340: }
341: p->p_flag &= ~SSTRC; /* Only set by PT_SYSCALL */
342: if ((unsigned)ipc.data >= NSIG) {
343: ipc.error = EINVAL;
344: } else {
345: p->p_xstat = ipc.data;
346: rv = 1;
347: }
348: break;
349:
350: case PT_KILL:
351: p->p_flag &= ~SSTRC; /* Only set by PT_SYSCALL */
352: rv = 2;
353: break;
354:
355: case PT_STEP:
356: #ifdef i386
357: if (ipc.addr != (int *)1) {
358: p->p_regs[(curpcb->pcb_flags&FM_TRAP)?tEIP:sEIP] = (int)ipc.addr;
359: }
360: p->p_regs[(curpcb->pcb_flags&FM_TRAP)?tEFLAGS:sEFLAGS] |= PSL_T;
361: #endif
362: p->p_flag &= ~SSTRC; /* Only set by PT_SYSCALL */
363: p->p_xstat = 0;
364: rv = 1;
365: break;
366:
367: #ifdef PT_SYSCALL
368: case PT_SYSCALL:
369: if (ipc.addr != (int *)1) {
370: #ifdef i386
371: p->p_regs[(curpcb->pcb_flags&FM_TRAP)?tEIP:sEIP] = (int)ipc.addr;
372: #endif
373: }
374: p->p_flag |= SSTRC;
375: p->p_xstat = 0;
376: rv = 1;
377: break;
378: #endif
379: #ifdef PT_GETREGS
380: case PT_GETREGS:
381: #ifdef i386
382: xreg = (curpcb->pcb_flags&FM_TRAP)?ipcreg:sipcreg;
383: #endif
384:
385: for (i = 0; i < NIPCREG; i++)
386: ipc.regs[i] = p->p_regs[xreg[i]];
387: break;
388:
389: case PT_SETREGS:
390: #ifdef i386
391: xreg = (curpcb->pcb_flags&FM_TRAP)?ipcreg:sipcreg;
392: #endif
393:
394: for (i = 0; i < NIPCREG; i++)
395: p->p_regs[xreg[i]] = ipc.regs[i];
396: break;
397: #endif
398:
399: #ifdef PT_DUMP
400: case PT_DUMP:
401: /* Should be able to specify core file name */
402: ipc.error = coredump(p);
403: break;
404: #endif
405:
406: default:
407: ipc.error = EINVAL;
408: }
409: ipc.flag |= IPC_DONE;
410: wakeup((caddr_t)&ipc);
411:
412: if (rv == 2)
1.1.1.5 ! root 413: kexit(p, 0); /*???*/
1.1.1.3 root 414:
415: return rv;
1.1 root 416: }
417:
418: /*
419: * Enable process profiling system call.
420: */
1.1.1.5 ! root 421:
! 422: struct profil_args {
! 423: short *bufbase; /* base of data buffer */
! 424: unsigned bufsize; /* size of data buffer */
! 425: unsigned pcoffset; /* pc offset (for subtraction) */
! 426: unsigned pcscale; /* scaling factor for offset pc */
! 427: };
! 428:
1.1 root 429: /* ARGSUSED */
1.1.1.5 ! root 430: int
1.1 root 431: profil(p, uap, retval)
432: struct proc *p;
1.1.1.5 ! root 433: register struct profil_args *uap;
1.1 root 434: int *retval;
435: {
1.1.1.3 root 436: /* from looking at man pages, and include files, looks like
437: * this just sets up the fields of p->p_stats->p_prof...
438: * and those fields come straight from the args.
439: * only thing *we* have to do is check the args for validity...
440: *
441: * cgd
442: */
1.1 root 443:
1.1.1.3 root 444: /* check to make sure that the buffer is OK. addupc (in locore)
445: * checks for faults, but would one be generated, say, writing to
446: * kernel space? probably not -- it just uses "movl"...
447: *
448: * so we've gotta check to make sure that the info set up for
449: * addupc is set right... it's gotta be writable by the user...
1.1 root 450: */
1.1.1.3 root 451:
1.1.1.5 ! root 452: if (useracc((caddr_t)uap->bufbase, uap->bufsize*sizeof(short), B_WRITE)
! 453: == 0)
1.1.1.3 root 454: return EFAULT;
455:
456: p->p_stats->p_prof.pr_base = uap->bufbase;
457: p->p_stats->p_prof.pr_size = uap->bufsize;
458: p->p_stats->p_prof.pr_off = uap->pcoffset;
459: p->p_stats->p_prof.pr_scale = uap->pcscale;
460:
461: return 0;
1.1 root 462: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.