diff options
Diffstat (limited to 'arch/x86/kernel/signal_32.c')
-rw-r--r-- | arch/x86/kernel/signal_32.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 6fb5bcdd8933..19a7a5669b5b 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c | |||
@@ -306,7 +306,8 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate, | |||
306 | * Determine which stack to use.. | 306 | * Determine which stack to use.. |
307 | */ | 307 | */ |
308 | static inline void __user * | 308 | static inline void __user * |
309 | get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) | 309 | get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, |
310 | struct _fpstate **fpstate) | ||
310 | { | 311 | { |
311 | unsigned long sp; | 312 | unsigned long sp; |
312 | 313 | ||
@@ -332,6 +333,11 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) | |||
332 | sp = (unsigned long) ka->sa.sa_restorer; | 333 | sp = (unsigned long) ka->sa.sa_restorer; |
333 | } | 334 | } |
334 | 335 | ||
336 | if (used_math()) { | ||
337 | sp = sp - sig_xstate_size; | ||
338 | *fpstate = (struct _fpstate *) sp; | ||
339 | } | ||
340 | |||
335 | sp -= frame_size; | 341 | sp -= frame_size; |
336 | /* | 342 | /* |
337 | * Align the stack pointer according to the i386 ABI, | 343 | * Align the stack pointer according to the i386 ABI, |
@@ -350,8 +356,9 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | |||
350 | void __user *restorer; | 356 | void __user *restorer; |
351 | int err = 0; | 357 | int err = 0; |
352 | int usig; | 358 | int usig; |
359 | struct _fpstate __user *fpstate = NULL; | ||
353 | 360 | ||
354 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 361 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); |
355 | 362 | ||
356 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 363 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
357 | goto give_sigsegv; | 364 | goto give_sigsegv; |
@@ -366,7 +373,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | |||
366 | if (err) | 373 | if (err) |
367 | goto give_sigsegv; | 374 | goto give_sigsegv; |
368 | 375 | ||
369 | err = setup_sigcontext(&frame->sc, &frame->fpstate, regs, set->sig[0]); | 376 | err = setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]); |
370 | if (err) | 377 | if (err) |
371 | goto give_sigsegv; | 378 | goto give_sigsegv; |
372 | 379 | ||
@@ -427,8 +434,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
427 | void __user *restorer; | 434 | void __user *restorer; |
428 | int err = 0; | 435 | int err = 0; |
429 | int usig; | 436 | int usig; |
437 | struct _fpstate __user *fpstate = NULL; | ||
430 | 438 | ||
431 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 439 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); |
432 | 440 | ||
433 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 441 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
434 | goto give_sigsegv; | 442 | goto give_sigsegv; |
@@ -453,7 +461,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
453 | err |= __put_user(sas_ss_flags(regs->sp), | 461 | err |= __put_user(sas_ss_flags(regs->sp), |
454 | &frame->uc.uc_stack.ss_flags); | 462 | &frame->uc.uc_stack.ss_flags); |
455 | err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); | 463 | err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); |
456 | err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, | 464 | err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, |
457 | regs, set->sig[0]); | 465 | regs, set->sig[0]); |
458 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 466 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
459 | if (err) | 467 | if (err) |