]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.19.31/powerpc-ptrace-simplify-vr_get-set-to-avoid-gcc-warning.patch
Linux 4.14.108
[thirdparty/kernel/stable-queue.git] / releases / 4.19.31 / powerpc-ptrace-simplify-vr_get-set-to-avoid-gcc-warning.patch
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
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 From: Michael Ellerman <mpe@ellerman.id.au>
10
11 commit ca6d5149d2ad0a8d2f9c28cbe379802260a0a5e0 upstream.
12
13 GCC 8 warns about the logic in vr_get/set(), which with -Werror breaks
14 the build:
15
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
23 } vrsave;
24
25 This has been identified as a regression in GCC, see GCC bug 88273.
26
27 However we can avoid the warning and also simplify the logic and make
28 it more robust.
29
30 Currently we pass -1 as end_pos to user_regset_copyout(). This says
31 "copy up to the end of the regset".
32
33 The definition of the regset is:
34 [REGSET_VMX] = {
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
38 },
39
40 The end is calculated as (n * size), ie. 34 * sizeof(vector128).
41
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.
44
45 The on-stack vrsave is defined as:
46 union {
47 elf_vrreg_t reg;
48 u32 word;
49 } vrsave;
50
51 And elf_vrreg_t is:
52 typedef __vector128 elf_vrreg_t;
53
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
56 hands.
57
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
61 compiler warning.
62
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>
70
71 ---
72 arch/powerpc/kernel/ptrace.c | 10 ++++++++--
73 1 file changed, 8 insertions(+), 2 deletions(-)
74
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
78 /*
79 * Copy out only the low-order word of vrsave.
80 */
81 + int start, end;
82 union {
83 elf_vrreg_t reg;
84 u32 word;
85 @@ -569,8 +570,10 @@ static int vr_get(struct task_struct *ta
86
87 vrsave.word = target->thread.vrsave;
88
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);
93 + start, end);
94 }
95
96 return ret;
97 @@ -608,6 +611,7 @@ static int vr_set(struct task_struct *ta
98 /*
99 * We use only the first word of vrsave.
100 */
101 + int start, end;
102 union {
103 elf_vrreg_t reg;
104 u32 word;
105 @@ -616,8 +620,10 @@ static int vr_set(struct task_struct *ta
106
107 vrsave.word = target->thread.vrsave;
108
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);
113 + start, end);
114 if (!ret)
115 target->thread.vrsave = vrsave.word;
116 }