This source file includes following definitions.
- get_task
- get_reg
- put_reg
- get_long
- put_long
- find_extend_vma
- read_long
- write_long
- read_int
- write_int
- ptrace_set_bpt
- ptrace_cancel_bpt
- sys_ptrace
- syscall_trace
1
2
3
4
5
6
7 #include <linux/head.h>
8 #include <linux/kernel.h>
9 #include <linux/sched.h>
10 #include <linux/mm.h>
11 #include <linux/errno.h>
12 #include <linux/ptrace.h>
13 #include <linux/user.h>
14 #include <linux/debugreg.h>
15
16 #include <asm/segment.h>
17 #include <asm/pgtable.h>
18 #include <asm/system.h>
19
20 #undef DEBUG
21
22 #ifdef DEBUG
23
24 enum {
25 DBG_MEM = (1<<0),
26 DBG_BPT = (1<<1),
27 DBG_MEM_ALL = (1<<2)
28 };
29
30 int debug_mask = DBG_BPT;
31
32 # define DBG(fac,args) {if ((fac) & debug_mask) printk args;}
33
34 #else
35 # define DBG(fac,args)
36 #endif
37
38 #define BREAKINST 0x00000080
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 #define PT_REG(reg) (PAGE_SIZE - sizeof(struct pt_regs) \
71 + (long)&((struct pt_regs *)0)->reg)
72 #define SW_REG(reg) (PAGE_SIZE - sizeof(struct pt_regs) \
73 - sizeof(struct switch_stack) \
74 + (long)&((struct switch_stack *)0)->reg)
75
76
77
78
79
80
81
82 enum {
83 REG_R0 = 0, REG_F0 = 32, REG_PC = 64
84 };
85
86 static unsigned short regoff[] = {
87 PT_REG( r0), PT_REG( r1), PT_REG( r2), PT_REG( r3),
88 PT_REG( r4), PT_REG( r5), PT_REG( r6), PT_REG( r7),
89 PT_REG( r8), SW_REG( r9), SW_REG( r10), SW_REG( r11),
90 SW_REG( r12), SW_REG( r13), SW_REG( r14), SW_REG( r15),
91 PT_REG( r16), PT_REG( r17), PT_REG( r18), PT_REG( r19),
92 PT_REG( r20), PT_REG( r21), PT_REG( r22), PT_REG( r23),
93 PT_REG( r24), PT_REG( r25), PT_REG( r26), PT_REG( r27),
94 PT_REG( r28), PT_REG( gp), -1, -1,
95 SW_REG(fp[ 0]), SW_REG(fp[ 1]), SW_REG(fp[ 2]), SW_REG(fp[ 3]),
96 SW_REG(fp[ 4]), SW_REG(fp[ 5]), SW_REG(fp[ 6]), SW_REG(fp[ 7]),
97 SW_REG(fp[ 8]), SW_REG(fp[ 9]), SW_REG(fp[10]), SW_REG(fp[11]),
98 SW_REG(fp[12]), SW_REG(fp[13]), SW_REG(fp[14]), SW_REG(fp[15]),
99 SW_REG(fp[16]), SW_REG(fp[17]), SW_REG(fp[18]), SW_REG(fp[19]),
100 SW_REG(fp[20]), SW_REG(fp[21]), SW_REG(fp[22]), SW_REG(fp[23]),
101 SW_REG(fp[24]), SW_REG(fp[25]), SW_REG(fp[26]), SW_REG(fp[27]),
102 SW_REG(fp[28]), SW_REG(fp[29]), SW_REG(fp[30]), SW_REG(fp[31]),
103 PT_REG( pc)
104 };
105
106 static long zero;
107
108
109
110 static inline struct task_struct * get_task(int pid)
111 {
112 int i;
113
114 for (i = 1; i < NR_TASKS; i++) {
115 if (task[i] != NULL && (task[i]->pid == pid))
116 return task[i];
117 }
118 return NULL;
119 }
120
121
122
123
124 static inline long get_reg(struct task_struct * task, long regno)
125 {
126 long *addr;
127
128 if (regno == 30) {
129 addr = &task->tss.usp;
130 } else if (regno == 31) {
131 zero = 0;
132 addr = &zero;
133 } else {
134 addr = (long *) (task->kernel_stack_page + regoff[regno]);
135 }
136 return *addr;
137 }
138
139
140
141
142 static inline int put_reg(struct task_struct *task, long regno, long data)
143 {
144 long *addr, zero;
145
146 if (regno == 30) {
147 addr = &task->tss.usp;
148 } else if (regno == 31) {
149 addr = &zero;
150 } else {
151 addr = (long *) (task->kernel_stack_page + regoff[regno]);
152 }
153 *addr = data;
154 return 0;
155 }
156
157
158
159
160
161
162
163 static unsigned long get_long(struct vm_area_struct * vma, unsigned long addr)
164 {
165 pgd_t * pgdir;
166 pmd_t * pgmiddle;
167 pte_t * pgtable;
168 unsigned long page;
169
170 DBG(DBG_MEM_ALL, ("getting long at 0x%lx\n", addr));
171 repeat:
172 pgdir = pgd_offset(vma->vm_task, addr);
173 if (pgd_none(*pgdir)) {
174 do_no_page(vma, addr, 0);
175 goto repeat;
176 }
177 if (pgd_bad(*pgdir)) {
178 printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
179 pgd_clear(pgdir);
180 return 0;
181 }
182 pgmiddle = pmd_offset(pgdir, addr);
183 if (pmd_none(*pgmiddle)) {
184 do_no_page(vma, addr, 0);
185 goto repeat;
186 }
187 if (pmd_bad(*pgmiddle)) {
188 printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
189 pmd_clear(pgmiddle);
190 return 0;
191 }
192 pgtable = pte_offset(pgmiddle, addr);
193 if (!pte_present(*pgtable)) {
194 do_no_page(vma, addr, 0);
195 goto repeat;
196 }
197 page = pte_page(*pgtable);
198
199 if (page >= high_memory)
200 return 0;
201 page += addr & ~PAGE_MASK;
202 return *(unsigned long *) page;
203 }
204
205
206
207
208
209
210
211
212
213
214 static void put_long(struct vm_area_struct * vma, unsigned long addr,
215 unsigned long data)
216 {
217 pgd_t *pgdir;
218 pmd_t *pgmiddle;
219 pte_t *pgtable;
220 unsigned long page;
221
222 repeat:
223 pgdir = pgd_offset(vma->vm_task, addr);
224 if (!pgd_present(*pgdir)) {
225 do_no_page(vma, addr, 1);
226 goto repeat;
227 }
228 if (pgd_bad(*pgdir)) {
229 printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
230 pgd_clear(pgdir);
231 return;
232 }
233 pgmiddle = pmd_offset(pgdir, addr);
234 if (pmd_none(*pgmiddle)) {
235 do_no_page(vma, addr, 1);
236 goto repeat;
237 }
238 if (pmd_bad(*pgmiddle)) {
239 printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
240 pmd_clear(pgmiddle);
241 return;
242 }
243 pgtable = pte_offset(pgmiddle, addr);
244 if (!pte_present(*pgtable)) {
245 do_no_page(vma, addr, 1);
246 goto repeat;
247 }
248 page = pte_page(*pgtable);
249 if (!pte_write(*pgtable)) {
250 do_wp_page(vma, addr, 1);
251 goto repeat;
252 }
253
254 if (page < high_memory)
255 *(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
256
257
258 set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
259 invalidate();
260 }
261
262 static struct vm_area_struct * find_extend_vma(struct task_struct * tsk,
263 unsigned long addr)
264 {
265 struct vm_area_struct * vma;
266
267 addr &= PAGE_MASK;
268 vma = find_vma(tsk,addr);
269 if (!vma)
270 return NULL;
271 if (vma->vm_start <= addr)
272 return vma;
273 if (!(vma->vm_flags & VM_GROWSDOWN))
274 return NULL;
275 if (vma->vm_end - addr > tsk->rlim[RLIMIT_STACK].rlim_cur)
276 return NULL;
277 vma->vm_offset -= vma->vm_start - addr;
278 vma->vm_start = addr;
279 return vma;
280 }
281
282
283
284
285
286 static int read_long(struct task_struct * tsk, unsigned long addr,
287 unsigned long * result)
288 {
289 struct vm_area_struct * vma = find_extend_vma(tsk, addr);
290
291 DBG(DBG_MEM_ALL, ("in read_long\n"));
292 if (!vma) {
293 printk("Unable to find vma for addr 0x%lx\n",addr);
294 return -EIO;
295 }
296 if ((addr & ~PAGE_MASK) > (PAGE_SIZE - sizeof(long))) {
297 struct vm_area_struct * vma_high = vma;
298 unsigned long low, align;
299
300 if (addr + sizeof(long) >= vma->vm_end) {
301 vma_high = vma->vm_next;
302 if (!vma_high || vma_high->vm_start != vma->vm_end)
303 return -EIO;
304 }
305 align = addr & (sizeof(long) - 1);
306 addr -= align;
307 low = get_long(vma, addr);
308 if (align) {
309 unsigned long high;
310
311 high = get_long(vma_high, addr + sizeof(long));
312 low >>= align * 8;
313 low |= high << (64 - align * 8);
314 }
315 *result = low;
316 } else {
317 long l = get_long(vma, addr);
318
319 DBG(DBG_MEM_ALL, ("value is 0x%lx\n", l));
320 *result = l;
321 }
322 return 0;
323 }
324
325
326
327
328
329 static int write_long(struct task_struct * tsk, unsigned long addr,
330 unsigned long data)
331 {
332 struct vm_area_struct * vma = find_extend_vma(tsk, addr);
333
334 if (!vma)
335 return -EIO;
336 if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) {
337 unsigned long low, high, align;
338 struct vm_area_struct * vma_high = vma;
339
340 if (addr + sizeof(long) >= vma->vm_end) {
341 vma_high = vma->vm_next;
342 if (!vma_high || vma_high->vm_start != vma->vm_end)
343 return -EIO;
344 }
345 align = addr & (sizeof(long) - 1);
346 addr -= align;
347 low = get_long(vma, addr);
348 high = get_long(vma_high, addr + sizeof(long));
349 low &= ~0UL >> (64 - align * 8);
350 high &= ~0UL << (align * 8);
351 low |= data << (align * 8);
352 high |= data >> (64 - align * 8);
353 put_long(vma, addr, low);
354 put_long(vma_high, addr + sizeof(long), high);
355 } else
356 put_long(vma, addr, data);
357 return 0;
358 }
359
360
361
362
363 static int read_int(struct task_struct * tsk, unsigned long addr,
364 unsigned int *data)
365 {
366 unsigned long l, align;
367 int res;
368
369 align = addr & 0x7;
370 addr &= ~0x7;
371
372 res = read_long(tsk, addr, &l);
373 if (res < 0)
374 return res;
375
376 if (align == 0) {
377 *data = l;
378 } else {
379 *data = l >> 32;
380 }
381 return 0;
382 }
383
384
385
386
387
388
389
390 static int write_int(struct task_struct * tsk, unsigned long addr,
391 unsigned int data)
392 {
393 unsigned long l, align;
394 int res;
395
396 align = addr & 0x7;
397 addr &= ~0x7;
398
399 res = read_long(tsk, addr, &l);
400 if (res < 0)
401 return res;
402
403 if (align == 0) {
404 l = (l & 0xffffffff00000000UL) | ((unsigned long) data << 0);
405 } else {
406 l = (l & 0x00000000ffffffffUL) | ((unsigned long) data << 32);
407 }
408 return write_long(tsk, addr, l);
409 }
410
411
412
413
414 int ptrace_set_bpt(struct task_struct * child)
415 {
416 int displ, i, res, reg_b, nsaved = 0;
417 u32 insn, op_code;
418 unsigned long pc;
419
420 pc = get_reg(child, REG_PC);
421 res = read_int(child, pc, &insn);
422 if (res < 0)
423 return res;
424
425 op_code = insn >> 26;
426 if (op_code >= 0x30) {
427
428
429
430
431
432
433
434
435 displ = ((s32)(insn << 11)) >> 9;
436 child->debugreg[nsaved++] = pc + 4;
437 if (displ)
438 child->debugreg[nsaved++] = pc + 4 + displ;
439 DBG(DBG_BPT, ("execing branch\n"));
440 } else if (op_code == 0x1a) {
441 reg_b = (insn >> 16) & 0x1f;
442 child->debugreg[nsaved++] = get_reg(child, reg_b);
443 DBG(DBG_BPT, ("execing jump\n"));
444 } else {
445 child->debugreg[nsaved++] = pc + 4;
446 DBG(DBG_BPT, ("execing normal insn\n"));
447 }
448
449
450 for (i = 0; i < nsaved; ++i) {
451 res = read_int(child, child->debugreg[i], &insn);
452 if (res < 0)
453 return res;
454 child->debugreg[i + 2] = insn;
455 DBG(DBG_BPT, (" -> next_pc=%lx\n", child->debugreg[i]));
456 res = write_int(child, child->debugreg[i], BREAKINST);
457 if (res < 0)
458 return res;
459 }
460 child->debugreg[4] = nsaved;
461 return 0;
462 }
463
464
465
466
467
468 int ptrace_cancel_bpt(struct task_struct * child)
469 {
470 int i, nsaved = child->debugreg[4];
471
472 child->debugreg[4] = 0;
473
474 if (nsaved > 2) {
475 printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
476 nsaved = 2;
477 }
478
479 for (i = 0; i < nsaved; ++i) {
480 write_int(child, child->debugreg[i], child->debugreg[i + 2]);
481 }
482 return (nsaved != 0);
483 }
484
485 asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
486 int a4, int a5, struct pt_regs regs)
487 {
488 struct task_struct *child;
489 struct user * dummy;
490
491 dummy = NULL;
492
493 DBG(DBG_MEM, ("request=%ld pid=%ld addr=0x%lx data=0x%lx\n",
494 request, pid, addr, data));
495 if (request == PTRACE_TRACEME) {
496
497 if (current->flags & PF_PTRACED)
498 return -EPERM;
499
500 current->flags |= PF_PTRACED;
501 return 0;
502 }
503 if (pid == 1)
504 return -EPERM;
505 if (!(child = get_task(pid)))
506 return -ESRCH;
507 if (request == PTRACE_ATTACH) {
508 if (child == current)
509 return -EPERM;
510 if ((!child->dumpable ||
511 (current->uid != child->euid) ||
512 (current->uid != child->uid) ||
513 (current->gid != child->egid) ||
514 (current->gid != child->gid)) && !suser())
515 return -EPERM;
516
517 if (child->flags & PF_PTRACED)
518 return -EPERM;
519 child->flags |= PF_PTRACED;
520 if (child->p_pptr != current) {
521 REMOVE_LINKS(child);
522 child->p_pptr = current;
523 SET_LINKS(child);
524 }
525 send_sig(SIGSTOP, child, 1);
526 return 0;
527 }
528 if (!(child->flags & PF_PTRACED)) {
529 DBG(DBG_MEM, ("child not traced\n"));
530 return -ESRCH;
531 }
532 if (child->state != TASK_STOPPED) {
533 DBG(DBG_MEM, ("child process not stopped\n"));
534 if (request != PTRACE_KILL)
535 return -ESRCH;
536 }
537 if (child->p_pptr != current) {
538 DBG(DBG_MEM, ("child not parent of this process\n"));
539 return -ESRCH;
540 }
541
542 switch (request) {
543
544 case PTRACE_PEEKTEXT:
545 case PTRACE_PEEKDATA: {
546 unsigned long tmp;
547 int res;
548
549 res = read_long(child, addr, &tmp);
550 DBG(DBG_MEM, ("peek %#lx->%#lx\n", addr, tmp));
551 if (res < 0)
552 return res;
553 regs.r0 = tmp;
554 return -255;
555 }
556
557
558 case PTRACE_PEEKUSR:
559 regs.r0 = get_reg(child, addr);
560 DBG(DBG_MEM, ("peek $%ld=%#lx\n", addr, regs.r0));
561 return -255;
562
563
564 case PTRACE_POKETEXT:
565 case PTRACE_POKEDATA:
566 DBG(DBG_MEM, ("poke %#lx<-%#lx\n", addr, data));
567 return write_long(child, addr, data);
568
569 case PTRACE_POKEUSR:
570 DBG(DBG_MEM, ("poke $%ld<-%#lx\n", addr, data));
571 return put_reg(child, addr, data);
572
573 case PTRACE_SYSCALL:
574
575 case PTRACE_CONT: {
576 if ((unsigned long) data > NSIG)
577 return -EIO;
578 if (request == PTRACE_SYSCALL)
579 child->flags |= PF_TRACESYS;
580 else
581 child->flags &= ~PF_TRACESYS;
582 child->exit_code = data;
583 wake_up_process(child);
584
585 ptrace_cancel_bpt(child);
586 return data;
587 }
588
589
590
591
592
593
594 case PTRACE_KILL: {
595 if (child->state != TASK_ZOMBIE) {
596 wake_up_process(child);
597 child->exit_code = SIGKILL;
598 }
599
600 ptrace_cancel_bpt(child);
601 return 0;
602 }
603
604 case PTRACE_SINGLESTEP: {
605 if ((unsigned long) data > NSIG)
606 return -EIO;
607 child->debugreg[4] = -1;
608 child->flags &= ~PF_TRACESYS;
609 wake_up_process(child);
610 child->exit_code = data;
611
612 return 0;
613 }
614
615 case PTRACE_DETACH: {
616 if ((unsigned long) data > NSIG)
617 return -EIO;
618 child->flags &= ~(PF_PTRACED|PF_TRACESYS);
619 wake_up_process(child);
620 child->exit_code = data;
621 REMOVE_LINKS(child);
622 child->p_pptr = child->p_opptr;
623 SET_LINKS(child);
624
625 ptrace_cancel_bpt(child);
626 return 0;
627 }
628
629 default:
630 return -EIO;
631 }
632 }
633
634 asmlinkage void syscall_trace(void)
635 {
636 if ((current->flags & (PF_PTRACED|PF_TRACESYS))
637 != (PF_PTRACED|PF_TRACESYS))
638 return;
639 current->exit_code = SIGTRAP;
640 current->state = TASK_STOPPED;
641 notify_parent(current);
642 schedule();
643
644
645
646
647
648 if (current->exit_code)
649 current->signal |= (1 << (current->exit_code - 1));
650 current->exit_code = 0;
651 }