1 /* 2 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 3 * Licensed under the GPL 4 */ 5 6 #include "linux/audit.h" 7 #include "linux/ptrace.h" 8 #include "linux/sched.h" 9 #include "asm/uaccess.h" 10 #include "skas_ptrace.h" 11 12 13 14 void user_enable_single_step(struct task_struct *child) 15 { 16 child->ptrace |= PT_DTRACE; 17 child->thread.singlestep_syscall = 0; 18 19 #ifdef SUBARCH_SET_SINGLESTEPPING 20 SUBARCH_SET_SINGLESTEPPING(child, 1); 21 #endif 22 } 23 24 void user_disable_single_step(struct task_struct *child) 25 { 26 child->ptrace &= ~PT_DTRACE; 27 child->thread.singlestep_syscall = 0; 28 29 #ifdef SUBARCH_SET_SINGLESTEPPING 30 SUBARCH_SET_SINGLESTEPPING(child, 0); 31 #endif 32 } 33 34 /* 35 * Called by kernel/ptrace.c when detaching.. 36 */ 37 void ptrace_disable(struct task_struct *child) 38 { 39 user_disable_single_step(child); 40 } 41 42 extern int peek_user(struct task_struct * child, long addr, long data); 43 extern int poke_user(struct task_struct * child, long addr, long data); 44 45 long arch_ptrace(struct task_struct *child, long request, 46 unsigned long addr, unsigned long data) 47 { 48 int i, ret; 49 unsigned long __user *p = (void __user *)data; 50 void __user *vp = p; 51 52 switch (request) { 53 /* read the word at location addr in the USER area. */ 54 case PTRACE_PEEKUSR: 55 ret = peek_user(child, addr, data); 56 break; 57 58 /* write the word at location addr in the USER area */ 59 case PTRACE_POKEUSR: 60 ret = poke_user(child, addr, data); 61 break; 62 63 case PTRACE_SYSEMU: 64 case PTRACE_SYSEMU_SINGLESTEP: 65 ret = -EIO; 66 break; 67 68 #ifdef PTRACE_GETREGS 69 case PTRACE_GETREGS: { /* Get all gp regs from the child. */ 70 if (!access_ok(VERIFY_WRITE, p, MAX_REG_OFFSET)) { 71 ret = -EIO; 72 break; 73 } 74 for ( i = 0; i < MAX_REG_OFFSET; i += sizeof(long) ) { 75 __put_user(getreg(child, i), p); 76 p++; 77 } 78 ret = 0; 79 break; 80 } 81 #endif 82 #ifdef PTRACE_SETREGS 83 case PTRACE_SETREGS: { /* Set all gp regs in the child. */ 84 unsigned long tmp = 0; 85 if (!access_ok(VERIFY_READ, p, MAX_REG_OFFSET)) { 86 ret = -EIO; 87 break; 88 } 89 for ( i = 0; i < MAX_REG_OFFSET; i += sizeof(long) ) { 90 __get_user(tmp, p); 91 putreg(child, i, tmp); 92 p++; 93 } 94 ret = 0; 95 break; 96 } 97 #endif 98 case PTRACE_GET_THREAD_AREA: 99 ret = ptrace_get_thread_area(child, addr, vp); 100 break; 101 102 case PTRACE_SET_THREAD_AREA: 103 ret = ptrace_set_thread_area(child, addr, vp); 104 break; 105 106 case PTRACE_FAULTINFO: { 107 /* 108 * Take the info from thread->arch->faultinfo, 109 * but transfer max. sizeof(struct ptrace_faultinfo). 110 * On i386, ptrace_faultinfo is smaller! 111 */ 112 ret = copy_to_user(p, &child->thread.arch.faultinfo, 113 sizeof(struct ptrace_faultinfo)) ? 114 -EIO : 0; 115 break; 116 } 117 118 #ifdef PTRACE_LDT 119 case PTRACE_LDT: { 120 struct ptrace_ldt ldt; 121 122 if (copy_from_user(&ldt, p, sizeof(ldt))) { 123 ret = -EIO; 124 break; 125 } 126 127 /* 128 * This one is confusing, so just punt and return -EIO for 129 * now 130 */ 131 ret = -EIO; 132 break; 133 } 134 #endif 135 default: 136 ret = ptrace_request(child, request, addr, data); 137 if (ret == -EIO) 138 ret = subarch_ptrace(child, request, addr, data); 139 break; 140 } 141 142 return ret; 143 } 144 145 static void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs, 146 int error_code) 147 { 148 struct siginfo info; 149 150 memset(&info, 0, sizeof(info)); 151 info.si_signo = SIGTRAP; 152 info.si_code = TRAP_BRKPT; 153 154 /* User-mode eip? */ 155 info.si_addr = UPT_IS_USER(regs) ? (void __user *) UPT_IP(regs) : NULL; 156 157 /* Send us the fake SIGTRAP */ 158 force_sig_info(SIGTRAP, &info, tsk); 159 } 160 161 /* 162 * XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and 163 * PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check 164 */ 165 void syscall_trace(struct uml_pt_regs *regs, int entryexit) 166 { 167 int is_singlestep = (current->ptrace & PT_DTRACE) && entryexit; 168 int tracesysgood; 169 170 if (unlikely(current->audit_context)) { 171 if (!entryexit) 172 audit_syscall_entry(HOST_AUDIT_ARCH, 173 UPT_SYSCALL_NR(regs), 174 UPT_SYSCALL_ARG1(regs), 175 UPT_SYSCALL_ARG2(regs), 176 UPT_SYSCALL_ARG3(regs), 177 UPT_SYSCALL_ARG4(regs)); 178 else audit_syscall_exit(AUDITSC_RESULT(UPT_SYSCALL_RET(regs)), 179 UPT_SYSCALL_RET(regs)); 180 } 181 182 /* Fake a debug trap */ 183 if (is_singlestep) 184 send_sigtrap(current, regs, 0); 185 186 if (!test_thread_flag(TIF_SYSCALL_TRACE)) 187 return; 188 189 if (!(current->ptrace & PT_PTRACED)) 190 return; 191 192 /* 193 * the 0x80 provides a way for the tracing parent to distinguish 194 * between a syscall stop and SIGTRAP delivery 195 */ 196 tracesysgood = (current->ptrace & PT_TRACESYSGOOD); 197 ptrace_notify(SIGTRAP | (tracesysgood ? 0x80 : 0)); 198 199 if (entryexit) /* force do_signal() --> is_syscall() */ 200 set_thread_flag(TIF_SIGPENDING); 201 202 /* 203 * this isn't the same as continuing with a signal, but it will do 204 * for normal use. strace only continues with a signal if the 205 * stopping signal is not SIGTRAP. -brl 206 */ 207 if (current->exit_code) { 208 send_sig(current->exit_code, current, 1); 209 current->exit_code = 0; 210 } 211 } 212