0001
0002
0003
0004
0005
0006 #include <linux/audit.h>
0007 #include <linux/ptrace.h>
0008 #include <linux/sched.h>
0009 #include <linux/uaccess.h>
0010 #include <asm/ptrace-abi.h>
0011
0012 void user_enable_single_step(struct task_struct *child)
0013 {
0014 set_tsk_thread_flag(child, TIF_SINGLESTEP);
0015 child->thread.singlestep_syscall = 0;
0016
0017 #ifdef SUBARCH_SET_SINGLESTEPPING
0018 SUBARCH_SET_SINGLESTEPPING(child, 1);
0019 #endif
0020 }
0021
0022 void user_disable_single_step(struct task_struct *child)
0023 {
0024 clear_tsk_thread_flag(child, TIF_SINGLESTEP);
0025 child->thread.singlestep_syscall = 0;
0026
0027 #ifdef SUBARCH_SET_SINGLESTEPPING
0028 SUBARCH_SET_SINGLESTEPPING(child, 0);
0029 #endif
0030 }
0031
0032
0033
0034
0035 void ptrace_disable(struct task_struct *child)
0036 {
0037 user_disable_single_step(child);
0038 }
0039
0040 extern int peek_user(struct task_struct * child, long addr, long data);
0041 extern int poke_user(struct task_struct * child, long addr, long data);
0042
0043 long arch_ptrace(struct task_struct *child, long request,
0044 unsigned long addr, unsigned long data)
0045 {
0046 int i, ret;
0047 unsigned long __user *p = (void __user *)data;
0048 void __user *vp = p;
0049
0050 switch (request) {
0051
0052 case PTRACE_PEEKUSR:
0053 ret = peek_user(child, addr, data);
0054 break;
0055
0056
0057 case PTRACE_POKEUSR:
0058 ret = poke_user(child, addr, data);
0059 break;
0060
0061 case PTRACE_SYSEMU:
0062 case PTRACE_SYSEMU_SINGLESTEP:
0063 ret = -EIO;
0064 break;
0065
0066 #ifdef PTRACE_GETREGS
0067 case PTRACE_GETREGS: {
0068 if (!access_ok(p, MAX_REG_OFFSET)) {
0069 ret = -EIO;
0070 break;
0071 }
0072 for ( i = 0; i < MAX_REG_OFFSET; i += sizeof(long) ) {
0073 __put_user(getreg(child, i), p);
0074 p++;
0075 }
0076 ret = 0;
0077 break;
0078 }
0079 #endif
0080 #ifdef PTRACE_SETREGS
0081 case PTRACE_SETREGS: {
0082 unsigned long tmp = 0;
0083 if (!access_ok(p, MAX_REG_OFFSET)) {
0084 ret = -EIO;
0085 break;
0086 }
0087 for ( i = 0; i < MAX_REG_OFFSET; i += sizeof(long) ) {
0088 __get_user(tmp, p);
0089 putreg(child, i, tmp);
0090 p++;
0091 }
0092 ret = 0;
0093 break;
0094 }
0095 #endif
0096 case PTRACE_GET_THREAD_AREA:
0097 ret = ptrace_get_thread_area(child, addr, vp);
0098 break;
0099
0100 case PTRACE_SET_THREAD_AREA:
0101 ret = ptrace_set_thread_area(child, addr, vp);
0102 break;
0103
0104 default:
0105 ret = ptrace_request(child, request, addr, data);
0106 if (ret == -EIO)
0107 ret = subarch_ptrace(child, request, addr, data);
0108 break;
0109 }
0110
0111 return ret;
0112 }
0113
0114 static void send_sigtrap(struct uml_pt_regs *regs, int error_code)
0115 {
0116
0117 force_sig_fault(SIGTRAP, TRAP_BRKPT,
0118
0119 UPT_IS_USER(regs) ? (void __user *) UPT_IP(regs) : NULL);
0120 }
0121
0122
0123
0124
0125
0126 int syscall_trace_enter(struct pt_regs *regs)
0127 {
0128 audit_syscall_entry(UPT_SYSCALL_NR(®s->regs),
0129 UPT_SYSCALL_ARG1(®s->regs),
0130 UPT_SYSCALL_ARG2(®s->regs),
0131 UPT_SYSCALL_ARG3(®s->regs),
0132 UPT_SYSCALL_ARG4(®s->regs));
0133
0134 if (!test_thread_flag(TIF_SYSCALL_TRACE))
0135 return 0;
0136
0137 return ptrace_report_syscall_entry(regs);
0138 }
0139
0140 void syscall_trace_leave(struct pt_regs *regs)
0141 {
0142 int ptraced = current->ptrace;
0143
0144 audit_syscall_exit(regs);
0145
0146
0147 if (test_thread_flag(TIF_SINGLESTEP))
0148 send_sigtrap(®s->regs, 0);
0149
0150 if (!test_thread_flag(TIF_SYSCALL_TRACE))
0151 return;
0152
0153 ptrace_report_syscall_exit(regs, 0);
0154
0155 if (ptraced & PT_PTRACED)
0156 set_thread_flag(TIF_SIGPENDING);
0157 }