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