1
2
3
4
5
6
7
8#include <linux/kernel.h>
9#include <linux/sched.h>
10#include <linux/mm.h>
11#include <linux/smp.h>
12#include <linux/errno.h>
13#include <linux/ptrace.h>
14#include <linux/user.h>
15#include <linux/security.h>
16#include <linux/audit.h>
17#include <linux/seccomp.h>
18#include <linux/signal.h>
19
20#include <asm/uaccess.h>
21#include <asm/pgtable.h>
22#include <asm/system.h>
23#include <asm/processor.h>
24#include <asm/i387.h>
25#include <asm/debugreg.h>
26#include <asm/ldt.h>
27#include <asm/desc.h>
28
29
30
31
32
33
34
35
36
37
38
39#define FLAG_MASK 0x00050dd5
40
41
42#define TRAP_FLAG 0x100
43
44
45
46
47#define EFL_OFFSET offsetof(struct pt_regs, eflags)
48
49static inline struct pt_regs *get_child_regs(struct task_struct *task)
50{
51 void *stack_top = (void *)task->thread.esp0;
52 return stack_top - sizeof(struct pt_regs);
53}
54
55
56
57
58
59
60
61static inline int get_stack_long(struct task_struct *task, int offset)
62{
63 unsigned char *stack;
64
65 stack = (unsigned char *)task->thread.esp0 - sizeof(struct pt_regs);
66 stack += offset;
67 return (*((int *)stack));
68}
69
70
71
72
73
74
75
76static inline int put_stack_long(struct task_struct *task, int offset,
77 unsigned long data)
78{
79 unsigned char * stack;
80
81 stack = (unsigned char *)task->thread.esp0 - sizeof(struct pt_regs);
82 stack += offset;
83 *(unsigned long *) stack = data;
84 return 0;
85}
86
87static int putreg(struct task_struct *child,
88 unsigned long regno, unsigned long value)
89{
90 switch (regno >> 2) {
91 case GS:
92 if (value && (value & 3) != 3)
93 return -EIO;
94 child->thread.gs = value;
95 return 0;
96 case DS:
97 case ES:
98 case FS:
99 if (value && (value & 3) != 3)
100 return -EIO;
101 value &= 0xffff;
102 break;
103 case SS:
104 case CS:
105 if ((value & 3) != 3)
106 return -EIO;
107 value &= 0xffff;
108 break;
109 case EFL:
110 value &= FLAG_MASK;
111 value |= get_stack_long(child, EFL_OFFSET) & ~FLAG_MASK;
112 break;
113 }
114 if (regno > FS*4)
115 regno -= 1*4;
116 put_stack_long(child, regno, value);
117 return 0;
118}
119
120static unsigned long getreg(struct task_struct *child,
121 unsigned long regno)
122{
123 unsigned long retval = ~0UL;
124
125 switch (regno >> 2) {
126 case GS:
127 retval = child->thread.gs;
128 break;
129 case DS:
130 case ES:
131 case FS:
132 case SS:
133 case CS:
134 retval = 0xffff;
135
136 default:
137 if (regno > FS*4)
138 regno -= 1*4;
139 retval &= get_stack_long(child, regno);
140 }
141 return retval;
142}
143
144#define LDT_SEGMENT 4
145
146static unsigned long convert_eip_to_linear(struct task_struct *child, struct pt_regs *regs)
147{
148 unsigned long addr, seg;
149
150 addr = regs->eip;
151 seg = regs->xcs & 0xffff;
152 if (regs->eflags & VM_MASK) {
153 addr = (addr & 0xffff) + (seg << 4);
154 return addr;
155 }
156
157
158
159
160
161
162
163 if (seg & LDT_SEGMENT) {
164 u32 *desc;
165 unsigned long base;
166
167 down(&child->mm->context.sem);
168 desc = child->mm->context.ldt + (seg & ~7);
169 base = (desc[0] >> 16) | ((desc[1] & 0xff) << 16) | (desc[1] & 0xff000000);
170
171
172 if (!((desc[1] >> 22) & 1))
173 addr &= 0xffff;
174 addr += base;
175 up(&child->mm->context.sem);
176 }
177 return addr;
178}
179
180static inline int is_setting_trap_flag(struct task_struct *child, struct pt_regs *regs)
181{
182 int i, copied;
183 unsigned char opcode[15];
184 unsigned long addr = convert_eip_to_linear(child, regs);
185
186 copied = access_process_vm(child, addr, opcode, sizeof(opcode), 0);
187 for (i = 0; i < copied; i++) {
188 switch (opcode[i]) {
189
190 case 0x9d: case 0xcf:
191 return 1;
192
193 case 0x66: case 0x67:
194 continue;
195
196 case 0x26: case 0x2e:
197 case 0x36: case 0x3e:
198 case 0x64: case 0x65:
199 case 0xf0: case 0xf2: case 0xf3:
200 continue;
201
202
203
204
205
206
207
208
209 case 0x9c:
210 default:
211 return 0;
212 }
213 }
214 return 0;
215}
216
217static void set_singlestep(struct task_struct *child)
218{
219 struct pt_regs *regs = get_child_regs(child);
220
221
222
223
224
225
226 set_tsk_thread_flag(child, TIF_SINGLESTEP);
227
228
229
230
231 if (regs->eflags & TRAP_FLAG)
232 return;
233
234
235 regs->eflags |= TRAP_FLAG;
236
237
238
239
240
241
242 if (is_setting_trap_flag(child, regs))
243 return;
244
245 child->ptrace |= PT_DTRACE;
246}
247
248static void clear_singlestep(struct task_struct *child)
249{
250
251 clear_tsk_thread_flag(child, TIF_SINGLESTEP);
252
253
254 if (child->ptrace & PT_DTRACE) {
255 struct pt_regs *regs = get_child_regs(child);
256 regs->eflags &= ~TRAP_FLAG;
257 child->ptrace &= ~PT_DTRACE;
258 }
259}
260
261
262
263
264
265
266void ptrace_disable(struct task_struct *child)
267{
268 clear_singlestep(child);
269 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
270 clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
271}
272
273
274
275
276static int
277ptrace_get_thread_area(struct task_struct *child,
278 int idx, struct user_desc __user *user_desc)
279{
280 struct user_desc info;
281 struct desc_struct *desc;
282
283
284
285
286
287#define GET_BASE(desc) ( \
288 (((desc)->a >> 16) & 0x0000ffff) | \
289 (((desc)->b << 16) & 0x00ff0000) | \
290 ( (desc)->b & 0xff000000) )
291
292#define GET_LIMIT(desc) ( \
293 ((desc)->a & 0x0ffff) | \
294 ((desc)->b & 0xf0000) )
295
296#define GET_32BIT(desc) (((desc)->b >> 22) & 1)
297#define GET_CONTENTS(desc) (((desc)->b >> 10) & 3)
298#define GET_WRITABLE(desc) (((desc)->b >> 9) & 1)
299#define GET_LIMIT_PAGES(desc) (((desc)->b >> 23) & 1)
300#define GET_PRESENT(desc) (((desc)->b >> 15) & 1)
301#define GET_USEABLE(desc) (((desc)->b >> 20) & 1)
302
303 if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
304 return -EINVAL;
305
306 desc = child->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
307
308 info.entry_number = idx;
309 info.base_addr = GET_BASE(desc);
310 info.limit = GET_LIMIT(desc);
311 info.seg_32bit = GET_32BIT(desc);
312 info.contents = GET_CONTENTS(desc);
313 info.read_exec_only = !GET_WRITABLE(desc);
314 info.limit_in_pages = GET_LIMIT_PAGES(desc);
315 info.seg_not_present = !GET_PRESENT(desc);
316 info.useable = GET_USEABLE(desc);
317
318 if (copy_to_user(user_desc, &info, sizeof(info)))
319 return -EFAULT;
320
321 return 0;
322}
323
324
325
326
327static int
328ptrace_set_thread_area(struct task_struct *child,
329 int idx, struct user_desc __user *user_desc)
330{
331 struct user_desc info;
332 struct desc_struct *desc;
333
334 if (copy_from_user(&info, user_desc, sizeof(info)))
335 return -EFAULT;
336
337 if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
338 return -EINVAL;
339
340 desc = child->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
341 if (LDT_empty(&info)) {
342 desc->a = 0;
343 desc->b = 0;
344 } else {
345 desc->a = LDT_entry_a(&info);
346 desc->b = LDT_entry_b(&info);
347 }
348
349 return 0;
350}
351
352long arch_ptrace(struct task_struct *child, long request, long addr, long data)
353{
354 struct user * dummy = NULL;
355 int i, ret;
356 unsigned long __user *datap = (unsigned long __user *)data;
357
358 switch (request) {
359
360 case PTRACE_PEEKTEXT:
361 case PTRACE_PEEKDATA: {
362 unsigned long tmp;
363 int copied;
364
365 copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
366 ret = -EIO;
367 if (copied != sizeof(tmp))
368 break;
369 ret = put_user(tmp, datap);
370 break;
371 }
372
373
374 case PTRACE_PEEKUSR: {
375 unsigned long tmp;
376
377 ret = -EIO;
378 if ((addr & 3) || addr < 0 ||
379 addr > sizeof(struct user) - 3)
380 break;
381
382 tmp = 0;
383 if(addr < FRAME_SIZE*sizeof(long))
384 tmp = getreg(child, addr);
385 if(addr >= (long) &dummy->u_debugreg[0] &&
386 addr <= (long) &dummy->u_debugreg[7]){
387 addr -= (long) &dummy->u_debugreg[0];
388 addr = addr >> 2;
389 tmp = child->thread.debugreg[addr];
390 }
391 ret = put_user(tmp, datap);
392 break;
393 }
394
395
396 case PTRACE_POKETEXT:
397 case PTRACE_POKEDATA:
398 ret = 0;
399 if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
400 break;
401 ret = -EIO;
402 break;
403
404 case PTRACE_POKEUSR:
405 ret = -EIO;
406 if ((addr & 3) || addr < 0 ||
407 addr > sizeof(struct user) - 3)
408 break;
409
410 if (addr < FRAME_SIZE*sizeof(long)) {
411 ret = putreg(child, addr, data);
412 break;
413 }
414
415
416
417
418
419 ret = -EIO;
420 if(addr >= (long) &dummy->u_debugreg[0] &&
421 addr <= (long) &dummy->u_debugreg[7]){
422
423 if(addr == (long) &dummy->u_debugreg[4]) break;
424 if(addr == (long) &dummy->u_debugreg[5]) break;
425 if(addr < (long) &dummy->u_debugreg[4] &&
426 ((unsigned long) data) >= TASK_SIZE-3) break;
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458 if(addr == (long) &dummy->u_debugreg[7]) {
459 data &= ~DR_CONTROL_RESERVED;
460 for(i=0; i<4; i++)
461 if ((0x5f54 >> ((data >> (16 + 4*i)) & 0xf)) & 1)
462 goto out_tsk;
463 if (data)
464 set_tsk_thread_flag(child, TIF_DEBUG);
465 else
466 clear_tsk_thread_flag(child, TIF_DEBUG);
467 }
468 addr -= (long) &dummy->u_debugreg;
469 addr = addr >> 2;
470 child->thread.debugreg[addr] = data;
471 ret = 0;
472 }
473 break;
474
475 case PTRACE_SYSEMU:
476 case PTRACE_SYSCALL:
477 case PTRACE_CONT:
478 ret = -EIO;
479 if (!valid_signal(data))
480 break;
481 if (request == PTRACE_SYSEMU) {
482 set_tsk_thread_flag(child, TIF_SYSCALL_EMU);
483 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
484 } else if (request == PTRACE_SYSCALL) {
485 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
486 clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
487 } else {
488 clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
489 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
490 }
491 child->exit_code = data;
492
493 clear_singlestep(child);
494 wake_up_process(child);
495 ret = 0;
496 break;
497
498
499
500
501
502
503 case PTRACE_KILL:
504 ret = 0;
505 if (child->exit_state == EXIT_ZOMBIE)
506 break;
507 child->exit_code = SIGKILL;
508
509 clear_singlestep(child);
510 wake_up_process(child);
511 break;
512
513 case PTRACE_SYSEMU_SINGLESTEP:
514 case PTRACE_SINGLESTEP:
515 ret = -EIO;
516 if (!valid_signal(data))
517 break;
518
519 if (request == PTRACE_SYSEMU_SINGLESTEP)
520 set_tsk_thread_flag(child, TIF_SYSCALL_EMU);
521 else
522 clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
523
524 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
525 set_singlestep(child);
526 child->exit_code = data;
527
528 wake_up_process(child);
529 ret = 0;
530 break;
531
532 case PTRACE_DETACH:
533
534 ret = ptrace_detach(child, data);
535 break;
536
537 case PTRACE_GETREGS: {
538 if (!access_ok(VERIFY_WRITE, datap, FRAME_SIZE*sizeof(long))) {
539 ret = -EIO;
540 break;
541 }
542 for ( i = 0; i < FRAME_SIZE*sizeof(long); i += sizeof(long) ) {
543 __put_user(getreg(child, i), datap);
544 datap++;
545 }
546 ret = 0;
547 break;
548 }
549
550 case PTRACE_SETREGS: {
551 unsigned long tmp;
552 if (!access_ok(VERIFY_READ, datap, FRAME_SIZE*sizeof(long))) {
553 ret = -EIO;
554 break;
555 }
556 for ( i = 0; i < FRAME_SIZE*sizeof(long); i += sizeof(long) ) {
557 __get_user(tmp, datap);
558 putreg(child, i, tmp);
559 datap++;
560 }
561 ret = 0;
562 break;
563 }
564
565 case PTRACE_GETFPREGS: {
566 if (!access_ok(VERIFY_WRITE, datap,
567 sizeof(struct user_i387_struct))) {
568 ret = -EIO;
569 break;
570 }
571 ret = 0;
572 if (!tsk_used_math(child))
573 init_fpu(child);
574 get_fpregs((struct user_i387_struct __user *)data, child);
575 break;
576 }
577
578 case PTRACE_SETFPREGS: {
579 if (!access_ok(VERIFY_READ, datap,
580 sizeof(struct user_i387_struct))) {
581 ret = -EIO;
582 break;
583 }
584 set_stopped_child_used_math(child);
585 set_fpregs(child, (struct user_i387_struct __user *)data);
586 ret = 0;
587 break;
588 }
589
590 case PTRACE_GETFPXREGS: {
591 if (!access_ok(VERIFY_WRITE, datap,
592 sizeof(struct user_fxsr_struct))) {
593 ret = -EIO;
594 break;
595 }
596 if (!tsk_used_math(child))
597 init_fpu(child);
598 ret = get_fpxregs((struct user_fxsr_struct __user *)data, child);
599 break;
600 }
601
602 case PTRACE_SETFPXREGS: {
603 if (!access_ok(VERIFY_READ, datap,
604 sizeof(struct user_fxsr_struct))) {
605 ret = -EIO;
606 break;
607 }
608 set_stopped_child_used_math(child);
609 ret = set_fpxregs(child, (struct user_fxsr_struct __user *)data);
610 break;
611 }
612
613 case PTRACE_GET_THREAD_AREA:
614 ret = ptrace_get_thread_area(child, addr,
615 (struct user_desc __user *) data);
616 break;
617
618 case PTRACE_SET_THREAD_AREA:
619 ret = ptrace_set_thread_area(child, addr,
620 (struct user_desc __user *) data);
621 break;
622
623 default:
624 ret = ptrace_request(child, request, addr, data);
625 break;
626 }
627 out_tsk:
628 return ret;
629}
630
631void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code)
632{
633 struct siginfo info;
634
635 tsk->thread.trap_no = 1;
636 tsk->thread.error_code = error_code;
637
638 memset(&info, 0, sizeof(info));
639 info.si_signo = SIGTRAP;
640 info.si_code = TRAP_BRKPT;
641
642
643 info.si_addr = user_mode_vm(regs) ? (void __user *) regs->eip : NULL;
644
645
646 force_sig_info(SIGTRAP, &info, tsk);
647}
648
649
650
651
652__attribute__((regparm(3)))
653int do_syscall_trace(struct pt_regs *regs, int entryexit)
654{
655 int is_sysemu = test_thread_flag(TIF_SYSCALL_EMU);
656
657
658
659
660 int is_singlestep = !is_sysemu && test_thread_flag(TIF_SINGLESTEP);
661 int ret = 0;
662
663
664 if (!entryexit)
665 secure_computing(regs->orig_eax);
666
667 if (unlikely(current->audit_context)) {
668 if (entryexit)
669 audit_syscall_exit(AUDITSC_RESULT(regs->eax),
670 regs->eax);
671
672
673
674
675
676
677
678
679
680
681 else if (is_singlestep)
682 goto out;
683 }
684
685 if (!(current->ptrace & PT_PTRACED))
686 goto out;
687
688
689
690
691 if (is_sysemu && entryexit)
692 return 0;
693
694
695 if (is_singlestep)
696 send_sigtrap(current, regs, 0);
697
698 if (!test_thread_flag(TIF_SYSCALL_TRACE) && !is_sysemu)
699 goto out;
700
701
702
703
704 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80:0));
705
706
707
708
709
710
711 if (current->exit_code) {
712 send_sig(current->exit_code, current, 1);
713 current->exit_code = 0;
714 }
715 ret = is_sysemu;
716out:
717 if (unlikely(current->audit_context) && !entryexit)
718 audit_syscall_entry(AUDIT_ARCH_I386, regs->orig_eax,
719 regs->ebx, regs->ecx, regs->edx, regs->esi);
720 if (ret == 0)
721 return 0;
722
723 regs->orig_eax = -1;
724 if (unlikely(current->audit_context))
725 audit_syscall_exit(AUDITSC_RESULT(regs->eax), regs->eax);
726 return 1;
727}
728