1 From ca6d5149d2ad0a8d2f9c28cbe379802260a0a5e0 Mon Sep 17 00:00:00 2001
2 From: Michael Ellerman <mpe@ellerman.id.au>
3 Date: Thu, 14 Feb 2019 11:08:29 +1100
4 Subject: powerpc/ptrace: Simplify vr_get/set() to avoid GCC warning
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
9 From: Michael Ellerman <mpe@ellerman.id.au>
11 commit ca6d5149d2ad0a8d2f9c28cbe379802260a0a5e0 upstream.
13 GCC 8 warns about the logic in vr_get/set(), which with -Werror breaks
16 In function ‘user_regset_copyin’,
17 inlined from ‘vr_set’ at arch/powerpc/kernel/ptrace.c:628:9:
18 include/linux/regset.h:295:4: error: ‘memcpy’ offset [-527, -529] is
19 out of the bounds [0, 16] of object ‘vrsave’ with type ‘union
20 <anonymous>’ [-Werror=array-bounds]
21 arch/powerpc/kernel/ptrace.c: In function ‘vr_set’:
22 arch/powerpc/kernel/ptrace.c:623:5: note: ‘vrsave’ declared here
25 This has been identified as a regression in GCC, see GCC bug 88273.
27 However we can avoid the warning and also simplify the logic and make
30 Currently we pass -1 as end_pos to user_regset_copyout(). This says
31 "copy up to the end of the regset".
33 The definition of the regset is:
35 .core_note_type = NT_PPC_VMX, .n = 34,
36 .size = sizeof(vector128), .align = sizeof(vector128),
37 .active = vr_active, .get = vr_get, .set = vr_set
40 The end is calculated as (n * size), ie. 34 * sizeof(vector128).
42 In vr_get/set() we pass start_pos as 33 * sizeof(vector128), meaning
43 we can copy up to sizeof(vector128) into/out-of vrsave.
45 The on-stack vrsave is defined as:
52 typedef __vector128 elf_vrreg_t;
54 So there is no bug, but we rely on all those sizes lining up,
55 otherwise we would have a kernel stack exposure/overwrite on our
58 Rather than relying on that we can pass an explict end_pos based on
59 the sizeof(vrsave). The result should be exactly the same but it's
60 more obviously not over-reading/writing the stack and it avoids the
63 Reported-by: Meelis Roos <mroos@linux.ee>
64 Reported-by: Mathieu Malaterre <malat@debian.org>
65 Cc: stable@vger.kernel.org
66 Tested-by: Mathieu Malaterre <malat@debian.org>
67 Tested-by: Meelis Roos <mroos@linux.ee>
68 Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
69 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
72 arch/powerpc/kernel/ptrace.c | 10 ++++++++--
73 1 file changed, 8 insertions(+), 2 deletions(-)
75 --- a/arch/powerpc/kernel/ptrace.c
76 +++ b/arch/powerpc/kernel/ptrace.c
77 @@ -561,6 +561,7 @@ static int vr_get(struct task_struct *ta
79 * Copy out only the low-order word of vrsave.
85 @@ -569,8 +570,10 @@ static int vr_get(struct task_struct *ta
87 vrsave.word = target->thread.vrsave;
89 + start = 33 * sizeof(vector128);
90 + end = start + sizeof(vrsave);
91 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave,
92 - 33 * sizeof(vector128), -1);
97 @@ -608,6 +611,7 @@ static int vr_set(struct task_struct *ta
99 * We use only the first word of vrsave.
105 @@ -616,8 +620,10 @@ static int vr_set(struct task_struct *ta
107 vrsave.word = target->thread.vrsave;
109 + start = 33 * sizeof(vector128);
110 + end = start + sizeof(vrsave);
111 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave,
112 - 33 * sizeof(vector128), -1);
115 target->thread.vrsave = vrsave.word;