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 task_struct * tsk,
164 struct vm_area_struct * vma, unsigned long addr)
165 {
166 pgd_t * pgdir;
167 pmd_t * pgmiddle;
168 pte_t * pgtable;
169 unsigned long page;
170
171 DBG(DBG_MEM_ALL, ("getting long at 0x%lx\n", addr));
172 repeat:
173 pgdir = pgd_offset(vma->vm_mm, addr);
174 if (pgd_none(*pgdir)) {
175 do_no_page(tsk, vma, addr, 0);
176 goto repeat;
177 }
178 if (pgd_bad(*pgdir)) {
179 printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
180 pgd_clear(pgdir);
181 return 0;
182 }
183 pgmiddle = pmd_offset(pgdir, addr);
184 if (pmd_none(*pgmiddle)) {
185 do_no_page(tsk, vma, addr, 0);
186 goto repeat;
187 }
188 if (pmd_bad(*pgmiddle)) {
189 printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
190 pmd_clear(pgmiddle);
191 return 0;
192 }
193 pgtable = pte_offset(pgmiddle, addr);
194 if (!pte_present(*pgtable)) {
195 do_no_page(tsk, vma, addr, 0);
196 goto repeat;
197 }
198 page = pte_page(*pgtable);
199
200 if (page >= high_memory)
201 return 0;
202 page += addr & ~PAGE_MASK;
203 return *(unsigned long *) page;
204 }
205
206
207
208
209
210
211
212
213
214
215 static void put_long(struct task_struct * tsk, struct vm_area_struct * vma,
216 unsigned long addr, unsigned long data)
217 {
218 pgd_t *pgdir;
219 pmd_t *pgmiddle;
220 pte_t *pgtable;
221 unsigned long page;
222
223 repeat:
224 pgdir = pgd_offset(vma->vm_mm, addr);
225 if (!pgd_present(*pgdir)) {
226 do_no_page(tsk, vma, addr, 1);
227 goto repeat;
228 }
229 if (pgd_bad(*pgdir)) {
230 printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
231 pgd_clear(pgdir);
232 return;
233 }
234 pgmiddle = pmd_offset(pgdir, addr);
235 if (pmd_none(*pgmiddle)) {
236 do_no_page(tsk, vma, addr, 1);
237 goto repeat;
238 }
239 if (pmd_bad(*pgmiddle)) {
240 printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
241 pmd_clear(pgmiddle);
242 return;
243 }
244 pgtable = pte_offset(pgmiddle, addr);
245 if (!pte_present(*pgtable)) {
246 do_no_page(tsk, vma, addr, 1);
247 goto repeat;
248 }
249 page = pte_page(*pgtable);
250 if (!pte_write(*pgtable)) {
251 do_wp_page(tsk, vma, addr, 1);
252 goto repeat;
253 }
254
255 if (page < high_memory)
256 *(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
257
258
259 set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
260 flush_tlb();
261 }
262
263 static struct vm_area_struct * find_extend_vma(struct task_struct * tsk,
264 unsigned long addr)
265 {
266 struct vm_area_struct * vma;
267
268 addr &= PAGE_MASK;
269 vma = find_vma(tsk,addr);
270 if (!vma)
271 return NULL;
272 if (vma->vm_start <= addr)
273 return vma;
274 if (!(vma->vm_flags & VM_GROWSDOWN))
275 return NULL;
276 if (vma->vm_end - addr > tsk->rlim[RLIMIT_STACK].rlim_cur)
277 return NULL;
278 vma->vm_offset -= vma->vm_start - addr;
279 vma->vm_start = addr;
280 return vma;
281 }
282
283
284
285
286
287 static int read_long(struct task_struct * tsk, unsigned long addr,
288 unsigned long * result)
289 {
290 struct vm_area_struct * vma = find_extend_vma(tsk, addr);
291
292 DBG(DBG_MEM_ALL, ("in read_long\n"));
293 if (!vma) {
294 printk("Unable to find vma for addr 0x%lx\n",addr);
295 return -EIO;
296 }
297 if ((addr & ~PAGE_MASK) > (PAGE_SIZE - sizeof(long))) {
298 struct vm_area_struct * vma_high = vma;
299 unsigned long low, align;
300
301 if (addr + sizeof(long) >= vma->vm_end) {
302 vma_high = vma->vm_next;
303 if (!vma_high || vma_high->vm_start != vma->vm_end)
304 return -EIO;
305 }
306 align = addr & (sizeof(long) - 1);
307 addr -= align;
308 low = get_long(tsk, vma, addr);
309 if (align) {
310 unsigned long high;
311
312 high = get_long(tsk, vma_high, addr + sizeof(long));
313 low >>= align * 8;
314 low |= high << (64 - align * 8);
315 }
316 *result = low;
317 } else {
318 long l = get_long(tsk, vma, addr);
319
320 DBG(DBG_MEM_ALL, ("value is 0x%lx\n", l));
321 *result = l;
322 }
323 return 0;
324 }
325
326
327
328
329
330 static int write_long(struct task_struct * tsk, unsigned long addr,
331 unsigned long data)
332 {
333 struct vm_area_struct * vma = find_extend_vma(tsk, addr);
334
335 if (!vma)
336 return -EIO;
337 if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) {
338 unsigned long low, high, align;
339 struct vm_area_struct * vma_high = vma;
340
341 if (addr + sizeof(long) >= vma->vm_end) {
342 vma_high = vma->vm_next;
343 if (!vma_high || vma_high->vm_start != vma->vm_end)
344 return -EIO;
345 }
346 align = addr & (sizeof(long) - 1);
347 addr -= align;
348 low = get_long(tsk, vma, addr);
349 high = get_long(tsk, vma_high, addr + sizeof(long));
350 low &= ~0UL >> (64 - align * 8);
351 high &= ~0UL << (align * 8);
352 low |= data << (align * 8);
353 high |= data >> (64 - align * 8);
354 put_long(tsk, vma, addr, low);
355 put_long(tsk, vma_high, addr + sizeof(long), high);
356 } else
357 put_long(tsk, vma, addr, data);
358 return 0;
359 }
360
361
362
363
364 static int read_int(struct task_struct * tsk, unsigned long addr,
365 unsigned int *data)
366 {
367 unsigned long l, align;
368 int res;
369
370 align = addr & 0x7;
371 addr &= ~0x7;
372
373 res = read_long(tsk, addr, &l);
374 if (res < 0)
375 return res;
376
377 if (align == 0) {
378 *data = l;
379 } else {
380 *data = l >> 32;
381 }
382 return 0;
383 }
384
385
386
387
388
389
390
391 static int write_int(struct task_struct * tsk, unsigned long addr,
392 unsigned int data)
393 {
394 unsigned long l, align;
395 int res;
396
397 align = addr & 0x7;
398 addr &= ~0x7;
399
400 res = read_long(tsk, addr, &l);
401 if (res < 0)
402 return res;
403
404 if (align == 0) {
405 l = (l & 0xffffffff00000000UL) | ((unsigned long) data << 0);
406 } else {
407 l = (l & 0x00000000ffffffffUL) | ((unsigned long) data << 32);
408 }
409 return write_long(tsk, addr, l);
410 }
411
412
413
414
415 int ptrace_set_bpt(struct task_struct * child)
416 {
417 int displ, i, res, reg_b, nsaved = 0;
418 u32 insn, op_code;
419 unsigned long pc;
420
421 pc = get_reg(child, REG_PC);
422 res = read_int(child, pc, &insn);
423 if (res < 0)
424 return res;
425
426 op_code = insn >> 26;
427 if (op_code >= 0x30) {
428
429
430
431
432
433
434
435
436 displ = ((s32)(insn << 11)) >> 9;
437 child->debugreg[nsaved++] = pc + 4;
438 if (displ)
439 child->debugreg[nsaved++] = pc + 4 + displ;
440 DBG(DBG_BPT, ("execing branch\n"));
441 } else if (op_code == 0x1a) {
442 reg_b = (insn >> 16) & 0x1f;
443 child->debugreg[nsaved++] = get_reg(child, reg_b);
444 DBG(DBG_BPT, ("execing jump\n"));
445 } else {
446 child->debugreg[nsaved++] = pc + 4;
447 DBG(DBG_BPT, ("execing normal insn\n"));
448 }
449
450
451 for (i = 0; i < nsaved; ++i) {
452 res = read_int(child, child->debugreg[i], &insn);
453 if (res < 0)
454 return res;
455 child->debugreg[i + 2] = insn;
456 DBG(DBG_BPT, (" -> next_pc=%lx\n", child->debugreg[i]));
457 res = write_int(child, child->debugreg[i], BREAKINST);
458 if (res < 0)
459 return res;
460 }
461 child->debugreg[4] = nsaved;
462 return 0;
463 }
464
465
466
467
468
469 int ptrace_cancel_bpt(struct task_struct * child)
470 {
471 int i, nsaved = child->debugreg[4];
472
473 child->debugreg[4] = 0;
474
475 if (nsaved > 2) {
476 printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
477 nsaved = 2;
478 }
479
480 for (i = 0; i < nsaved; ++i) {
481 write_int(child, child->debugreg[i], child->debugreg[i + 2]);
482 }
483 return (nsaved != 0);
484 }
485
486 asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
487 int a4, int a5, struct pt_regs regs)
488 {
489 struct task_struct *child;
490 struct user * dummy;
491
492 dummy = NULL;
493
494 DBG(DBG_MEM, ("request=%ld pid=%ld addr=0x%lx data=0x%lx\n",
495 request, pid, addr, data));
496 if (request == PTRACE_TRACEME) {
497
498 if (current->flags & PF_PTRACED)
499 return -EPERM;
500
501 current->flags |= PF_PTRACED;
502 return 0;
503 }
504 if (pid == 1)
505 return -EPERM;
506 if (!(child = get_task(pid)))
507 return -ESRCH;
508 if (request == PTRACE_ATTACH) {
509 if (child == current)
510 return -EPERM;
511 if ((!child->dumpable ||
512 (current->uid != child->euid) ||
513 (current->uid != child->suid) ||
514 (current->uid != child->uid) ||
515 (current->gid != child->egid) ||
516 (current->gid != child->sgid) ||
517 (current->gid != child->gid)) && !suser())
518 return -EPERM;
519
520 if (child->flags & PF_PTRACED)
521 return -EPERM;
522 child->flags |= PF_PTRACED;
523 if (child->p_pptr != current) {
524 REMOVE_LINKS(child);
525 child->p_pptr = current;
526 SET_LINKS(child);
527 }
528 send_sig(SIGSTOP, child, 1);
529 return 0;
530 }
531 if (!(child->flags & PF_PTRACED)) {
532 DBG(DBG_MEM, ("child not traced\n"));
533 return -ESRCH;
534 }
535 if (child->state != TASK_STOPPED) {
536 DBG(DBG_MEM, ("child process not stopped\n"));
537 if (request != PTRACE_KILL)
538 return -ESRCH;
539 }
540 if (child->p_pptr != current) {
541 DBG(DBG_MEM, ("child not parent of this process\n"));
542 return -ESRCH;
543 }
544
545 switch (request) {
546
547 case PTRACE_PEEKTEXT:
548 case PTRACE_PEEKDATA: {
549 unsigned long tmp;
550 int res;
551
552 res = read_long(child, addr, &tmp);
553 DBG(DBG_MEM, ("peek %#lx->%#lx\n", addr, tmp));
554 if (res < 0)
555 return res;
556 regs.r0 = 0;
557 return tmp;
558 }
559
560
561 case PTRACE_PEEKUSR:
562 regs.r0 = 0;
563 DBG(DBG_MEM, ("peek $%ld=%#lx\n", addr, regs.r0));
564 return get_reg(child, addr);
565
566
567 case PTRACE_POKETEXT:
568 case PTRACE_POKEDATA:
569 DBG(DBG_MEM, ("poke %#lx<-%#lx\n", addr, data));
570 return write_long(child, addr, data);
571
572 case PTRACE_POKEUSR:
573 DBG(DBG_MEM, ("poke $%ld<-%#lx\n", addr, data));
574 return put_reg(child, addr, data);
575
576 case PTRACE_SYSCALL:
577
578 case PTRACE_CONT: {
579 if ((unsigned long) data > NSIG)
580 return -EIO;
581 if (request == PTRACE_SYSCALL)
582 child->flags |= PF_TRACESYS;
583 else
584 child->flags &= ~PF_TRACESYS;
585 child->exit_code = data;
586 wake_up_process(child);
587
588 ptrace_cancel_bpt(child);
589 return data;
590 }
591
592
593
594
595
596
597 case PTRACE_KILL: {
598 if (child->state != TASK_ZOMBIE) {
599 wake_up_process(child);
600 child->exit_code = SIGKILL;
601 }
602
603 ptrace_cancel_bpt(child);
604 return 0;
605 }
606
607 case PTRACE_SINGLESTEP: {
608 if ((unsigned long) data > NSIG)
609 return -EIO;
610 child->debugreg[4] = -1;
611 child->flags &= ~PF_TRACESYS;
612 wake_up_process(child);
613 child->exit_code = data;
614
615 return 0;
616 }
617
618 case PTRACE_DETACH: {
619 if ((unsigned long) data > NSIG)
620 return -EIO;
621 child->flags &= ~(PF_PTRACED|PF_TRACESYS);
622 wake_up_process(child);
623 child->exit_code = data;
624 REMOVE_LINKS(child);
625 child->p_pptr = child->p_opptr;
626 SET_LINKS(child);
627
628 ptrace_cancel_bpt(child);
629 return 0;
630 }
631
632 default:
633 return -EIO;
634 }
635 }
636
637 asmlinkage void syscall_trace(void)
638 {
639 if ((current->flags & (PF_PTRACED|PF_TRACESYS))
640 != (PF_PTRACED|PF_TRACESYS))
641 return;
642 current->exit_code = SIGTRAP;
643 current->state = TASK_STOPPED;
644 notify_parent(current);
645 schedule();
646
647
648
649
650
651 if (current->exit_code)
652 current->signal |= (1 << (current->exit_code - 1));
653 current->exit_code = 0;
654 }