1 /* 2 * Based on arch/arm/kernel/ptrace.c 3 * 4 * By Ross Biro 1/23/92 5 * edited by Linus Torvalds 6 * ARM modifications Copyright (C) 2000 Russell King 7 * Copyright (C) 2012 ARM Ltd. 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 20 */ 21 22 #include <linux/audit.h> 23 #include <linux/compat.h> 24 #include <linux/kernel.h> 25 #include <linux/sched.h> 26 #include <linux/mm.h> 27 #include <linux/smp.h> 28 #include <linux/ptrace.h> 29 #include <linux/user.h> 30 #include <linux/security.h> 31 #include <linux/init.h> 32 #include <linux/signal.h> 33 #include <linux/uaccess.h> 34 #include <linux/perf_event.h> 35 #include <linux/hw_breakpoint.h> 36 #include <linux/regset.h> 37 #include <linux/tracehook.h> 38 #include <linux/elf.h> 39 40 #include <asm/compat.h> 41 #include <asm/debug-monitors.h> 42 #include <asm/pgtable.h> 43 #include <asm/syscall.h> 44 #include <asm/traps.h> 45 #include <asm/system_misc.h> 46 47 #define CREATE_TRACE_POINTS 48 #include <trace/events/syscalls.h> 49 50 /* 51 * TODO: does not yet catch signals sent when the child dies. 52 * in exit.c or in signal.c. 53 */ 54 55 /* 56 * Called by kernel/ptrace.c when detaching.. 57 */ 58 void ptrace_disable(struct task_struct *child) 59 { 60 } 61 62 #ifdef CONFIG_HAVE_HW_BREAKPOINT 63 /* 64 * Handle hitting a HW-breakpoint. 65 */ 66 static void ptrace_hbptriggered(struct perf_event *bp, 67 struct perf_sample_data *data, 68 struct pt_regs *regs) 69 { 70 struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp); 71 siginfo_t info = { 72 .si_signo = SIGTRAP, 73 .si_errno = 0, 74 .si_code = TRAP_HWBKPT, 75 .si_addr = (void __user *)(bkpt->trigger), 76 }; 77 78 #ifdef CONFIG_COMPAT 79 int i; 80 81 if (!is_compat_task()) 82 goto send_sig; 83 84 for (i = 0; i < ARM_MAX_BRP; ++i) { 85 if (current->thread.debug.hbp_break[i] == bp) { 86 info.si_errno = (i << 1) + 1; 87 break; 88 } 89 } 90 for (i = ARM_MAX_BRP; i < ARM_MAX_HBP_SLOTS && !bp; ++i) { 91 if (current->thread.debug.hbp_watch[i] == bp) { 92 info.si_errno = -((i << 1) + 1); 93 break; 94 } 95 } 96 97 send_sig: 98 #endif 99 force_sig_info(SIGTRAP, &info, current); 100 } 101 102 /* 103 * Unregister breakpoints from this task and reset the pointers in 104 * the thread_struct. 105 */ 106 void flush_ptrace_hw_breakpoint(struct task_struct *tsk) 107 { 108 int i; 109 struct thread_struct *t = &tsk->thread; 110 111 for (i = 0; i < ARM_MAX_BRP; i++) { 112 if (t->debug.hbp_break[i]) { 113 unregister_hw_breakpoint(t->debug.hbp_break[i]); 114 t->debug.hbp_break[i] = NULL; 115 } 116 } 117 118 for (i = 0; i < ARM_MAX_WRP; i++) { 119 if (t->debug.hbp_watch[i]) { 120 unregister_hw_breakpoint(t->debug.hbp_watch[i]); 121 t->debug.hbp_watch[i] = NULL; 122 } 123 } 124 } 125 126 void ptrace_hw_copy_thread(struct task_struct *tsk) 127 { 128 memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); 129 } 130 131 static struct perf_event *ptrace_hbp_get_event(unsigned int note_type, 132 struct task_struct *tsk, 133 unsigned long idx) 134 { 135 struct perf_event *bp = ERR_PTR(-EINVAL); 136 137 switch (note_type) { 138 case NT_ARM_HW_BREAK: 139 if (idx < ARM_MAX_BRP) 140 bp = tsk->thread.debug.hbp_break[idx]; 141 break; 142 case NT_ARM_HW_WATCH: 143 if (idx < ARM_MAX_WRP) 144 bp = tsk->thread.debug.hbp_watch[idx]; 145 break; 146 } 147 148 return bp; 149 } 150 151 static int ptrace_hbp_set_event(unsigned int note_type, 152 struct task_struct *tsk, 153 unsigned long idx, 154 struct perf_event *bp) 155 { 156 int err = -EINVAL; 157 158 switch (note_type) { 159 case NT_ARM_HW_BREAK: 160 if (idx < ARM_MAX_BRP) { 161 tsk->thread.debug.hbp_break[idx] = bp; 162 err = 0; 163 } 164 break; 165 case NT_ARM_HW_WATCH: 166 if (idx < ARM_MAX_WRP) { 167 tsk->thread.debug.hbp_watch[idx] = bp; 168 err = 0; 169 } 170 break; 171 } 172 173 return err; 174 } 175 176 static struct perf_event *ptrace_hbp_create(unsigned int note_type, 177 struct task_struct *tsk, 178 unsigned long idx) 179 { 180 struct perf_event *bp; 181 struct perf_event_attr attr; 182 int err, type; 183 184 switch (note_type) { 185 case NT_ARM_HW_BREAK: 186 type = HW_BREAKPOINT_X; 187 break; 188 case NT_ARM_HW_WATCH: 189 type = HW_BREAKPOINT_RW; 190 break; 191 default: 192 return ERR_PTR(-EINVAL); 193 } 194 195 ptrace_breakpoint_init(&attr); 196 197 /* 198 * Initialise fields to sane defaults 199 * (i.e. values that will pass validation). 200 */ 201 attr.bp_addr = 0; 202 attr.bp_len = HW_BREAKPOINT_LEN_4; 203 attr.bp_type = type; 204 attr.disabled = 1; 205 206 bp = register_user_hw_breakpoint(&attr, ptrace_hbptriggered, NULL, tsk); 207 if (IS_ERR(bp)) 208 return bp; 209 210 err = ptrace_hbp_set_event(note_type, tsk, idx, bp); 211 if (err) 212 return ERR_PTR(err); 213 214 return bp; 215 } 216 217 static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type, 218 struct arch_hw_breakpoint_ctrl ctrl, 219 struct perf_event_attr *attr) 220 { 221 int err, len, type, disabled = !ctrl.enabled; 222 223 attr->disabled = disabled; 224 if (disabled) 225 return 0; 226 227 err = arch_bp_generic_fields(ctrl, &len, &type); 228 if (err) 229 return err; 230 231 switch (note_type) { 232 case NT_ARM_HW_BREAK: 233 if ((type & HW_BREAKPOINT_X) != type) 234 return -EINVAL; 235 break; 236 case NT_ARM_HW_WATCH: 237 if ((type & HW_BREAKPOINT_RW) != type) 238 return -EINVAL; 239 break; 240 default: 241 return -EINVAL; 242 } 243 244 attr->bp_len = len; 245 attr->bp_type = type; 246 247 return 0; 248 } 249 250 static int ptrace_hbp_get_resource_info(unsigned int note_type, u32 *info) 251 { 252 u8 num; 253 u32 reg = 0; 254 255 switch (note_type) { 256 case NT_ARM_HW_BREAK: 257 num = hw_breakpoint_slots(TYPE_INST); 258 break; 259 case NT_ARM_HW_WATCH: 260 num = hw_breakpoint_slots(TYPE_DATA); 261 break; 262 default: 263 return -EINVAL; 264 } 265 266 reg |= debug_monitors_arch(); 267 reg <<= 8; 268 reg |= num; 269 270 *info = reg; 271 return 0; 272 } 273 274 static int ptrace_hbp_get_ctrl(unsigned int note_type, 275 struct task_struct *tsk, 276 unsigned long idx, 277 u32 *ctrl) 278 { 279 struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx); 280 281 if (IS_ERR(bp)) 282 return PTR_ERR(bp); 283 284 *ctrl = bp ? encode_ctrl_reg(counter_arch_bp(bp)->ctrl) : 0; 285 return 0; 286 } 287 288 static int ptrace_hbp_get_addr(unsigned int note_type, 289 struct task_struct *tsk, 290 unsigned long idx, 291 u64 *addr) 292 { 293 struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx); 294 295 if (IS_ERR(bp)) 296 return PTR_ERR(bp); 297 298 *addr = bp ? bp->attr.bp_addr : 0; 299 return 0; 300 } 301 302 static struct perf_event *ptrace_hbp_get_initialised_bp(unsigned int note_type, 303 struct task_struct *tsk, 304 unsigned long idx) 305 { 306 struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx); 307 308 if (!bp) 309 bp = ptrace_hbp_create(note_type, tsk, idx); 310 311 return bp; 312 } 313 314 static int ptrace_hbp_set_ctrl(unsigned int note_type, 315 struct task_struct *tsk, 316 unsigned long idx, 317 u32 uctrl) 318 { 319 int err; 320 struct perf_event *bp; 321 struct perf_event_attr attr; 322 struct arch_hw_breakpoint_ctrl ctrl; 323 324 bp = ptrace_hbp_get_initialised_bp(note_type, tsk, idx); 325 if (IS_ERR(bp)) { 326 err = PTR_ERR(bp); 327 return err; 328 } 329 330 attr = bp->attr; 331 decode_ctrl_reg(uctrl, &ctrl); 332 err = ptrace_hbp_fill_attr_ctrl(note_type, ctrl, &attr); 333 if (err) 334 return err; 335 336 return modify_user_hw_breakpoint(bp, &attr); 337 } 338 339 static int ptrace_hbp_set_addr(unsigned int note_type, 340 struct task_struct *tsk, 341 unsigned long idx, 342 u64 addr) 343 { 344 int err; 345 struct perf_event *bp; 346 struct perf_event_attr attr; 347 348 bp = ptrace_hbp_get_initialised_bp(note_type, tsk, idx); 349 if (IS_ERR(bp)) { 350 err = PTR_ERR(bp); 351 return err; 352 } 353 354 attr = bp->attr; 355 attr.bp_addr = addr; 356 err = modify_user_hw_breakpoint(bp, &attr); 357 return err; 358 } 359 360 #define PTRACE_HBP_ADDR_SZ sizeof(u64) 361 #define PTRACE_HBP_CTRL_SZ sizeof(u32) 362 #define PTRACE_HBP_PAD_SZ sizeof(u32) 363 364 static int hw_break_get(struct task_struct *target, 365 const struct user_regset *regset, 366 unsigned int pos, unsigned int count, 367 void *kbuf, void __user *ubuf) 368 { 369 unsigned int note_type = regset->core_note_type; 370 int ret, idx = 0, offset, limit; 371 u32 info, ctrl; 372 u64 addr; 373 374 /* Resource info */ 375 ret = ptrace_hbp_get_resource_info(note_type, &info); 376 if (ret) 377 return ret; 378 379 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &info, 0, 380 sizeof(info)); 381 if (ret) 382 return ret; 383 384 /* Pad */ 385 offset = offsetof(struct user_hwdebug_state, pad); 386 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, offset, 387 offset + PTRACE_HBP_PAD_SZ); 388 if (ret) 389 return ret; 390 391 /* (address, ctrl) registers */ 392 offset = offsetof(struct user_hwdebug_state, dbg_regs); 393 limit = regset->n * regset->size; 394 while (count && offset < limit) { 395 ret = ptrace_hbp_get_addr(note_type, target, idx, &addr); 396 if (ret) 397 return ret; 398 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &addr, 399 offset, offset + PTRACE_HBP_ADDR_SZ); 400 if (ret) 401 return ret; 402 offset += PTRACE_HBP_ADDR_SZ; 403 404 ret = ptrace_hbp_get_ctrl(note_type, target, idx, &ctrl); 405 if (ret) 406 return ret; 407 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &ctrl, 408 offset, offset + PTRACE_HBP_CTRL_SZ); 409 if (ret) 410 return ret; 411 offset += PTRACE_HBP_CTRL_SZ; 412 413 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 414 offset, 415 offset + PTRACE_HBP_PAD_SZ); 416 if (ret) 417 return ret; 418 offset += PTRACE_HBP_PAD_SZ; 419 idx++; 420 } 421 422 return 0; 423 } 424 425 static int hw_break_set(struct task_struct *target, 426 const struct user_regset *regset, 427 unsigned int pos, unsigned int count, 428 const void *kbuf, const void __user *ubuf) 429 { 430 unsigned int note_type = regset->core_note_type; 431 int ret, idx = 0, offset, limit; 432 u32 ctrl; 433 u64 addr; 434 435 /* Resource info and pad */ 436 offset = offsetof(struct user_hwdebug_state, dbg_regs); 437 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, offset); 438 if (ret) 439 return ret; 440 441 /* (address, ctrl) registers */ 442 limit = regset->n * regset->size; 443 while (count && offset < limit) { 444 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &addr, 445 offset, offset + PTRACE_HBP_ADDR_SZ); 446 if (ret) 447 return ret; 448 ret = ptrace_hbp_set_addr(note_type, target, idx, addr); 449 if (ret) 450 return ret; 451 offset += PTRACE_HBP_ADDR_SZ; 452 453 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl, 454 offset, offset + PTRACE_HBP_CTRL_SZ); 455 if (ret) 456 return ret; 457 ret = ptrace_hbp_set_ctrl(note_type, target, idx, ctrl); 458 if (ret) 459 return ret; 460 offset += PTRACE_HBP_CTRL_SZ; 461 462 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 463 offset, 464 offset + PTRACE_HBP_PAD_SZ); 465 if (ret) 466 return ret; 467 offset += PTRACE_HBP_PAD_SZ; 468 idx++; 469 } 470 471 return 0; 472 } 473 #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 474 475 static int gpr_get(struct task_struct *target, 476 const struct user_regset *regset, 477 unsigned int pos, unsigned int count, 478 void *kbuf, void __user *ubuf) 479 { 480 struct user_pt_regs *uregs = &task_pt_regs(target)->user_regs; 481 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1); 482 } 483 484 static int gpr_set(struct task_struct *target, const struct user_regset *regset, 485 unsigned int pos, unsigned int count, 486 const void *kbuf, const void __user *ubuf) 487 { 488 int ret; 489 struct user_pt_regs newregs; 490 491 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1); 492 if (ret) 493 return ret; 494 495 if (!valid_user_regs(&newregs)) 496 return -EINVAL; 497 498 task_pt_regs(target)->user_regs = newregs; 499 return 0; 500 } 501 502 /* 503 * TODO: update fp accessors for lazy context switching (sync/flush hwstate) 504 */ 505 static int fpr_get(struct task_struct *target, const struct user_regset *regset, 506 unsigned int pos, unsigned int count, 507 void *kbuf, void __user *ubuf) 508 { 509 struct user_fpsimd_state *uregs; 510 uregs = &target->thread.fpsimd_state.user_fpsimd; 511 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1); 512 } 513 514 static int fpr_set(struct task_struct *target, const struct user_regset *regset, 515 unsigned int pos, unsigned int count, 516 const void *kbuf, const void __user *ubuf) 517 { 518 int ret; 519 struct user_fpsimd_state newstate; 520 521 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newstate, 0, -1); 522 if (ret) 523 return ret; 524 525 target->thread.fpsimd_state.user_fpsimd = newstate; 526 fpsimd_flush_task_state(target); 527 return ret; 528 } 529 530 static int tls_get(struct task_struct *target, const struct user_regset *regset, 531 unsigned int pos, unsigned int count, 532 void *kbuf, void __user *ubuf) 533 { 534 unsigned long *tls = &target->thread.tp_value; 535 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, tls, 0, -1); 536 } 537 538 static int tls_set(struct task_struct *target, const struct user_regset *regset, 539 unsigned int pos, unsigned int count, 540 const void *kbuf, const void __user *ubuf) 541 { 542 int ret; 543 unsigned long tls; 544 545 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1); 546 if (ret) 547 return ret; 548 549 target->thread.tp_value = tls; 550 return ret; 551 } 552 553 enum aarch64_regset { 554 REGSET_GPR, 555 REGSET_FPR, 556 REGSET_TLS, 557 #ifdef CONFIG_HAVE_HW_BREAKPOINT 558 REGSET_HW_BREAK, 559 REGSET_HW_WATCH, 560 #endif 561 }; 562 563 static const struct user_regset aarch64_regsets[] = { 564 [REGSET_GPR] = { 565 .core_note_type = NT_PRSTATUS, 566 .n = sizeof(struct user_pt_regs) / sizeof(u64), 567 .size = sizeof(u64), 568 .align = sizeof(u64), 569 .get = gpr_get, 570 .set = gpr_set 571 }, 572 [REGSET_FPR] = { 573 .core_note_type = NT_PRFPREG, 574 .n = sizeof(struct user_fpsimd_state) / sizeof(u32), 575 /* 576 * We pretend we have 32-bit registers because the fpsr and 577 * fpcr are 32-bits wide. 578 */ 579 .size = sizeof(u32), 580 .align = sizeof(u32), 581 .get = fpr_get, 582 .set = fpr_set 583 }, 584 [REGSET_TLS] = { 585 .core_note_type = NT_ARM_TLS, 586 .n = 1, 587 .size = sizeof(void *), 588 .align = sizeof(void *), 589 .get = tls_get, 590 .set = tls_set, 591 }, 592 #ifdef CONFIG_HAVE_HW_BREAKPOINT 593 [REGSET_HW_BREAK] = { 594 .core_note_type = NT_ARM_HW_BREAK, 595 .n = sizeof(struct user_hwdebug_state) / sizeof(u32), 596 .size = sizeof(u32), 597 .align = sizeof(u32), 598 .get = hw_break_get, 599 .set = hw_break_set, 600 }, 601 [REGSET_HW_WATCH] = { 602 .core_note_type = NT_ARM_HW_WATCH, 603 .n = sizeof(struct user_hwdebug_state) / sizeof(u32), 604 .size = sizeof(u32), 605 .align = sizeof(u32), 606 .get = hw_break_get, 607 .set = hw_break_set, 608 }, 609 #endif 610 }; 611 612 static const struct user_regset_view user_aarch64_view = { 613 .name = "aarch64", .e_machine = EM_AARCH64, 614 .regsets = aarch64_regsets, .n = ARRAY_SIZE(aarch64_regsets) 615 }; 616 617 #ifdef CONFIG_COMPAT 618 #include <linux/compat.h> 619 620 enum compat_regset { 621 REGSET_COMPAT_GPR, 622 REGSET_COMPAT_VFP, 623 }; 624 625 static int compat_gpr_get(struct task_struct *target, 626 const struct user_regset *regset, 627 unsigned int pos, unsigned int count, 628 void *kbuf, void __user *ubuf) 629 { 630 int ret = 0; 631 unsigned int i, start, num_regs; 632 633 /* Calculate the number of AArch32 registers contained in count */ 634 num_regs = count / regset->size; 635 636 /* Convert pos into an register number */ 637 start = pos / regset->size; 638 639 if (start + num_regs > regset->n) 640 return -EIO; 641 642 for (i = 0; i < num_regs; ++i) { 643 unsigned int idx = start + i; 644 compat_ulong_t reg; 645 646 switch (idx) { 647 case 15: 648 reg = task_pt_regs(target)->pc; 649 break; 650 case 16: 651 reg = task_pt_regs(target)->pstate; 652 break; 653 case 17: 654 reg = task_pt_regs(target)->orig_x0; 655 break; 656 default: 657 reg = task_pt_regs(target)->regs[idx]; 658 } 659 660 if (kbuf) { 661 memcpy(kbuf, ®, sizeof(reg)); 662 kbuf += sizeof(reg); 663 } else { 664 ret = copy_to_user(ubuf, ®, sizeof(reg)); 665 if (ret) 666 break; 667 668 ubuf += sizeof(reg); 669 } 670 } 671 672 return ret; 673 } 674 675 static int compat_gpr_set(struct task_struct *target, 676 const struct user_regset *regset, 677 unsigned int pos, unsigned int count, 678 const void *kbuf, const void __user *ubuf) 679 { 680 struct pt_regs newregs; 681 int ret = 0; 682 unsigned int i, start, num_regs; 683 684 /* Calculate the number of AArch32 registers contained in count */ 685 num_regs = count / regset->size; 686 687 /* Convert pos into an register number */ 688 start = pos / regset->size; 689 690 if (start + num_regs > regset->n) 691 return -EIO; 692 693 newregs = *task_pt_regs(target); 694 695 for (i = 0; i < num_regs; ++i) { 696 unsigned int idx = start + i; 697 compat_ulong_t reg; 698 699 if (kbuf) { 700 memcpy(®, kbuf, sizeof(reg)); 701 kbuf += sizeof(reg); 702 } else { 703 ret = copy_from_user(®, ubuf, sizeof(reg)); 704 if (ret) 705 return ret; 706 707 ubuf += sizeof(reg); 708 } 709 710 switch (idx) { 711 case 15: 712 newregs.pc = reg; 713 break; 714 case 16: 715 newregs.pstate = reg; 716 break; 717 case 17: 718 newregs.orig_x0 = reg; 719 break; 720 default: 721 newregs.regs[idx] = reg; 722 } 723 724 } 725 726 if (valid_user_regs(&newregs.user_regs)) 727 *task_pt_regs(target) = newregs; 728 else 729 ret = -EINVAL; 730 731 return ret; 732 } 733 734 static int compat_vfp_get(struct task_struct *target, 735 const struct user_regset *regset, 736 unsigned int pos, unsigned int count, 737 void *kbuf, void __user *ubuf) 738 { 739 struct user_fpsimd_state *uregs; 740 compat_ulong_t fpscr; 741 int ret; 742 743 uregs = &target->thread.fpsimd_state.user_fpsimd; 744 745 /* 746 * The VFP registers are packed into the fpsimd_state, so they all sit 747 * nicely together for us. We just need to create the fpscr separately. 748 */ 749 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, 750 VFP_STATE_SIZE - sizeof(compat_ulong_t)); 751 752 if (count && !ret) { 753 fpscr = (uregs->fpsr & VFP_FPSCR_STAT_MASK) | 754 (uregs->fpcr & VFP_FPSCR_CTRL_MASK); 755 ret = put_user(fpscr, (compat_ulong_t *)ubuf); 756 } 757 758 return ret; 759 } 760 761 static int compat_vfp_set(struct task_struct *target, 762 const struct user_regset *regset, 763 unsigned int pos, unsigned int count, 764 const void *kbuf, const void __user *ubuf) 765 { 766 struct user_fpsimd_state *uregs; 767 compat_ulong_t fpscr; 768 int ret; 769 770 if (pos + count > VFP_STATE_SIZE) 771 return -EIO; 772 773 uregs = &target->thread.fpsimd_state.user_fpsimd; 774 775 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0, 776 VFP_STATE_SIZE - sizeof(compat_ulong_t)); 777 778 if (count && !ret) { 779 ret = get_user(fpscr, (compat_ulong_t *)ubuf); 780 uregs->fpsr = fpscr & VFP_FPSCR_STAT_MASK; 781 uregs->fpcr = fpscr & VFP_FPSCR_CTRL_MASK; 782 } 783 784 fpsimd_flush_task_state(target); 785 return ret; 786 } 787 788 static const struct user_regset aarch32_regsets[] = { 789 [REGSET_COMPAT_GPR] = { 790 .core_note_type = NT_PRSTATUS, 791 .n = COMPAT_ELF_NGREG, 792 .size = sizeof(compat_elf_greg_t), 793 .align = sizeof(compat_elf_greg_t), 794 .get = compat_gpr_get, 795 .set = compat_gpr_set 796 }, 797 [REGSET_COMPAT_VFP] = { 798 .core_note_type = NT_ARM_VFP, 799 .n = VFP_STATE_SIZE / sizeof(compat_ulong_t), 800 .size = sizeof(compat_ulong_t), 801 .align = sizeof(compat_ulong_t), 802 .get = compat_vfp_get, 803 .set = compat_vfp_set 804 }, 805 }; 806 807 static const struct user_regset_view user_aarch32_view = { 808 .name = "aarch32", .e_machine = EM_ARM, 809 .regsets = aarch32_regsets, .n = ARRAY_SIZE(aarch32_regsets) 810 }; 811 812 static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off, 813 compat_ulong_t __user *ret) 814 { 815 compat_ulong_t tmp; 816 817 if (off & 3) 818 return -EIO; 819 820 if (off == COMPAT_PT_TEXT_ADDR) 821 tmp = tsk->mm->start_code; 822 else if (off == COMPAT_PT_DATA_ADDR) 823 tmp = tsk->mm->start_data; 824 else if (off == COMPAT_PT_TEXT_END_ADDR) 825 tmp = tsk->mm->end_code; 826 else if (off < sizeof(compat_elf_gregset_t)) 827 return copy_regset_to_user(tsk, &user_aarch32_view, 828 REGSET_COMPAT_GPR, off, 829 sizeof(compat_ulong_t), ret); 830 else if (off >= COMPAT_USER_SZ) 831 return -EIO; 832 else 833 tmp = 0; 834 835 return put_user(tmp, ret); 836 } 837 838 static int compat_ptrace_write_user(struct task_struct *tsk, compat_ulong_t off, 839 compat_ulong_t val) 840 { 841 int ret; 842 mm_segment_t old_fs = get_fs(); 843 844 if (off & 3 || off >= COMPAT_USER_SZ) 845 return -EIO; 846 847 if (off >= sizeof(compat_elf_gregset_t)) 848 return 0; 849 850 set_fs(KERNEL_DS); 851 ret = copy_regset_from_user(tsk, &user_aarch32_view, 852 REGSET_COMPAT_GPR, off, 853 sizeof(compat_ulong_t), 854 &val); 855 set_fs(old_fs); 856 857 return ret; 858 } 859 860 #ifdef CONFIG_HAVE_HW_BREAKPOINT 861 862 /* 863 * Convert a virtual register number into an index for a thread_info 864 * breakpoint array. Breakpoints are identified using positive numbers 865 * whilst watchpoints are negative. The registers are laid out as pairs 866 * of (address, control), each pair mapping to a unique hw_breakpoint struct. 867 * Register 0 is reserved for describing resource information. 868 */ 869 static int compat_ptrace_hbp_num_to_idx(compat_long_t num) 870 { 871 return (abs(num) - 1) >> 1; 872 } 873 874 static int compat_ptrace_hbp_get_resource_info(u32 *kdata) 875 { 876 u8 num_brps, num_wrps, debug_arch, wp_len; 877 u32 reg = 0; 878 879 num_brps = hw_breakpoint_slots(TYPE_INST); 880 num_wrps = hw_breakpoint_slots(TYPE_DATA); 881 882 debug_arch = debug_monitors_arch(); 883 wp_len = 8; 884 reg |= debug_arch; 885 reg <<= 8; 886 reg |= wp_len; 887 reg <<= 8; 888 reg |= num_wrps; 889 reg <<= 8; 890 reg |= num_brps; 891 892 *kdata = reg; 893 return 0; 894 } 895 896 static int compat_ptrace_hbp_get(unsigned int note_type, 897 struct task_struct *tsk, 898 compat_long_t num, 899 u32 *kdata) 900 { 901 u64 addr = 0; 902 u32 ctrl = 0; 903 904 int err, idx = compat_ptrace_hbp_num_to_idx(num);; 905 906 if (num & 1) { 907 err = ptrace_hbp_get_addr(note_type, tsk, idx, &addr); 908 *kdata = (u32)addr; 909 } else { 910 err = ptrace_hbp_get_ctrl(note_type, tsk, idx, &ctrl); 911 *kdata = ctrl; 912 } 913 914 return err; 915 } 916 917 static int compat_ptrace_hbp_set(unsigned int note_type, 918 struct task_struct *tsk, 919 compat_long_t num, 920 u32 *kdata) 921 { 922 u64 addr; 923 u32 ctrl; 924 925 int err, idx = compat_ptrace_hbp_num_to_idx(num); 926 927 if (num & 1) { 928 addr = *kdata; 929 err = ptrace_hbp_set_addr(note_type, tsk, idx, addr); 930 } else { 931 ctrl = *kdata; 932 err = ptrace_hbp_set_ctrl(note_type, tsk, idx, ctrl); 933 } 934 935 return err; 936 } 937 938 static int compat_ptrace_gethbpregs(struct task_struct *tsk, compat_long_t num, 939 compat_ulong_t __user *data) 940 { 941 int ret; 942 u32 kdata; 943 mm_segment_t old_fs = get_fs(); 944 945 set_fs(KERNEL_DS); 946 /* Watchpoint */ 947 if (num < 0) { 948 ret = compat_ptrace_hbp_get(NT_ARM_HW_WATCH, tsk, num, &kdata); 949 /* Resource info */ 950 } else if (num == 0) { 951 ret = compat_ptrace_hbp_get_resource_info(&kdata); 952 /* Breakpoint */ 953 } else { 954 ret = compat_ptrace_hbp_get(NT_ARM_HW_BREAK, tsk, num, &kdata); 955 } 956 set_fs(old_fs); 957 958 if (!ret) 959 ret = put_user(kdata, data); 960 961 return ret; 962 } 963 964 static int compat_ptrace_sethbpregs(struct task_struct *tsk, compat_long_t num, 965 compat_ulong_t __user *data) 966 { 967 int ret; 968 u32 kdata = 0; 969 mm_segment_t old_fs = get_fs(); 970 971 if (num == 0) 972 return 0; 973 974 ret = get_user(kdata, data); 975 if (ret) 976 return ret; 977 978 set_fs(KERNEL_DS); 979 if (num < 0) 980 ret = compat_ptrace_hbp_set(NT_ARM_HW_WATCH, tsk, num, &kdata); 981 else 982 ret = compat_ptrace_hbp_set(NT_ARM_HW_BREAK, tsk, num, &kdata); 983 set_fs(old_fs); 984 985 return ret; 986 } 987 #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 988 989 long compat_arch_ptrace(struct task_struct *child, compat_long_t request, 990 compat_ulong_t caddr, compat_ulong_t cdata) 991 { 992 unsigned long addr = caddr; 993 unsigned long data = cdata; 994 void __user *datap = compat_ptr(data); 995 int ret; 996 997 switch (request) { 998 case PTRACE_PEEKUSR: 999 ret = compat_ptrace_read_user(child, addr, datap); 1000 break; 1001 1002 case PTRACE_POKEUSR: 1003 ret = compat_ptrace_write_user(child, addr, data); 1004 break; 1005 1006 case COMPAT_PTRACE_GETREGS: 1007 ret = copy_regset_to_user(child, 1008 &user_aarch32_view, 1009 REGSET_COMPAT_GPR, 1010 0, sizeof(compat_elf_gregset_t), 1011 datap); 1012 break; 1013 1014 case COMPAT_PTRACE_SETREGS: 1015 ret = copy_regset_from_user(child, 1016 &user_aarch32_view, 1017 REGSET_COMPAT_GPR, 1018 0, sizeof(compat_elf_gregset_t), 1019 datap); 1020 break; 1021 1022 case COMPAT_PTRACE_GET_THREAD_AREA: 1023 ret = put_user((compat_ulong_t)child->thread.tp_value, 1024 (compat_ulong_t __user *)datap); 1025 break; 1026 1027 case COMPAT_PTRACE_SET_SYSCALL: 1028 task_pt_regs(child)->syscallno = data; 1029 ret = 0; 1030 break; 1031 1032 case COMPAT_PTRACE_GETVFPREGS: 1033 ret = copy_regset_to_user(child, 1034 &user_aarch32_view, 1035 REGSET_COMPAT_VFP, 1036 0, VFP_STATE_SIZE, 1037 datap); 1038 break; 1039 1040 case COMPAT_PTRACE_SETVFPREGS: 1041 ret = copy_regset_from_user(child, 1042 &user_aarch32_view, 1043 REGSET_COMPAT_VFP, 1044 0, VFP_STATE_SIZE, 1045 datap); 1046 break; 1047 1048 #ifdef CONFIG_HAVE_HW_BREAKPOINT 1049 case COMPAT_PTRACE_GETHBPREGS: 1050 ret = compat_ptrace_gethbpregs(child, addr, datap); 1051 break; 1052 1053 case COMPAT_PTRACE_SETHBPREGS: 1054 ret = compat_ptrace_sethbpregs(child, addr, datap); 1055 break; 1056 #endif 1057 1058 default: 1059 ret = compat_ptrace_request(child, request, addr, 1060 data); 1061 break; 1062 } 1063 1064 return ret; 1065 } 1066 #endif /* CONFIG_COMPAT */ 1067 1068 const struct user_regset_view *task_user_regset_view(struct task_struct *task) 1069 { 1070 #ifdef CONFIG_COMPAT 1071 if (is_compat_thread(task_thread_info(task))) 1072 return &user_aarch32_view; 1073 #endif 1074 return &user_aarch64_view; 1075 } 1076 1077 long arch_ptrace(struct task_struct *child, long request, 1078 unsigned long addr, unsigned long data) 1079 { 1080 return ptrace_request(child, request, addr, data); 1081 } 1082 1083 enum ptrace_syscall_dir { 1084 PTRACE_SYSCALL_ENTER = 0, 1085 PTRACE_SYSCALL_EXIT, 1086 }; 1087 1088 static void tracehook_report_syscall(struct pt_regs *regs, 1089 enum ptrace_syscall_dir dir) 1090 { 1091 int regno; 1092 unsigned long saved_reg; 1093 1094 /* 1095 * A scratch register (ip(r12) on AArch32, x7 on AArch64) is 1096 * used to denote syscall entry/exit: 1097 */ 1098 regno = (is_compat_task() ? 12 : 7); 1099 saved_reg = regs->regs[regno]; 1100 regs->regs[regno] = dir; 1101 1102 if (dir == PTRACE_SYSCALL_EXIT) 1103 tracehook_report_syscall_exit(regs, 0); 1104 else if (tracehook_report_syscall_entry(regs)) 1105 regs->syscallno = ~0UL; 1106 1107 regs->regs[regno] = saved_reg; 1108 } 1109 1110 asmlinkage int syscall_trace_enter(struct pt_regs *regs) 1111 { 1112 if (test_thread_flag(TIF_SYSCALL_TRACE)) 1113 tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER); 1114 1115 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) 1116 trace_sys_enter(regs, regs->syscallno); 1117 1118 #ifdef CONFIG_AUDITSYSCALL 1119 audit_syscall_entry(syscall_get_arch(), regs->syscallno, 1120 regs->orig_x0, regs->regs[1], regs->regs[2], regs->regs[3]); 1121 #endif 1122 1123 return regs->syscallno; 1124 } 1125 1126 asmlinkage void syscall_trace_exit(struct pt_regs *regs) 1127 { 1128 #ifdef CONFIG_AUDITSYSCALL 1129 audit_syscall_exit(regs); 1130 #endif 1131 1132 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) 1133 trace_sys_exit(regs, regs_return_value(regs)); 1134 1135 if (test_thread_flag(TIF_SYSCALL_TRACE)) 1136 tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT); 1137 } 1138