]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob
95c41d86a4e34a08cef2b18ed5d7d7179fe94c88
[thirdparty/kernel/stable-queue.git] /
1 From 2b3f8e87cf99a33fb6faf5026d7147748bbd77b6 Mon Sep 17 00:00:00 2001
2 From: Michael Neuling <mikey@neuling.org>
3 Date: Sun, 26 May 2013 18:09:41 +0000
4 Subject: powerpc/tm: Fix userspace stack corruption on signal delivery for active transactions
5
6 From: Michael Neuling <mikey@neuling.org>
7
8 commit 2b3f8e87cf99a33fb6faf5026d7147748bbd77b6 upstream.
9
10 When in an active transaction that takes a signal, we need to be careful with
11 the stack. It's possible that the stack has moved back up after the tbegin.
12 The obvious case here is when the tbegin is called inside a function that
13 returns before a tend. In this case, the stack is part of the checkpointed
14 transactional memory state. If we write over this non transactionally or in
15 suspend, we are in trouble because if we get a tm abort, the program counter
16 and stack pointer will be back at the tbegin but our in memory stack won't be
17 valid anymore.
18
19 To avoid this, when taking a signal in an active transaction, we need to use
20 the stack pointer from the checkpointed state, rather than the speculated
21 state. This ensures that the signal context (written tm suspended) will be
22 written below the stack required for the rollback. The transaction is aborted
23 becuase of the treclaim, so any memory written between the tbegin and the
24 signal will be rolled back anyway.
25
26 For signals taken in non-TM or suspended mode, we use the
27 normal/non-checkpointed stack pointer.
28
29 Tested with 64 and 32 bit signals
30
31 Signed-off-by: Michael Neuling <mikey@neuling.org>
32 Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
33 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
34
35 ---
36 Documentation/powerpc/transactional_memory.txt | 19 +++++++++++
37 arch/powerpc/include/asm/processor.h | 13 ++------
38 arch/powerpc/include/asm/signal.h | 3 +
39 arch/powerpc/kernel/signal.c | 40 +++++++++++++++++++++++--
40 arch/powerpc/kernel/signal.h | 2 -
41 arch/powerpc/kernel/signal_32.c | 10 +-----
42 arch/powerpc/kernel/signal_64.c | 23 ++++----------
43 7 files changed, 74 insertions(+), 36 deletions(-)
44
45 --- a/Documentation/powerpc/transactional_memory.txt
46 +++ b/Documentation/powerpc/transactional_memory.txt
47 @@ -147,6 +147,25 @@ Example signal handler:
48 fix_the_problem(ucp->dar);
49 }
50
51 +When in an active transaction that takes a signal, we need to be careful with
52 +the stack. It's possible that the stack has moved back up after the tbegin.
53 +The obvious case here is when the tbegin is called inside a function that
54 +returns before a tend. In this case, the stack is part of the checkpointed
55 +transactional memory state. If we write over this non transactionally or in
56 +suspend, we are in trouble because if we get a tm abort, the program counter and
57 +stack pointer will be back at the tbegin but our in memory stack won't be valid
58 +anymore.
59 +
60 +To avoid this, when taking a signal in an active transaction, we need to use
61 +the stack pointer from the checkpointed state, rather than the speculated
62 +state. This ensures that the signal context (written tm suspended) will be
63 +written below the stack required for the rollback. The transaction is aborted
64 +becuase of the treclaim, so any memory written between the tbegin and the
65 +signal will be rolled back anyway.
66 +
67 +For signals taken in non-TM or suspended mode, we use the
68 +normal/non-checkpointed stack pointer.
69 +
70
71 Failure cause codes used by kernel
72 ==================================
73 --- a/arch/powerpc/include/asm/processor.h
74 +++ b/arch/powerpc/include/asm/processor.h
75 @@ -407,21 +407,16 @@ static inline void prefetchw(const void
76 #endif
77
78 #ifdef CONFIG_PPC64
79 -static inline unsigned long get_clean_sp(struct pt_regs *regs, int is_32)
80 +static inline unsigned long get_clean_sp(unsigned long sp, int is_32)
81 {
82 - unsigned long sp;
83 -
84 if (is_32)
85 - sp = regs->gpr[1] & 0x0ffffffffUL;
86 - else
87 - sp = regs->gpr[1];
88 -
89 + return sp & 0x0ffffffffUL;
90 return sp;
91 }
92 #else
93 -static inline unsigned long get_clean_sp(struct pt_regs *regs, int is_32)
94 +static inline unsigned long get_clean_sp(unsigned long sp, int is_32)
95 {
96 - return regs->gpr[1];
97 + return sp;
98 }
99 #endif
100
101 --- a/arch/powerpc/include/asm/signal.h
102 +++ b/arch/powerpc/include/asm/signal.h
103 @@ -3,5 +3,8 @@
104
105 #define __ARCH_HAS_SA_RESTORER
106 #include <uapi/asm/signal.h>
107 +#include <uapi/asm/ptrace.h>
108 +
109 +extern unsigned long get_tm_stackpointer(struct pt_regs *regs);
110
111 #endif /* _ASM_POWERPC_SIGNAL_H */
112 --- a/arch/powerpc/kernel/signal.c
113 +++ b/arch/powerpc/kernel/signal.c
114 @@ -17,6 +17,7 @@
115 #include <asm/uaccess.h>
116 #include <asm/unistd.h>
117 #include <asm/debug.h>
118 +#include <asm/tm.h>
119
120 #include "signal.h"
121
122 @@ -29,13 +30,13 @@ int show_unhandled_signals = 0;
123 /*
124 * Allocate space for the signal frame
125 */
126 -void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
127 +void __user * get_sigframe(struct k_sigaction *ka, unsigned long sp,
128 size_t frame_size, int is_32)
129 {
130 unsigned long oldsp, newsp;
131
132 /* Default to using normal stack */
133 - oldsp = get_clean_sp(regs, is_32);
134 + oldsp = get_clean_sp(sp, is_32);
135
136 /* Check for alt stack */
137 if ((ka->sa.sa_flags & SA_ONSTACK) &&
138 @@ -170,3 +171,38 @@ void do_notify_resume(struct pt_regs *re
139 tracehook_notify_resume(regs);
140 }
141 }
142 +
143 +unsigned long get_tm_stackpointer(struct pt_regs *regs)
144 +{
145 + /* When in an active transaction that takes a signal, we need to be
146 + * careful with the stack. It's possible that the stack has moved back
147 + * up after the tbegin. The obvious case here is when the tbegin is
148 + * called inside a function that returns before a tend. In this case,
149 + * the stack is part of the checkpointed transactional memory state.
150 + * If we write over this non transactionally or in suspend, we are in
151 + * trouble because if we get a tm abort, the program counter and stack
152 + * pointer will be back at the tbegin but our in memory stack won't be
153 + * valid anymore.
154 + *
155 + * To avoid this, when taking a signal in an active transaction, we
156 + * need to use the stack pointer from the checkpointed state, rather
157 + * than the speculated state. This ensures that the signal context
158 + * (written tm suspended) will be written below the stack required for
159 + * the rollback. The transaction is aborted becuase of the treclaim,
160 + * so any memory written between the tbegin and the signal will be
161 + * rolled back anyway.
162 + *
163 + * For signals taken in non-TM or suspended mode, we use the
164 + * normal/non-checkpointed stack pointer.
165 + */
166 +
167 +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
168 + if (MSR_TM_ACTIVE(regs->msr)) {
169 + tm_enable();
170 + tm_reclaim(&current->thread, regs->msr, TM_CAUSE_SIGNAL);
171 + if (MSR_TM_TRANSACTIONAL(regs->msr))
172 + return current->thread.ckpt_regs.gpr[1];
173 + }
174 +#endif
175 + return regs->gpr[1];
176 +}
177 --- a/arch/powerpc/kernel/signal.h
178 +++ b/arch/powerpc/kernel/signal.h
179 @@ -12,7 +12,7 @@
180
181 extern void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags);
182
183 -extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
184 +extern void __user * get_sigframe(struct k_sigaction *ka, unsigned long sp,
185 size_t frame_size, int is_32);
186
187 extern int handle_signal32(unsigned long sig, struct k_sigaction *ka,
188 --- a/arch/powerpc/kernel/signal_32.c
189 +++ b/arch/powerpc/kernel/signal_32.c
190 @@ -503,12 +503,6 @@ static int save_tm_user_regs(struct pt_r
191 {
192 unsigned long msr = regs->msr;
193
194 - /* tm_reclaim rolls back all reg states, updating thread.ckpt_regs,
195 - * thread.transact_fpr[], thread.transact_vr[], etc.
196 - */
197 - tm_enable();
198 - tm_reclaim(&current->thread, msr, TM_CAUSE_SIGNAL);
199 -
200 /* Make sure floating point registers are stored in regs */
201 flush_fp_to_thread(current);
202
203 @@ -965,7 +959,7 @@ int handle_rt_signal32(unsigned long sig
204
205 /* Set up Signal Frame */
206 /* Put a Real Time Context onto stack */
207 - rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf), 1);
208 + rt_sf = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*rt_sf), 1);
209 addr = rt_sf;
210 if (unlikely(rt_sf == NULL))
211 goto badframe;
212 @@ -1403,7 +1397,7 @@ int handle_signal32(unsigned long sig, s
213 unsigned long tramp;
214
215 /* Set up Signal Frame */
216 - frame = get_sigframe(ka, regs, sizeof(*frame), 1);
217 + frame = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*frame), 1);
218 if (unlikely(frame == NULL))
219 goto badframe;
220 sc = (struct sigcontext __user *) &frame->sctx;
221 --- a/arch/powerpc/kernel/signal_64.c
222 +++ b/arch/powerpc/kernel/signal_64.c
223 @@ -154,11 +154,12 @@ static long setup_sigcontext(struct sigc
224 * As above, but Transactional Memory is in use, so deliver sigcontexts
225 * containing checkpointed and transactional register states.
226 *
227 - * To do this, we treclaim to gather both sets of registers and set up the
228 - * 'normal' sigcontext registers with rolled-back register values such that a
229 - * simple signal handler sees a correct checkpointed register state.
230 - * If interested, a TM-aware sighandler can examine the transactional registers
231 - * in the 2nd sigcontext to determine the real origin of the signal.
232 + * To do this, we treclaim (done before entering here) to gather both sets of
233 + * registers and set up the 'normal' sigcontext registers with rolled-back
234 + * register values such that a simple signal handler sees a correct
235 + * checkpointed register state. If interested, a TM-aware sighandler can
236 + * examine the transactional registers in the 2nd sigcontext to determine the
237 + * real origin of the signal.
238 */
239 static long setup_tm_sigcontexts(struct sigcontext __user *sc,
240 struct sigcontext __user *tm_sc,
241 @@ -184,16 +185,6 @@ static long setup_tm_sigcontexts(struct
242
243 BUG_ON(!MSR_TM_ACTIVE(regs->msr));
244
245 - /* tm_reclaim rolls back all reg states, saving checkpointed (older)
246 - * GPRs to thread.ckpt_regs and (if used) FPRs to (newer)
247 - * thread.transact_fp and/or VRs to (newer) thread.transact_vr.
248 - * THEN we save out FP/VRs, if necessary, to the checkpointed (older)
249 - * thread.fr[]/vr[]s. The transactional (newer) GPRs are on the
250 - * stack, in *regs.
251 - */
252 - tm_enable();
253 - tm_reclaim(&current->thread, msr, TM_CAUSE_SIGNAL);
254 -
255 flush_fp_to_thread(current);
256
257 #ifdef CONFIG_ALTIVEC
258 @@ -711,7 +702,7 @@ int handle_rt_signal64(int signr, struct
259 unsigned long newsp = 0;
260 long err = 0;
261
262 - frame = get_sigframe(ka, regs, sizeof(*frame), 0);
263 + frame = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*frame), 0);
264 if (unlikely(frame == NULL))
265 goto badframe;
266