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 for (i = 0; i < nsaved; ++i) {
535 write_int(child, child->debugreg[i], child->debugreg[i + 2]);
536 }
537 return nsaved;
538 }
539
540 asmlinkage long sys_ptrace(long request, long pid, long addr, long data, int a4, int a5,
541 struct pt_regs regs)
542 {
543 struct task_struct *child;
544 struct user * dummy;
545 int res;
546
547 dummy = NULL;
548
549 DBG(DBG_MEM, ("request=%ld pid=%ld addr=0x%lx data=0x%lx\n",request,pid,addr,data));
550 set_success(®s,0);
551 if (request == PTRACE_TRACEME) {
552
553 if (current->flags & PF_PTRACED) {
554 set_failure(®s,-EPERM);
555 return -EPERM;
556 }
557
558 current->flags |= PF_PTRACED;
559 return 0;
560 }
561 if (pid == 1) {
562 set_failure(®s,-EPERM);
563 return -EPERM;
564 }
565 if (!(child = get_task(pid))) {
566 set_failure(®s,-ESRCH);
567 return -ESRCH;
568 }
569 if (request == PTRACE_ATTACH) {
570 if (child == current) {
571 set_failure(®s,-EPERM);
572 return -EPERM;
573 }
574 if ((!child->dumpable ||
575 (current->uid != child->euid) ||
576 (current->uid != child->uid) ||
577 (current->gid != child->egid) ||
578 (current->gid != child->gid)) && !suser()) {
579 set_failure(®s,-EPERM);
580 return -EPERM;
581 }
582
583 if (child->flags & PF_PTRACED) {
584 set_failure(®s,-EPERM);
585 return -EPERM;
586 }
587 child->flags |= PF_PTRACED;
588 if (child->p_pptr != current) {
589 REMOVE_LINKS(child);
590 child->p_pptr = current;
591 SET_LINKS(child);
592 }
593 send_sig(SIGSTOP, child, 1);
594 return 0;
595 }
596 if (!(child->flags & PF_PTRACED)) {
597 DBG(DBG_MEM, ("child not traced\n"));
598 set_failure(®s,-ESRCH);
599 return -ESRCH;
600 }
601 if (child->state != TASK_STOPPED) {
602 DBG(DBG_MEM, ("child process not stopped\n"));
603 if (request != PTRACE_KILL) {
604 set_failure(®s,-ESRCH);
605 return -ESRCH;
606 }
607 }
608 if (child->p_pptr != current) {
609 DBG(DBG_MEM, ("child not parent of this process\n"));
610 set_failure(®s,-ESRCH);
611 return -ESRCH;
612 }
613
614 switch (request) {
615
616 case PTRACE_PEEKTEXT:
617 case PTRACE_PEEKDATA: {
618 unsigned long tmp;
619 int res;
620
621 DBG(DBG_MEM, ("doing request at addr 0x%lx\n",addr));
622 res = read_long(child, addr, &tmp);
623 if (res < 0) {
624 set_failure(®s,res);
625 return res;
626 }
627 else {
628 set_success(®s,tmp);
629 return 0;
630 }
631 }
632
633
634 case PTRACE_PEEKUSR: {
635
636 unsigned long tmp;
637
638 tmp = 0;
639 if(addr==30) {
640
641 tmp=child->tss.usp;
642 }
643 else {
644 #ifdef DEBUG
645 int reg=addr;
646 #endif
647 addr = offset_of_register(addr);
648 if (addr < 0) {
649 set_failure(®s, -EIO);
650 return -EIO;
651 }
652 tmp = get_stack_long(child, addr);
653 DBG(DBG_MEM, ("%d = reg 0x%lx=tmp\n",reg,tmp));
654 }
655 set_success(®s,tmp);
656 return 0;
657 }
658
659
660 case PTRACE_POKETEXT:
661 case PTRACE_POKEDATA: {
662 long res=write_long(child,addr,data);
663 if(res) {
664 set_failure(®s,res);
665 }
666 return res;
667 }
668
669 case PTRACE_POKEUSR:
670 {
671 long res;
672 addr= offset_of_register(addr);
673 if(addr < 0) {
674 set_failure(®s,-EIO);
675 return -EIO;
676 }
677 res=put_stack_long(child,addr,data);
678 if(res) {
679 set_failure(®s,res);
680 }
681 return res;
682 }
683
684 case PTRACE_SYSCALL:
685
686 case PTRACE_CONT: {
687 if ((unsigned long) data > NSIG) {
688 set_failure(®s,-EIO);
689 return -EIO;
690 }
691 if (request == PTRACE_SYSCALL)
692 child->flags |= PF_TRACESYS;
693 else
694 child->flags &= ~PF_TRACESYS;
695 child->exit_code = data;
696 child->state = TASK_RUNNING;
697 ptrace_cancel_bpt(child);
698 set_success(®s,data);
699 return 0;
700 }
701
702
703
704
705
706
707 case PTRACE_KILL: {
708 child->state = TASK_RUNNING;
709 child->exit_code = SIGKILL;
710 ptrace_cancel_bpt(child);
711 return 0;
712 }
713
714 case PTRACE_SINGLESTEP: {
715 if ((unsigned long) data > NSIG) {
716 set_failure(®s,-EIO);
717 return -EIO;
718 }
719 res = set_bpt(child);
720 if (res < 0) {
721 return res;
722 }
723 child->flags &= ~PF_TRACESYS;
724 child->state = TASK_RUNNING;
725 child->exit_code = data;
726
727 return 0;
728 }
729
730 case PTRACE_DETACH: {
731 if ((unsigned long) data > NSIG) {
732 set_failure(®s,-EIO);
733 return -EIO;
734 }
735 child->flags &= ~(PF_PTRACED|PF_TRACESYS);
736 child->state = TASK_RUNNING;
737 child->exit_code = data;
738 REMOVE_LINKS(child);
739 child->p_pptr = child->p_opptr;
740 SET_LINKS(child);
741
742 ptrace_cancel_bpt(child);
743 return 0;
744 }
745
746 default:
747 {
748 set_failure(®s,-EIO);
749 return -EIO;
750 }
751 }
752 }
753
754 asmlinkage void syscall_trace(void)
755 {
756 if ((current->flags & (PF_PTRACED|PF_TRACESYS))
757 != (PF_PTRACED|PF_TRACESYS))
758 return;
759 current->exit_code = SIGTRAP;
760 current->state = TASK_STOPPED;
761 notify_parent(current);
762 schedule();
763
764
765
766
767
768 if (current->exit_code)
769 current->signal |= (1 << (current->exit_code - 1));
770 current->exit_code = 0;
771 }