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