Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/ptrace: Split gpr32_set_common

objtool reports the following warning:

arch/powerpc/kernel/ptrace/ptrace-view.o: warning: objtool:
gpr32_set_common+0x23c (.text+0x860): redundant UACCESS disable

gpr32_set_common() conditionally opens and closes UACCESS based on
whether kbuf pointer is NULL or not. This is wackelig.

Split gpr32_set_common() in two fonctions, one for user one for
kernel.

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
[mpe: Fix oops in gpr32_set_common_user() due to NULL kbuf]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/b8d6ae4483fcfd17524e79d803c969694a85cc02.1687428075.git.christophe.leroy@csgroup.eu

authored by

Christophe Leroy and committed by
Michael Ellerman
9a32584b 0e216fa5

+67 -38
+67 -38
arch/powerpc/kernel/ptrace/ptrace-view.c
··· 716 716 return membuf_zero(&to, (ELF_NGREG - PT_REGS_COUNT) * sizeof(u32)); 717 717 } 718 718 719 - int gpr32_set_common(struct task_struct *target, 720 - const struct user_regset *regset, 721 - unsigned int pos, unsigned int count, 722 - const void *kbuf, const void __user *ubuf, 723 - unsigned long *regs) 719 + static int gpr32_set_common_kernel(struct task_struct *target, 720 + const struct user_regset *regset, 721 + unsigned int pos, unsigned int count, 722 + const void *kbuf, unsigned long *regs) 724 723 { 725 724 const compat_ulong_t *k = kbuf; 725 + 726 + pos /= sizeof(compat_ulong_t); 727 + count /= sizeof(compat_ulong_t); 728 + 729 + for (; count > 0 && pos < PT_MSR; --count) 730 + regs[pos++] = *k++; 731 + 732 + if (count > 0 && pos == PT_MSR) { 733 + set_user_msr(target, *k++); 734 + ++pos; 735 + --count; 736 + } 737 + 738 + for (; count > 0 && pos <= PT_MAX_PUT_REG; --count) 739 + regs[pos++] = *k++; 740 + for (; count > 0 && pos < PT_TRAP; --count, ++pos) 741 + ++k; 742 + 743 + if (count > 0 && pos == PT_TRAP) { 744 + set_user_trap(target, *k++); 745 + ++pos; 746 + --count; 747 + } 748 + 749 + kbuf = k; 750 + pos *= sizeof(compat_ulong_t); 751 + count *= sizeof(compat_ulong_t); 752 + user_regset_copyin_ignore(&pos, &count, &kbuf, NULL, 753 + (PT_TRAP + 1) * sizeof(compat_ulong_t), -1); 754 + return 0; 755 + } 756 + 757 + static int gpr32_set_common_user(struct task_struct *target, 758 + const struct user_regset *regset, 759 + unsigned int pos, unsigned int count, 760 + const void __user *ubuf, unsigned long *regs) 761 + { 726 762 const compat_ulong_t __user *u = ubuf; 763 + const void *kbuf = NULL; 727 764 compat_ulong_t reg; 728 765 729 - if (!kbuf && !user_read_access_begin(u, count)) 766 + if (!user_read_access_begin(u, count)) 730 767 return -EFAULT; 731 768 732 769 pos /= sizeof(reg); 733 770 count /= sizeof(reg); 734 771 735 - if (kbuf) 736 - for (; count > 0 && pos < PT_MSR; --count) 737 - regs[pos++] = *k++; 738 - else 739 - for (; count > 0 && pos < PT_MSR; --count) { 740 - unsafe_get_user(reg, u++, Efault); 741 - regs[pos++] = reg; 742 - } 743 - 772 + for (; count > 0 && pos < PT_MSR; --count) { 773 + unsafe_get_user(reg, u++, Efault); 774 + regs[pos++] = reg; 775 + } 744 776 745 777 if (count > 0 && pos == PT_MSR) { 746 - if (kbuf) 747 - reg = *k++; 748 - else 749 - unsafe_get_user(reg, u++, Efault); 778 + unsafe_get_user(reg, u++, Efault); 750 779 set_user_msr(target, reg); 751 780 ++pos; 752 781 --count; 753 782 } 754 783 755 - if (kbuf) { 756 - for (; count > 0 && pos <= PT_MAX_PUT_REG; --count) 757 - regs[pos++] = *k++; 758 - for (; count > 0 && pos < PT_TRAP; --count, ++pos) 759 - ++k; 760 - } else { 761 - for (; count > 0 && pos <= PT_MAX_PUT_REG; --count) { 762 - unsafe_get_user(reg, u++, Efault); 763 - regs[pos++] = reg; 764 - } 765 - for (; count > 0 && pos < PT_TRAP; --count, ++pos) 766 - unsafe_get_user(reg, u++, Efault); 784 + for (; count > 0 && pos <= PT_MAX_PUT_REG; --count) { 785 + unsafe_get_user(reg, u++, Efault); 786 + regs[pos++] = reg; 767 787 } 788 + for (; count > 0 && pos < PT_TRAP; --count, ++pos) 789 + unsafe_get_user(reg, u++, Efault); 768 790 769 791 if (count > 0 && pos == PT_TRAP) { 770 - if (kbuf) 771 - reg = *k++; 772 - else 773 - unsafe_get_user(reg, u++, Efault); 792 + unsafe_get_user(reg, u++, Efault); 774 793 set_user_trap(target, reg); 775 794 ++pos; 776 795 --count; 777 796 } 778 - if (!kbuf) 779 - user_read_access_end(); 797 + user_read_access_end(); 780 798 781 - kbuf = k; 782 799 ubuf = u; 783 800 pos *= sizeof(reg); 784 801 count *= sizeof(reg); ··· 806 789 Efault: 807 790 user_read_access_end(); 808 791 return -EFAULT; 792 + } 793 + 794 + int gpr32_set_common(struct task_struct *target, 795 + const struct user_regset *regset, 796 + unsigned int pos, unsigned int count, 797 + const void *kbuf, const void __user *ubuf, 798 + unsigned long *regs) 799 + { 800 + if (kbuf) 801 + return gpr32_set_common_kernel(target, regset, pos, count, kbuf, regs); 802 + else 803 + return gpr32_set_common_user(target, regset, pos, count, ubuf, regs); 809 804 } 810 805 811 806 static int gpr32_get(struct task_struct *target,