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