|
|
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.4 ! root 34: *
! 35: * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
! 36: * -------------------- ----- ----------------------
! 37: * CURRENT PATCH LEVEL: 1 00137
! 38: * -------------------- ----- ----------------------
! 39: *
! 40: * 04 Sep 92 Paul Kranenburg Fixed copy-on-write checking for pages
! 41: * other than anonymous (text pages, etc.)
! 42: * 08 Apr 93 Bruce Evans Several VM system fixes
1.1 root 43: */
44:
45: #define IPCREG
46: #include "param.h"
47: #include "proc.h"
48: #include "vnode.h"
49: #include "buf.h"
50: #include "ptrace.h"
51:
52: #include "machine/reg.h"
53: #include "machine/psl.h"
54: #include "vm/vm.h"
55: #include "vm/vm_page.h"
56:
57: #include "user.h"
58:
59: /*
1.1.1.3 root 60: * NOTES.
61: *
62: * The following ptrace calls have been defined in addition to
63: * the standard ones found in original <sys/ptrace.h>:
64: *
65: * PT_ATTACH - attach to running process
66: * PT_DETACH - detach from running process
67: * PT_SYSCALL - trace system calls
68: * PT_GETREG - get register file
69: * PT_SETREG - set register file
70: * PT_BREAD_[IDU] - block read from process (not yet implemented)
71: * PT_BWRITE_[IDU] - block write " "
72: * PT_INHERIT - make forked processes inherit trace flags
73: *
74: */
75:
76: /* Define to prevent extraneous clutter in source */
77: #ifndef SSTRC
78: #define SSTRC 0
79: #endif
80: #ifndef SFTRC
81: #define SFTRC 0
82: #endif
83:
84: /*
85: * `ipcreg' defined in <machine/reg.h>
86: * Should we define a structure with all regs?
87: */
88: int sipcreg[NIPCREG] =
89: { 0,0,sEDI,sESI,sEBP,sEBX,sEDX,sECX,sEAX,sEIP,sCS,sEFLAGS,sESP,sSS };
90:
91: struct {
92: int flag;
93: #define IPC_BUSY 1
94: #define IPC_WANT 2
95: #define IPC_DONE 4
96: int req; /* copy of ptrace request */
97: int *addr; /* copy of ptrace address */
98: int data; /* copy of ptrace data */
99: int error; /* errno from `procxmt' */
100: int regs[NIPCREG]; /* PT_[GS]ETREG */
101: caddr_t buf; /* PT_BREAD/WRITE */
102: int buflen; /* " */
103: } ipc;
104:
105: /*
1.1 root 106: * Process debugging system call.
107: */
108: ptrace(curp, uap, retval)
109: struct proc *curp;
110: register struct args {
111: int req;
112: int pid;
113: int *addr;
114: int data;
115: } *uap;
116: int *retval;
117: {
1.1.1.3 root 118: struct proc *p;
119: int s, error = 0;
1.1 root 120:
1.1.1.3 root 121: *retval = 0;
122: if (uap->req == PT_TRACE_ME) {
123: curp->p_flag |= STRC;
124: /*p->p_tptr = p->p_pptr; * What shall we do here ? */
125: return 0;
126: }
127: if ((p = pfind(uap->pid)) == NULL) {
128: return ESRCH;
129: }
130:
131: #ifdef notyet
132: if (uap->req != PT_ATTACH && (
133: (p->p_flag & STRC) == 0 ||
134: (p->p_tptr && curp != p->p_tptr) ||
135: (!p->p_tptr && curp != p->p_pptr)))
136:
137: return ESRCH;
138: #endif
139:
140:
141: #ifdef PT_ATTACH
142: switch (uap->req) {
143: case PT_ATTACH:
144: if (curp->p_ucred->cr_uid != 0 && (
145: curp->p_ucred->cr_uid != p->p_ucred->cr_uid ||
146: curp->p_ucred->cr_uid != p->p_cred->p_svuid))
147: return EACCES;
148:
149: p->p_tptr = curp;
150: p->p_flag |= STRC;
151: psignal(p, SIGTRAP);
152: return 0;
153:
154: case PT_DETACH:
155: if ((unsigned)uap->data >= NSIG)
156: return EINVAL;
157: p->p_flag &= ~(STRC|SSTRC|SFTRC);
158: p->p_tptr = NULL;
159: psignal(p->p_pptr, SIGCHLD);
160: wakeup((caddr_t)p->p_pptr);
161: s = splhigh();
162: if (p->p_stat == SSTOP) {
163: p->p_xstat = uap->data;
164: setrun(p);
165: } else if (uap->data) {
166: psignal(p, uap->data);
167: }
168: splx(s);
169: return 0;
170:
171: #ifdef PT_INHERIT
172: case PT_INHERIT:
173: if ((p->p_flag & STRC) == 0)
174: return ESRCH;
175: p->p_flag |= SFTRC;
176: return 0;
177: #endif
178:
179: default:
180: break;
181: }
182: #endif
183:
184: /* Other ptrace calls require target process to be in stopped state */
185: if ((p->p_flag & STRC) == 0 || p->p_stat != SSTOP) {
186: return ESRCH;
187: }
188:
189: /* Acquire the ipc structure */
190: while (ipc.flag & IPC_BUSY) {
191: ipc.flag |= IPC_WANT;
192: error = tsleep((caddr_t)&ipc, PWAIT|PCATCH, "ipc", 0);
193: if (error)
194: goto out;
195: }
196:
197: /* Got it, fill it */
198: ipc.flag = IPC_BUSY;
199: ipc.error = 0;
200: ipc.req = uap->req;
201: ipc.addr = uap->addr;
202: ipc.data = uap->data;
203:
204: #ifdef PT_GETREGS
205: switch (uap->req) {
206: case PT_SETREGS:
207: error = copyin((char *)ipc.addr, (char *)ipc.regs, sizeof(ipc.regs));
208: if (error)
209: goto out;
210: break;
211:
212: #ifdef notyet /* requires change in number of args to ptrace syscall */
213: case PT_BWRITE_I:
214: case PT_BWRITE_D:
215: ipc.buflen = uap->data;
216: ipc.buf = kmem_alloc_wait(kernelmap, uap->data);
217: error = copyin((char *)ipc.addr, (char *)ipc.buf, ipc.buflen);
218: if (error) {
219: kmem_free_wakeup(kernelmap, ipc.buf, ipc.buflen);
220: goto out;
221: }
222: #endif
223: default:
224: break;
225: }
226: #endif
227:
228: setrun(p);
229: while ((ipc.flag & IPC_DONE) == 0) {
230: error = tsleep((caddr_t)&ipc, PWAIT|PCATCH, "ipc", 0);
231: if (error)
232: goto out;
233: }
234:
235: *retval = ipc.data;
236: if (error = ipc.error)
237: goto out;
238:
239: #ifdef PT_GETREGS
240: switch (uap->req) {
241: case PT_GETREGS:
242: error = copyout((char *)ipc.regs, (char *)ipc.addr, sizeof(ipc.regs));
243: break;
244:
245: case PT_BREAD_I:
246: case PT_BREAD_D:
247: /* Not yet */
248: default:
249: break;
250: }
251: #endif
252:
253: out:
254: /* Release ipc structure */
255: ipc.flag &= ~IPC_BUSY;
256: if (ipc.flag & IPC_WANT) {
257: ipc.flag &= ~IPC_WANT;
258: wakeup((caddr_t)&ipc);
259: }
260: return error;
1.1 root 261: }
262:
263: procxmt(p)
264: register struct proc *p;
265: {
1.1.1.3 root 266: int i, *xreg, rv = 0;
1.1 root 267:
1.1.1.3 root 268: /* Are we still being traced? */
269: if ((p->p_flag & STRC) == 0)
270: return 1;
271:
272: p->p_addr->u_kproc.kp_proc = *p;
273: fill_eproc(p, &p->p_addr->u_kproc.kp_eproc);
274:
275: switch (ipc.req) {
276: case PT_READ_I:
277: case PT_READ_D:
1.1.1.4 ! root 278: if (!useracc(ipc.addr, sizeof(ipc.data), B_READ)) {
! 279: ipc.error = EFAULT;
! 280: break;
! 281: }
1.1.1.3 root 282: ipc.error = copyin((char *)ipc.addr, (char *)&ipc.data, sizeof(ipc.data));
283: break;
284:
285: case PT_READ_U:
286: if ((u_int)ipc.addr > UPAGES * NBPG - sizeof(int)) {
287: ipc.error = EFAULT;
288: break;
289: }
290: ipc.data = *(int *)((u_int)p->p_addr + (u_int)ipc.addr);
291: break;
292:
293: case PT_WRITE_I:
1.1.1.4 ! root 294: case PT_WRITE_D: { /* 04 Sep 92*/
! 295: vm_prot_t prot; /* current protection of region */
! 296: int cow; /* ensure copy-on-write happens */
! 297:
! 298: if (cow = (useracc(ipc.addr, sizeof(ipc.data), B_WRITE) == 0)) {
! 299: vm_offset_t addr = (vm_offset_t)ipc.addr;
! 300: vm_size_t size;
! 301: vm_prot_t max_prot;
! 302: vm_inherit_t inh;
! 303: boolean_t shared;
! 304: vm_object_t object;
! 305: vm_offset_t objoff;
! 306:
! 307: /*
! 308: * XXX - the useracc check is stronger than the vm
! 309: * checks because the user page tables are in the map.
! 310: */
! 311: if (!useracc(ipc.addr, sizeof(ipc.data), B_READ) ||
! 312: vm_region(&p->p_vmspace->vm_map, &addr, &size,
! 313: &prot, &max_prot, &inh, &shared,
! 314: &object, &objoff) != KERN_SUCCESS ||
! 315: vm_protect(&p->p_vmspace->vm_map, ipc.addr,
! 316: sizeof(ipc.data), FALSE,
! 317: prot|VM_PROT_WRITE) != KERN_SUCCESS ||
! 318: vm_fault(&p->p_vmspace->vm_map,trunc_page(ipc.addr),
! 319: VM_PROT_WRITE, FALSE) != KERN_SUCCESS) {
! 320:
! 321: ipc.error = EFAULT;
! 322: break;
! 323: }
! 324: }
! 325: ipc.error = copyout((char *)&ipc.data,
! 326: (char *)ipc.addr, sizeof(ipc.data));
! 327: if (cow)
! 328: if (vm_protect(&p->p_vmspace->vm_map, ipc.addr,
! 329: sizeof(ipc.data), FALSE,
! 330: prot) != KERN_SUCCESS)
! 331: printf("ptrace: oops\n");
1.1.1.3 root 332: break;
1.1.1.4 ! root 333: }
1.1.1.3 root 334:
335: case PT_WRITE_U:
336: if ((u_int)ipc.addr > UPAGES * NBPG - sizeof(int)) {
337: ipc.error = EFAULT;
338: break;
339: }
340: *(int *)((u_int)p->p_addr + (u_int)ipc.addr) = ipc.data;
341: break;
342:
343: case PT_CONTINUE:
344: if (ipc.addr != (int *)1) {
345: #ifdef i386
346: p->p_regs[(curpcb->pcb_flags&FM_TRAP)?tEIP:sEIP] = (int)ipc.addr;
347: #endif
348: }
349: p->p_flag &= ~SSTRC; /* Only set by PT_SYSCALL */
350: if ((unsigned)ipc.data >= NSIG) {
351: ipc.error = EINVAL;
352: } else {
353: p->p_xstat = ipc.data;
354: rv = 1;
355: }
356: break;
357:
358: case PT_KILL:
359: p->p_flag &= ~SSTRC; /* Only set by PT_SYSCALL */
360: rv = 2;
361: break;
362:
363: case PT_STEP:
364: #ifdef i386
365: if (ipc.addr != (int *)1) {
366: p->p_regs[(curpcb->pcb_flags&FM_TRAP)?tEIP:sEIP] = (int)ipc.addr;
367: }
368: p->p_regs[(curpcb->pcb_flags&FM_TRAP)?tEFLAGS:sEFLAGS] |= PSL_T;
369: #endif
370: p->p_flag &= ~SSTRC; /* Only set by PT_SYSCALL */
371: p->p_xstat = 0;
372: rv = 1;
373: break;
374:
375: #ifdef PT_SYSCALL
376: case PT_SYSCALL:
377: if (ipc.addr != (int *)1) {
378: #ifdef i386
379: p->p_regs[(curpcb->pcb_flags&FM_TRAP)?tEIP:sEIP] = (int)ipc.addr;
380: #endif
381: }
382: p->p_flag |= SSTRC;
383: p->p_xstat = 0;
384: rv = 1;
385: break;
386: #endif
387: #ifdef PT_GETREGS
388: case PT_GETREGS:
389: #ifdef i386
390: xreg = (curpcb->pcb_flags&FM_TRAP)?ipcreg:sipcreg;
391: #endif
392:
393: for (i = 0; i < NIPCREG; i++)
394: ipc.regs[i] = p->p_regs[xreg[i]];
395: break;
396:
397: case PT_SETREGS:
398: #ifdef i386
399: xreg = (curpcb->pcb_flags&FM_TRAP)?ipcreg:sipcreg;
400: #endif
401:
402: for (i = 0; i < NIPCREG; i++)
403: p->p_regs[xreg[i]] = ipc.regs[i];
404: break;
405: #endif
406:
407: #ifdef PT_DUMP
408: case PT_DUMP:
409: /* Should be able to specify core file name */
410: ipc.error = coredump(p);
411: break;
412: #endif
413:
414: default:
415: ipc.error = EINVAL;
416: }
417: ipc.flag |= IPC_DONE;
418: wakeup((caddr_t)&ipc);
419:
420: if (rv == 2)
421: exit(p, 0); /*???*/
422:
423: return rv;
1.1 root 424: }
425:
426: /*
427: * Enable process profiling system call.
428: */
429: /* ARGSUSED */
430: profil(p, uap, retval)
431: struct proc *p;
432: register struct args {
1.1.1.3 root 433: short *bufbase; /* base of data buffer */
434: unsigned bufsize; /* size of data buffer */
435: unsigned pcoffset; /* pc offset (for subtraction) */
436: unsigned pcscale; /* scaling factor for offset pc */
1.1 root 437: } *uap;
438: int *retval;
439: {
1.1.1.3 root 440: /* from looking at man pages, and include files, looks like
441: * this just sets up the fields of p->p_stats->p_prof...
442: * and those fields come straight from the args.
443: * only thing *we* have to do is check the args for validity...
444: *
445: * cgd
446: */
1.1 root 447:
1.1.1.3 root 448: /* check to make sure that the buffer is OK. addupc (in locore)
449: * checks for faults, but would one be generated, say, writing to
450: * kernel space? probably not -- it just uses "movl"...
451: *
452: * so we've gotta check to make sure that the info set up for
453: * addupc is set right... it's gotta be writable by the user...
1.1 root 454: */
1.1.1.3 root 455:
456: if (useracc(uap->bufbase,uap->bufsize*sizeof(short),B_WRITE) == 0)
457: return EFAULT;
458:
459: p->p_stats->p_prof.pr_base = uap->bufbase;
460: p->p_stats->p_prof.pr_size = uap->bufsize;
461: p->p_stats->p_prof.pr_off = uap->pcoffset;
462: p->p_stats->p_prof.pr_scale = uap->pcscale;
463:
464: return 0;
1.1 root 465: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.