aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/signal.c97
1 files changed, 41 insertions, 56 deletions
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index 89ef90df985f..53425c681f2b 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -187,28 +187,6 @@ setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
187/* 187/*
188 * Set up a signal frame. 188 * Set up a signal frame.
189 */ 189 */
190#ifdef CONFIG_X86_32
191static const struct {
192 u16 poplmovl;
193 u32 val;
194 u16 int80;
195} __attribute__((packed)) retcode = {
196 0xb858, /* popl %eax; movl $..., %eax */
197 __NR_sigreturn,
198 0x80cd, /* int $0x80 */
199};
200
201static const struct {
202 u8 movl;
203 u32 val;
204 u16 int80;
205 u8 pad;
206} __attribute__((packed)) rt_retcode = {
207 0xb8, /* movl $..., %eax */
208 __NR_rt_sigreturn,
209 0x80cd, /* int $0x80 */
210 0
211};
212 190
213/* 191/*
214 * Determine which stack to use.. 192 * Determine which stack to use..
@@ -217,10 +195,13 @@ static inline void __user *
217get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, 195get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
218 void __user **fpstate) 196 void __user **fpstate)
219{ 197{
220 unsigned long sp;
221
222 /* Default to using normal stack */ 198 /* Default to using normal stack */
223 sp = regs->sp; 199 unsigned long sp = regs->sp;
200
201#ifdef CONFIG_X86_64
202 /* redzone */
203 sp -= 128;
204#endif /* CONFIG_X86_64 */
224 205
225 /* 206 /*
226 * If we are on the alternate signal stack and would overflow it, don't. 207 * If we are on the alternate signal stack and would overflow it, don't.
@@ -234,30 +215,64 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
234 if (sas_ss_flags(sp) == 0) 215 if (sas_ss_flags(sp) == 0)
235 sp = current->sas_ss_sp + current->sas_ss_size; 216 sp = current->sas_ss_sp + current->sas_ss_size;
236 } else { 217 } else {
218#ifdef CONFIG_X86_32
237 /* This is the legacy signal stack switching. */ 219 /* This is the legacy signal stack switching. */
238 if ((regs->ss & 0xffff) != __USER_DS && 220 if ((regs->ss & 0xffff) != __USER_DS &&
239 !(ka->sa.sa_flags & SA_RESTORER) && 221 !(ka->sa.sa_flags & SA_RESTORER) &&
240 ka->sa.sa_restorer) 222 ka->sa.sa_restorer)
241 sp = (unsigned long) ka->sa.sa_restorer; 223 sp = (unsigned long) ka->sa.sa_restorer;
224#endif /* CONFIG_X86_32 */
242 } 225 }
243 226
244 if (used_math()) { 227 if (used_math()) {
245 sp = sp - sig_xstate_size; 228 sp -= sig_xstate_size;
229#ifdef CONFIG_X86_32
246 *fpstate = (void __user *) sp; 230 *fpstate = (void __user *) sp;
231#else /* !CONFIG_X86_32 */
232 *fpstate = (void __user *)round_down(sp, 64);
233#endif /* CONFIG_X86_32 */
234
247 if (save_i387_xstate(*fpstate) < 0) 235 if (save_i387_xstate(*fpstate) < 0)
248 return (void __user *)-1L; 236 return (void __user *)-1L;
249 } 237 }
250 238
251 sp -= frame_size; 239 sp -= frame_size;
240#ifdef CONFIG_X86_32
252 /* 241 /*
253 * Align the stack pointer according to the i386 ABI, 242 * Align the stack pointer according to the i386 ABI,
254 * i.e. so that on function entry ((sp + 4) & 15) == 0. 243 * i.e. so that on function entry ((sp + 4) & 15) == 0.
255 */ 244 */
256 sp = ((sp + 4) & -16ul) - 4; 245 sp = ((sp + 4) & -16ul) - 4;
246#else /* !CONFIG_X86_32 */
247 sp = round_down(sp, 16) - 8;
248#endif
257 249
258 return (void __user *) sp; 250 return (void __user *) sp;
259} 251}
260 252
253#ifdef CONFIG_X86_32
254static const struct {
255 u16 poplmovl;
256 u32 val;
257 u16 int80;
258} __attribute__((packed)) retcode = {
259 0xb858, /* popl %eax; movl $..., %eax */
260 __NR_sigreturn,
261 0x80cd, /* int $0x80 */
262};
263
264static const struct {
265 u8 movl;
266 u32 val;
267 u16 int80;
268 u8 pad;
269} __attribute__((packed)) rt_retcode = {
270 0xb8, /* movl $..., %eax */
271 __NR_rt_sigreturn,
272 0x80cd, /* int $0x80 */
273 0
274};
275
261static int 276static int
262__setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, 277__setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
263 struct pt_regs *regs) 278 struct pt_regs *regs)
@@ -388,36 +403,6 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
388 return 0; 403 return 0;
389} 404}
390#else /* !CONFIG_X86_32 */ 405#else /* !CONFIG_X86_32 */
391/*
392 * Determine which stack to use..
393 */
394static void __user *
395get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
396 void __user **fpstate)
397{
398 unsigned long sp;
399
400 /* Default to using normal stack - redzone */
401 sp = regs->sp - 128;
402
403 /* This is the X/Open sanctioned signal stack switching. */
404 if (ka->sa.sa_flags & SA_ONSTACK) {
405 if (sas_ss_flags(sp) == 0)
406 sp = current->sas_ss_sp + current->sas_ss_size;
407 }
408
409 if (used_math()) {
410 sp -= sig_xstate_size;
411 *fpstate = (void __user *)round_down(sp, 64);
412
413 if (save_i387_xstate(*fpstate) < 0)
414 return (void __user *) -1L;
415 }
416
417 sp -= frame_size;
418 return (void __user *)round_down(sp, 16) - 8;
419}
420
421static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 406static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
422 sigset_t *set, struct pt_regs *regs) 407 sigset_t *set, struct pt_regs *regs)
423{ 408{