1 /* 2 * SuperH process tracing 3 * 4 * Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka 5 * Copyright (C) 2002 - 2008 Paul Mundt 6 * 7 * Audit support by Yuichi Nakamura <ynakam@hitachisoft.jp> 8 * 9 * This file is subject to the terms and conditions of the GNU General Public 10 * License. See the file "COPYING" in the main directory of this archive 11 * for more details. 12 */ 13 #include <linux/kernel.h> 14 #include <linux/sched.h> 15 #include <linux/mm.h> 16 #include <linux/smp.h> 17 #include <linux/errno.h> 18 #include <linux/ptrace.h> 19 #include <linux/user.h> 20 #include <linux/slab.h> 21 #include <linux/security.h> 22 #include <linux/signal.h> 23 #include <linux/io.h> 24 #include <linux/audit.h> 25 #include <linux/seccomp.h> 26 #include <linux/tracehook.h> 27 #include <linux/elf.h> 28 #include <linux/regset.h> 29 #include <asm/uaccess.h> 30 #include <asm/pgtable.h> 31 #include <asm/system.h> 32 #include <asm/processor.h> 33 #include <asm/mmu_context.h> 34 #include <asm/syscalls.h> 35 #include <asm/fpu.h> 36 37 /* 38 * This routine will get a word off of the process kernel stack. 39 */ 40 static inline int get_stack_long(struct task_struct *task, int offset) 41 { 42 unsigned char *stack; 43 44 stack = (unsigned char *)task_pt_regs(task); 45 stack += offset; 46 return (*((int *)stack)); 47 } 48 49 /* 50 * This routine will put a word on the process kernel stack. 51 */ 52 static inline int put_stack_long(struct task_struct *task, int offset, 53 unsigned long data) 54 { 55 unsigned char *stack; 56 57 stack = (unsigned char *)task_pt_regs(task); 58 stack += offset; 59 *(unsigned long *) stack = data; 60 return 0; 61 } 62 63 void user_enable_single_step(struct task_struct *child) 64 { 65 /* Next scheduling will set up UBC */ 66 if (child->thread.ubc_pc == 0) 67 ubc_usercnt += 1; 68 69 child->thread.ubc_pc = get_stack_long(child, 70 offsetof(struct pt_regs, pc)); 71 72 set_tsk_thread_flag(child, TIF_SINGLESTEP); 73 } 74 75 void user_disable_single_step(struct task_struct *child) 76 { 77 clear_tsk_thread_flag(child, TIF_SINGLESTEP); 78 79 /* 80 * Ensure the UBC is not programmed at the next context switch. 81 * 82 * Normally this is not needed but there are sequences such as 83 * singlestep, signal delivery, and continue that leave the 84 * ubc_pc non-zero leading to spurious SIGTRAPs. 85 */ 86 if (child->thread.ubc_pc != 0) { 87 ubc_usercnt -= 1; 88 child->thread.ubc_pc = 0; 89 } 90 } 91 92 /* 93 * Called by kernel/ptrace.c when detaching.. 94 * 95 * Make sure single step bits etc are not set. 96 */ 97 void ptrace_disable(struct task_struct *child) 98 { 99 user_disable_single_step(child); 100 } 101 102 static int genregs_get(struct task_struct *target, 103 const struct user_regset *regset, 104 unsigned int pos, unsigned int count, 105 void *kbuf, void __user *ubuf) 106 { 107 const struct pt_regs *regs = task_pt_regs(target); 108 int ret; 109 110 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 111 regs->regs, 112 0, 16 * sizeof(unsigned long)); 113 if (!ret) 114 /* PC, PR, SR, GBR, MACH, MACL, TRA */ 115 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 116 ®s->pc, 117 offsetof(struct pt_regs, pc), 118 sizeof(struct pt_regs)); 119 if (!ret) 120 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 121 sizeof(struct pt_regs), -1); 122 123 return ret; 124 } 125 126 static int genregs_set(struct task_struct *target, 127 const struct user_regset *regset, 128 unsigned int pos, unsigned int count, 129 const void *kbuf, const void __user *ubuf) 130 { 131 struct pt_regs *regs = task_pt_regs(target); 132 int ret; 133 134 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 135 regs->regs, 136 0, 16 * sizeof(unsigned long)); 137 if (!ret && count > 0) 138 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 139 ®s->pc, 140 offsetof(struct pt_regs, pc), 141 sizeof(struct pt_regs)); 142 if (!ret) 143 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 144 sizeof(struct pt_regs), -1); 145 146 return ret; 147 } 148 149 #ifdef CONFIG_SH_FPU 150 int fpregs_get(struct task_struct *target, 151 const struct user_regset *regset, 152 unsigned int pos, unsigned int count, 153 void *kbuf, void __user *ubuf) 154 { 155 int ret; 156 157 ret = init_fpu(target); 158 if (ret) 159 return ret; 160 161 if ((boot_cpu_data.flags & CPU_HAS_FPU)) 162 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, 163 &target->thread.fpu.hard, 0, -1); 164 165 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, 166 &target->thread.fpu.soft, 0, -1); 167 } 168 169 static int fpregs_set(struct task_struct *target, 170 const struct user_regset *regset, 171 unsigned int pos, unsigned int count, 172 const void *kbuf, const void __user *ubuf) 173 { 174 int ret; 175 176 ret = init_fpu(target); 177 if (ret) 178 return ret; 179 180 set_stopped_child_used_math(target); 181 182 if ((boot_cpu_data.flags & CPU_HAS_FPU)) 183 return user_regset_copyin(&pos, &count, &kbuf, &ubuf, 184 &target->thread.fpu.hard, 0, -1); 185 186 return user_regset_copyin(&pos, &count, &kbuf, &ubuf, 187 &target->thread.fpu.soft, 0, -1); 188 } 189 190 static int fpregs_active(struct task_struct *target, 191 const struct user_regset *regset) 192 { 193 return tsk_used_math(target) ? regset->n : 0; 194 } 195 #endif 196 197 #ifdef CONFIG_SH_DSP 198 static int dspregs_get(struct task_struct *target, 199 const struct user_regset *regset, 200 unsigned int pos, unsigned int count, 201 void *kbuf, void __user *ubuf) 202 { 203 const struct pt_dspregs *regs = 204 (struct pt_dspregs *)&target->thread.dsp_status.dsp_regs; 205 int ret; 206 207 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, regs, 208 0, sizeof(struct pt_dspregs)); 209 if (!ret) 210 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 211 sizeof(struct pt_dspregs), -1); 212 213 return ret; 214 } 215 216 static int dspregs_set(struct task_struct *target, 217 const struct user_regset *regset, 218 unsigned int pos, unsigned int count, 219 const void *kbuf, const void __user *ubuf) 220 { 221 struct pt_dspregs *regs = 222 (struct pt_dspregs *)&target->thread.dsp_status.dsp_regs; 223 int ret; 224 225 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, regs, 226 0, sizeof(struct pt_dspregs)); 227 if (!ret) 228 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 229 sizeof(struct pt_dspregs), -1); 230 231 return ret; 232 } 233 234 static int dspregs_active(struct task_struct *target, 235 const struct user_regset *regset) 236 { 237 struct pt_regs *regs = task_pt_regs(target); 238 239 return regs->sr & SR_DSP ? regset->n : 0; 240 } 241 #endif 242 243 /* 244 * These are our native regset flavours. 245 */ 246 enum sh_regset { 247 REGSET_GENERAL, 248 #ifdef CONFIG_SH_FPU 249 REGSET_FPU, 250 #endif 251 #ifdef CONFIG_SH_DSP 252 REGSET_DSP, 253 #endif 254 }; 255 256 static const struct user_regset sh_regsets[] = { 257 /* 258 * Format is: 259 * R0 --> R15 260 * PC, PR, SR, GBR, MACH, MACL, TRA 261 */ 262 [REGSET_GENERAL] = { 263 .core_note_type = NT_PRSTATUS, 264 .n = ELF_NGREG, 265 .size = sizeof(long), 266 .align = sizeof(long), 267 .get = genregs_get, 268 .set = genregs_set, 269 }, 270 271 #ifdef CONFIG_SH_FPU 272 [REGSET_FPU] = { 273 .core_note_type = NT_PRFPREG, 274 .n = sizeof(struct user_fpu_struct) / sizeof(long), 275 .size = sizeof(long), 276 .align = sizeof(long), 277 .get = fpregs_get, 278 .set = fpregs_set, 279 .active = fpregs_active, 280 }, 281 #endif 282 283 #ifdef CONFIG_SH_DSP 284 [REGSET_DSP] = { 285 .n = sizeof(struct pt_dspregs) / sizeof(long), 286 .size = sizeof(long), 287 .align = sizeof(long), 288 .get = dspregs_get, 289 .set = dspregs_set, 290 .active = dspregs_active, 291 }, 292 #endif 293 }; 294 295 static const struct user_regset_view user_sh_native_view = { 296 .name = "sh", 297 .e_machine = EM_SH, 298 .regsets = sh_regsets, 299 .n = ARRAY_SIZE(sh_regsets), 300 }; 301 302 const struct user_regset_view *task_user_regset_view(struct task_struct *task) 303 { 304 return &user_sh_native_view; 305 } 306 307 long arch_ptrace(struct task_struct *child, long request, long addr, long data) 308 { 309 struct user * dummy = NULL; 310 unsigned long __user *datap = (unsigned long __user *)data; 311 int ret; 312 313 switch (request) { 314 /* read the word at location addr in the USER area. */ 315 case PTRACE_PEEKUSR: { 316 unsigned long tmp; 317 318 ret = -EIO; 319 if ((addr & 3) || addr < 0 || 320 addr > sizeof(struct user) - 3) 321 break; 322 323 if (addr < sizeof(struct pt_regs)) 324 tmp = get_stack_long(child, addr); 325 else if (addr >= (long) &dummy->fpu && 326 addr < (long) &dummy->u_fpvalid) { 327 if (!tsk_used_math(child)) { 328 if (addr == (long)&dummy->fpu.fpscr) 329 tmp = FPSCR_INIT; 330 else 331 tmp = 0; 332 } else 333 tmp = ((long *)&child->thread.fpu) 334 [(addr - (long)&dummy->fpu) >> 2]; 335 } else if (addr == (long) &dummy->u_fpvalid) 336 tmp = !!tsk_used_math(child); 337 else 338 tmp = 0; 339 ret = put_user(tmp, datap); 340 break; 341 } 342 343 case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ 344 ret = -EIO; 345 if ((addr & 3) || addr < 0 || 346 addr > sizeof(struct user) - 3) 347 break; 348 349 if (addr < sizeof(struct pt_regs)) 350 ret = put_stack_long(child, addr, data); 351 else if (addr >= (long) &dummy->fpu && 352 addr < (long) &dummy->u_fpvalid) { 353 set_stopped_child_used_math(child); 354 ((long *)&child->thread.fpu) 355 [(addr - (long)&dummy->fpu) >> 2] = data; 356 ret = 0; 357 } else if (addr == (long) &dummy->u_fpvalid) { 358 conditional_stopped_child_used_math(data, child); 359 ret = 0; 360 } 361 break; 362 363 case PTRACE_GETREGS: 364 return copy_regset_to_user(child, &user_sh_native_view, 365 REGSET_GENERAL, 366 0, sizeof(struct pt_regs), 367 (void __user *)data); 368 case PTRACE_SETREGS: 369 return copy_regset_from_user(child, &user_sh_native_view, 370 REGSET_GENERAL, 371 0, sizeof(struct pt_regs), 372 (const void __user *)data); 373 #ifdef CONFIG_SH_FPU 374 case PTRACE_GETFPREGS: 375 return copy_regset_to_user(child, &user_sh_native_view, 376 REGSET_FPU, 377 0, sizeof(struct user_fpu_struct), 378 (void __user *)data); 379 case PTRACE_SETFPREGS: 380 return copy_regset_from_user(child, &user_sh_native_view, 381 REGSET_FPU, 382 0, sizeof(struct user_fpu_struct), 383 (const void __user *)data); 384 #endif 385 #ifdef CONFIG_SH_DSP 386 case PTRACE_GETDSPREGS: 387 return copy_regset_to_user(child, &user_sh_native_view, 388 REGSET_DSP, 389 0, sizeof(struct pt_dspregs), 390 (void __user *)data); 391 case PTRACE_SETDSPREGS: 392 return copy_regset_from_user(child, &user_sh_native_view, 393 REGSET_DSP, 394 0, sizeof(struct pt_dspregs), 395 (const void __user *)data); 396 #endif 397 #ifdef CONFIG_BINFMT_ELF_FDPIC 398 case PTRACE_GETFDPIC: { 399 unsigned long tmp = 0; 400 401 switch (addr) { 402 case PTRACE_GETFDPIC_EXEC: 403 tmp = child->mm->context.exec_fdpic_loadmap; 404 break; 405 case PTRACE_GETFDPIC_INTERP: 406 tmp = child->mm->context.interp_fdpic_loadmap; 407 break; 408 default: 409 break; 410 } 411 412 ret = 0; 413 if (put_user(tmp, datap)) { 414 ret = -EFAULT; 415 break; 416 } 417 break; 418 } 419 #endif 420 default: 421 ret = ptrace_request(child, request, addr, data); 422 break; 423 } 424 425 return ret; 426 } 427 428 static inline int audit_arch(void) 429 { 430 int arch = EM_SH; 431 432 #ifdef CONFIG_CPU_LITTLE_ENDIAN 433 arch |= __AUDIT_ARCH_LE; 434 #endif 435 436 return arch; 437 } 438 439 asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) 440 { 441 long ret = 0; 442 443 secure_computing(regs->regs[0]); 444 445 if (test_thread_flag(TIF_SYSCALL_TRACE) && 446 tracehook_report_syscall_entry(regs)) 447 /* 448 * Tracing decided this syscall should not happen. 449 * We'll return a bogus call number to get an ENOSYS 450 * error, but leave the original number in regs->regs[0]. 451 */ 452 ret = -1L; 453 454 if (unlikely(current->audit_context)) 455 audit_syscall_entry(audit_arch(), regs->regs[3], 456 regs->regs[4], regs->regs[5], 457 regs->regs[6], regs->regs[7]); 458 459 return ret ?: regs->regs[0]; 460 } 461 462 asmlinkage void do_syscall_trace_leave(struct pt_regs *regs) 463 { 464 int step; 465 466 if (unlikely(current->audit_context)) 467 audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]), 468 regs->regs[0]); 469 470 step = test_thread_flag(TIF_SINGLESTEP); 471 if (step || test_thread_flag(TIF_SYSCALL_TRACE)) 472 tracehook_report_syscall_exit(regs, step); 473 } 474