| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * linux/arch/arm/kernel/ptrace.c |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * By Ross Biro 1/23/92 |
|---|
| 5 | 6 | * edited by Linus Torvalds |
|---|
| 6 | 7 | * ARM modifications Copyright (C) 2000 Russell King |
|---|
| 7 | | - * |
|---|
| 8 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 9 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 10 | | - * published by the Free Software Foundation. |
|---|
| 11 | 8 | */ |
|---|
| 12 | 9 | #include <linux/kernel.h> |
|---|
| 13 | 10 | #include <linux/sched/signal.h> |
|---|
| .. | .. |
|---|
| 28 | 25 | #include <linux/tracehook.h> |
|---|
| 29 | 26 | #include <linux/unistd.h> |
|---|
| 30 | 27 | |
|---|
| 31 | | -#include <asm/pgtable.h> |
|---|
| 32 | 28 | #include <asm/traps.h> |
|---|
| 33 | 29 | |
|---|
| 34 | 30 | #define CREATE_TRACE_POINTS |
|---|
| .. | .. |
|---|
| 201 | 197 | /* |
|---|
| 202 | 198 | * Handle hitting a breakpoint. |
|---|
| 203 | 199 | */ |
|---|
| 204 | | -void ptrace_break(struct task_struct *tsk, struct pt_regs *regs) |
|---|
| 200 | +void ptrace_break(struct pt_regs *regs) |
|---|
| 205 | 201 | { |
|---|
| 206 | | - siginfo_t info; |
|---|
| 207 | | - |
|---|
| 208 | | - clear_siginfo(&info); |
|---|
| 209 | | - info.si_signo = SIGTRAP; |
|---|
| 210 | | - info.si_errno = 0; |
|---|
| 211 | | - info.si_code = TRAP_BRKPT; |
|---|
| 212 | | - info.si_addr = (void __user *)instruction_pointer(regs); |
|---|
| 213 | | - |
|---|
| 214 | | - force_sig_info(SIGTRAP, &info, tsk); |
|---|
| 202 | + force_sig_fault(SIGTRAP, TRAP_BRKPT, |
|---|
| 203 | + (void __user *)instruction_pointer(regs)); |
|---|
| 215 | 204 | } |
|---|
| 216 | 205 | |
|---|
| 217 | 206 | static int break_trap(struct pt_regs *regs, unsigned int instr) |
|---|
| 218 | 207 | { |
|---|
| 219 | | - ptrace_break(current, regs); |
|---|
| 208 | + ptrace_break(regs); |
|---|
| 220 | 209 | return 0; |
|---|
| 221 | 210 | } |
|---|
| 222 | 211 | |
|---|
| .. | .. |
|---|
| 580 | 569 | |
|---|
| 581 | 570 | static int gpr_get(struct task_struct *target, |
|---|
| 582 | 571 | const struct user_regset *regset, |
|---|
| 583 | | - unsigned int pos, unsigned int count, |
|---|
| 584 | | - void *kbuf, void __user *ubuf) |
|---|
| 572 | + struct membuf to) |
|---|
| 585 | 573 | { |
|---|
| 586 | | - struct pt_regs *regs = task_pt_regs(target); |
|---|
| 587 | | - |
|---|
| 588 | | - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
|---|
| 589 | | - regs, |
|---|
| 590 | | - 0, sizeof(*regs)); |
|---|
| 574 | + return membuf_write(&to, task_pt_regs(target), sizeof(struct pt_regs)); |
|---|
| 591 | 575 | } |
|---|
| 592 | 576 | |
|---|
| 593 | 577 | static int gpr_set(struct task_struct *target, |
|---|
| .. | .. |
|---|
| 613 | 597 | |
|---|
| 614 | 598 | static int fpa_get(struct task_struct *target, |
|---|
| 615 | 599 | const struct user_regset *regset, |
|---|
| 616 | | - unsigned int pos, unsigned int count, |
|---|
| 617 | | - void *kbuf, void __user *ubuf) |
|---|
| 600 | + struct membuf to) |
|---|
| 618 | 601 | { |
|---|
| 619 | | - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
|---|
| 620 | | - &task_thread_info(target)->fpstate, |
|---|
| 621 | | - 0, sizeof(struct user_fp)); |
|---|
| 602 | + return membuf_write(&to, &task_thread_info(target)->fpstate, |
|---|
| 603 | + sizeof(struct user_fp)); |
|---|
| 622 | 604 | } |
|---|
| 623 | 605 | |
|---|
| 624 | 606 | static int fpa_set(struct task_struct *target, |
|---|
| .. | .. |
|---|
| 653 | 635 | * vfp_set() ignores this chunk |
|---|
| 654 | 636 | * |
|---|
| 655 | 637 | * 1 word for the FPSCR |
|---|
| 656 | | - * |
|---|
| 657 | | - * The bounds-checking logic built into user_regset_copyout and friends |
|---|
| 658 | | - * means that we can make a simple sequence of calls to map the relevant data |
|---|
| 659 | | - * to/from the specified slice of the user regset structure. |
|---|
| 660 | 638 | */ |
|---|
| 661 | 639 | static int vfp_get(struct task_struct *target, |
|---|
| 662 | 640 | const struct user_regset *regset, |
|---|
| 663 | | - unsigned int pos, unsigned int count, |
|---|
| 664 | | - void *kbuf, void __user *ubuf) |
|---|
| 641 | + struct membuf to) |
|---|
| 665 | 642 | { |
|---|
| 666 | | - int ret; |
|---|
| 667 | 643 | struct thread_info *thread = task_thread_info(target); |
|---|
| 668 | 644 | struct vfp_hard_struct const *vfp = &thread->vfpstate.hard; |
|---|
| 669 | | - const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs); |
|---|
| 670 | 645 | const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr); |
|---|
| 671 | 646 | |
|---|
| 672 | 647 | vfp_sync_hwstate(thread); |
|---|
| 673 | 648 | |
|---|
| 674 | | - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
|---|
| 675 | | - &vfp->fpregs, |
|---|
| 676 | | - user_fpregs_offset, |
|---|
| 677 | | - user_fpregs_offset + sizeof(vfp->fpregs)); |
|---|
| 678 | | - if (ret) |
|---|
| 679 | | - return ret; |
|---|
| 680 | | - |
|---|
| 681 | | - ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, |
|---|
| 682 | | - user_fpregs_offset + sizeof(vfp->fpregs), |
|---|
| 683 | | - user_fpscr_offset); |
|---|
| 684 | | - if (ret) |
|---|
| 685 | | - return ret; |
|---|
| 686 | | - |
|---|
| 687 | | - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
|---|
| 688 | | - &vfp->fpscr, |
|---|
| 689 | | - user_fpscr_offset, |
|---|
| 690 | | - user_fpscr_offset + sizeof(vfp->fpscr)); |
|---|
| 649 | + membuf_write(&to, vfp->fpregs, sizeof(vfp->fpregs)); |
|---|
| 650 | + membuf_zero(&to, user_fpscr_offset - sizeof(vfp->fpregs)); |
|---|
| 651 | + return membuf_store(&to, vfp->fpscr); |
|---|
| 691 | 652 | } |
|---|
| 692 | 653 | |
|---|
| 693 | 654 | /* |
|---|
| .. | .. |
|---|
| 750 | 711 | .n = ELF_NGREG, |
|---|
| 751 | 712 | .size = sizeof(u32), |
|---|
| 752 | 713 | .align = sizeof(u32), |
|---|
| 753 | | - .get = gpr_get, |
|---|
| 714 | + .regset_get = gpr_get, |
|---|
| 754 | 715 | .set = gpr_set |
|---|
| 755 | 716 | }, |
|---|
| 756 | 717 | [REGSET_FPR] = { |
|---|
| .. | .. |
|---|
| 762 | 723 | .n = sizeof(struct user_fp) / sizeof(u32), |
|---|
| 763 | 724 | .size = sizeof(u32), |
|---|
| 764 | 725 | .align = sizeof(u32), |
|---|
| 765 | | - .get = fpa_get, |
|---|
| 726 | + .regset_get = fpa_get, |
|---|
| 766 | 727 | .set = fpa_set |
|---|
| 767 | 728 | }, |
|---|
| 768 | 729 | #ifdef CONFIG_VFP |
|---|
| .. | .. |
|---|
| 775 | 736 | .n = ARM_VFPREGS_SIZE / sizeof(u32), |
|---|
| 776 | 737 | .size = sizeof(u32), |
|---|
| 777 | 738 | .align = sizeof(u32), |
|---|
| 778 | | - .get = vfp_get, |
|---|
| 739 | + .regset_get = vfp_get, |
|---|
| 779 | 740 | .set = vfp_set |
|---|
| 780 | 741 | }, |
|---|
| 781 | 742 | #endif /* CONFIG_VFP */ |
|---|
| .. | .. |
|---|
| 933 | 894 | |
|---|
| 934 | 895 | /* Do seccomp after ptrace; syscall may have changed. */ |
|---|
| 935 | 896 | #ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER |
|---|
| 936 | | - if (secure_computing(NULL) == -1) |
|---|
| 897 | + if (secure_computing() == -1) |
|---|
| 937 | 898 | return -1; |
|---|
| 938 | 899 | #else |
|---|
| 939 | 900 | /* XXX: remove this once OABI gets fixed */ |
|---|