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