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