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 page += addr & ~PAGE_MASK;
227 *(unsigned long *) page = data;
228 }
229
230
231 *pgtable = pte_mkdirty(mk_pte(page, vma->vm_page_prot));
232 invalidate();
233 }
234
235 static struct vm_area_struct * find_extend_vma(struct task_struct * tsk, unsigned long addr)
236 {
237 struct vm_area_struct * vma;
238
239 addr &= PAGE_MASK;
240 vma = find_vma(tsk,addr);
241 if (!vma)
242 return NULL;
243 if (vma->vm_start <= addr)
244 return vma;
245 if (!(vma->vm_flags & VM_GROWSDOWN))
246 return NULL;
247 if (vma->vm_end - addr > tsk->rlim[RLIMIT_STACK].rlim_cur)
248 return NULL;
249 vma->vm_offset -= vma->vm_start - addr;
250 vma->vm_start = addr;
251 return vma;
252 }
253
254
255
256
257
258 static int read_long(struct task_struct * tsk, unsigned long addr,
259 unsigned long * result)
260 {
261 struct vm_area_struct * vma = find_extend_vma(tsk, addr);
262
263 DBG(DBG_MEM, ("in read_long\n"));
264 if (!vma) {
265 printk("Unable to find vma for addr 0x%lx\n",addr);
266 return -EIO;
267 }
268 if ((addr & ~PAGE_MASK) > (PAGE_SIZE-sizeof(long))) {
269 unsigned long low,high;
270 struct vm_area_struct * vma_high = vma;
271
272 if (addr + sizeof(long) >= vma->vm_end) {
273 vma_high = vma->vm_next;
274 if (!vma_high || vma_high->vm_start != vma->vm_end)
275 return -EIO;
276 }
277 low = get_long(vma, addr & ~(sizeof(long)-1));
278 high = get_long(vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1));
279 switch (addr & (sizeof(long)-1)) {
280 case 1:
281 low >>= 8;
282 low |= high << 56;
283 break;
284 case 2:
285 low >>= 16;
286 low |= high << 48;
287 break;
288 case 3:
289 low >>= 24;
290 low |= high << 40;
291 break;
292 case 4:
293 low >>= 32;
294 low |= high << 32;
295 break;
296 case 5:
297 low >>= 40;
298 low |= high << 24;
299 break;
300 case 6:
301 low >>= 48;
302 low |= high << 16;
303 break;
304 case 7:
305 low >>= 56;
306 low |= high << 8;
307 break;
308 }
309 *result = low;
310 } else {
311 long l =get_long(vma, addr);
312
313 DBG(DBG_MEM, ("value is 0x%lx\n",l));
314 *result = l;
315 }
316 return 0;
317 }
318
319
320
321
322
323 static int write_long(struct task_struct * tsk, unsigned long addr,
324 unsigned long data)
325 {
326 struct vm_area_struct * vma = find_extend_vma(tsk, addr);
327
328 if (!vma)
329 return -EIO;
330 if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) {
331 unsigned long low,high;
332 struct vm_area_struct * vma_high = vma;
333
334 if (addr + sizeof(long) >= vma->vm_end) {
335 vma_high = vma->vm_next;
336 if (!vma_high || vma_high->vm_start != vma->vm_end)
337 return -EIO;
338 }
339 low = get_long(vma, addr & ~(sizeof(long)-1));
340 high = get_long(vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1));
341 switch (addr & (sizeof(long)-1)) {
342 case 0:
343 low = data;
344 break;
345 case 1:
346 low &= 0x00000000000000ffL;
347 low |= data << 8;
348 high &= ~0x000000000000ffL;
349 high |= data >> 56;
350 break;
351 case 2:
352 low &= 0x000000000000ffffL;
353 low |= data << 16;
354 high &= ~0x0000000000ffffL;
355 high |= data >> 48;
356 break;
357 case 3:
358 low &= 0x0000000000ffffffL;
359 low |= data << 24;
360 high &= ~0x00000000ffffffL;
361 high |= data >> 40;
362 break;
363 case 4:
364 low &= 0x00000000ffffffffL;
365 low |= data << 32;
366 high &= ~0x000000ffffffffL;
367 high |= data >> 32;
368 break;
369
370 case 5:
371 low &= 0x000000ffffffffffL;
372 low |= data << 40;
373 high &= ~0x0000ffffffffffL;
374 high |= data >> 24;
375 break;
376 case 6:
377 low &= 0x0000ffffffffffffL;
378 low |= data << 48;
379 high &= ~0x00ffffffffffffL;
380 high |= data >> 16;
381 break;
382 case 7:
383 low &= 0x00ffffffffffffffL;
384 low |= data << 56;
385 high &= ~0xffffffffffffffL;
386 high |= data >> 8;
387 break;
388 }
389 put_long(vma, addr & ~(sizeof(long)-1),low);
390 put_long(vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1),high);
391 } else
392 put_long(vma, addr, data);
393 return 0;
394 }
395
396
397
398
399 static int read_int(struct task_struct * tsk, unsigned long addr, unsigned int *data)
400 {
401 unsigned long l, align;
402 int res;
403
404 align = addr & 0x7;
405 addr &= ~0x7;
406
407 res = read_long(tsk, addr, &l);
408 if (res < 0)
409 return res;
410
411 if (align == 0) {
412 *data = l;
413 } else {
414 *data = l >> 32;
415 }
416 return 0;
417 }
418
419
420
421
422
423
424
425 static int write_int(struct task_struct * tsk, unsigned long addr, unsigned int data)
426 {
427 unsigned long l, align;
428 int res;
429
430 align = addr & 0x7;
431 addr &= ~0x7;
432
433 res = read_long(tsk, addr, &l);
434 if (res < 0)
435 return res;
436
437 if (align == 0) {
438 l = (l & 0xffffffff00000000UL) | ((unsigned long) data << 0);
439 } else {
440 l = (l & 0x00000000ffffffffUL) | ((unsigned long) data << 32);
441 }
442 return write_long(tsk, addr, l);
443 }
444
445
446
447
448
449
450
451 static inline void set_success(struct pt_regs *regs,long resval)
452 {
453 regs->r19 = resval;
454 }
455
456
457
458
459
460
461 static inline void set_failure(struct pt_regs *regs, long errcode)
462 {
463 regs->r19 = 0;
464 }
465
466
467
468
469 static int set_bpt(struct task_struct *child)
470 {
471 int displ, i, res, reg_b, off, nsaved = 0;
472 u32 insn, op_code;
473 unsigned long pc;
474
475 pc = get_stack_long(child, map_reg_to_offset[REG_PC]);
476 res = read_int(child, pc, &insn);
477 if (res < 0)
478 return res;
479
480 op_code = insn >> 26;
481 if (op_code >= 0x30) {
482
483
484
485
486
487
488
489
490 displ = ((s32)(insn << 11)) >> 9;
491 child->debugreg[nsaved++] = pc + 4;
492 if (displ)
493 child->debugreg[nsaved++] = pc + 4 + displ;
494 DBG(DBG_BPT, ("execing branch\n"));
495 } else if (op_code == 0x1a) {
496 reg_b = (insn >> 16) & 0x1f;
497 off = offset_of_register(reg_b);
498 if (off >= 0) {
499 child->debugreg[nsaved++] = get_stack_long(child, off);
500 } else {
501
502 if (reg_b == 31) {
503 child->debugreg[nsaved++] = 0;
504 } else {
505 return -EIO;
506 }
507 }
508 DBG(DBG_BPT, ("execing jump\n"));
509 } else {
510 child->debugreg[nsaved++] = pc + 4;
511 DBG(DBG_BPT, ("execing normal insn\n"));
512 }
513
514
515 for (i = 0; i < nsaved; ++i) {
516 res = read_int(child, child->debugreg[i], &insn);
517 if (res < 0)
518 return res;
519 child->debugreg[i + 2] = insn;
520 DBG(DBG_BPT, (" -> next_pc=%lx\n", child->debugreg[i]));
521 res = write_int(child, child->debugreg[i], BREAKINST);
522 if (res < 0)
523 return res;
524 }
525 child->debugreg[4] = nsaved;
526 return 0;
527 }
528
529 int ptrace_cancel_bpt(struct task_struct *child)
530 {
531 int i, nsaved = child->debugreg[4];
532
533 child->debugreg[4] = 0;
534
535 if (nsaved > 2) {
536 printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
537 nsaved = 2;
538 }
539
540 for (i = 0; i < nsaved; ++i) {
541 write_int(child, child->debugreg[i], child->debugreg[i + 2]);
542 }
543 return nsaved;
544 }
545
546 asmlinkage long sys_ptrace(long request, long pid, long addr, long data, int a4, int a5,
547 struct pt_regs regs)
548 {
549 struct task_struct *child;
550 struct user * dummy;
551 int res;
552
553 dummy = NULL;
554
555 DBG(DBG_MEM, ("request=%ld pid=%ld addr=0x%lx data=0x%lx\n",request,pid,addr,data));
556 set_success(®s,0);
557 if (request == PTRACE_TRACEME) {
558
559 if (current->flags & PF_PTRACED) {
560 set_failure(®s,-EPERM);
561 return -EPERM;
562 }
563
564 current->flags |= PF_PTRACED;
565 return 0;
566 }
567 if (pid == 1) {
568 set_failure(®s,-EPERM);
569 return -EPERM;
570 }
571 if (!(child = get_task(pid))) {
572 set_failure(®s,-ESRCH);
573 return -ESRCH;
574 }
575 if (request == PTRACE_ATTACH) {
576 if (child == current) {
577 set_failure(®s,-EPERM);
578 return -EPERM;
579 }
580 if ((!child->dumpable ||
581 (current->uid != child->euid) ||
582 (current->uid != child->uid) ||
583 (current->gid != child->egid) ||
584 (current->gid != child->gid)) && !suser()) {
585 set_failure(®s,-EPERM);
586 return -EPERM;
587 }
588
589 if (child->flags & PF_PTRACED) {
590 set_failure(®s,-EPERM);
591 return -EPERM;
592 }
593 child->flags |= PF_PTRACED;
594 if (child->p_pptr != current) {
595 REMOVE_LINKS(child);
596 child->p_pptr = current;
597 SET_LINKS(child);
598 }
599 send_sig(SIGSTOP, child, 1);
600 return 0;
601 }
602 if (!(child->flags & PF_PTRACED)) {
603 DBG(DBG_MEM, ("child not traced\n"));
604 set_failure(®s,-ESRCH);
605 return -ESRCH;
606 }
607 if (child->state != TASK_STOPPED) {
608 DBG(DBG_MEM, ("child process not stopped\n"));
609 if (request != PTRACE_KILL) {
610 set_failure(®s,-ESRCH);
611 return -ESRCH;
612 }
613 }
614 if (child->p_pptr != current) {
615 DBG(DBG_MEM, ("child not parent of this process\n"));
616 set_failure(®s,-ESRCH);
617 return -ESRCH;
618 }
619
620 switch (request) {
621
622 case PTRACE_PEEKTEXT:
623 case PTRACE_PEEKDATA: {
624 unsigned long tmp;
625 int res;
626
627 DBG(DBG_MEM, ("doing request at addr 0x%lx\n",addr));
628 res = read_long(child, addr, &tmp);
629 if (res < 0) {
630 set_failure(®s,res);
631 return res;
632 } else {
633 set_success(®s,tmp);
634 return 0;
635 }
636 }
637
638
639 case PTRACE_PEEKUSR: {
640
641 unsigned long tmp;
642
643 tmp = 0;
644 if (addr == 30) {
645
646 tmp=child->tss.usp;
647 } else {
648 #ifdef DEBUG
649 int reg = addr;
650 #endif
651 addr = offset_of_register(addr);
652 if (addr < 0) {
653 set_failure(®s, -EIO);
654 return -EIO;
655 }
656 tmp = get_stack_long(child, addr);
657 DBG(DBG_MEM, ("%d = reg 0x%lx=tmp\n",reg,tmp));
658 }
659 set_success(®s,tmp);
660 return 0;
661 }
662
663
664 case PTRACE_POKETEXT:
665 case PTRACE_POKEDATA: {
666 long res = write_long(child,addr,data);
667 if (res) {
668 set_failure(®s,res);
669 }
670 return res;
671 }
672
673 case PTRACE_POKEUSR:
674 {
675 long res;
676 addr = offset_of_register(addr);
677 if(addr < 0) {
678 set_failure(®s,-EIO);
679 return -EIO;
680 }
681 res = put_stack_long(child, addr, data);
682 if (res) {
683 set_failure(®s,res);
684 }
685 return res;
686 }
687
688 case PTRACE_SYSCALL:
689
690 case PTRACE_CONT: {
691 if ((unsigned long) data > NSIG) {
692 set_failure(®s,-EIO);
693 return -EIO;
694 }
695 if (request == PTRACE_SYSCALL)
696 child->flags |= PF_TRACESYS;
697 else
698 child->flags &= ~PF_TRACESYS;
699 child->exit_code = data;
700 wake_up_process(child);
701
702 ptrace_cancel_bpt(child);
703 set_success(®s,data);
704 return 0;
705 }
706
707
708
709
710
711
712 case PTRACE_KILL: {
713 wake_up_process(child);
714 child->exit_code = SIGKILL;
715
716 ptrace_cancel_bpt(child);
717 return 0;
718 }
719
720 case PTRACE_SINGLESTEP: {
721 if ((unsigned long) data > NSIG) {
722 set_failure(®s,-EIO);
723 return -EIO;
724 }
725 res = set_bpt(child);
726 if (res < 0) {
727 return res;
728 }
729 child->flags &= ~PF_TRACESYS;
730 wake_up_process(child);
731 child->exit_code = data;
732
733 return 0;
734 }
735
736 case PTRACE_DETACH: {
737 if ((unsigned long) data > NSIG) {
738 set_failure(®s,-EIO);
739 return -EIO;
740 }
741 child->flags &= ~(PF_PTRACED|PF_TRACESYS);
742 wake_up_process(child);
743 child->exit_code = data;
744 REMOVE_LINKS(child);
745 child->p_pptr = child->p_opptr;
746 SET_LINKS(child);
747
748 ptrace_cancel_bpt(child);
749 return 0;
750 }
751
752 default:
753 set_failure(®s,-EIO);
754 return -EIO;
755 }
756 }
757
758 asmlinkage void syscall_trace(void)
759 {
760 if ((current->flags & (PF_PTRACED|PF_TRACESYS))
761 != (PF_PTRACED|PF_TRACESYS))
762 return;
763 current->exit_code = SIGTRAP;
764 current->state = TASK_STOPPED;
765 notify_parent(current);
766 schedule();
767
768
769
770
771
772 if (current->exit_code)
773 current->signal |= (1 << (current->exit_code - 1));
774 current->exit_code = 0;
775 }