diff options
Diffstat (limited to 'arch/x86/ia32/ia32_signal.c')
-rw-r--r-- | arch/x86/ia32/ia32_signal.c | 31 |
1 files changed, 19 insertions, 12 deletions
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 673ac9b63d6b..efc6a958b71d 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <asm/sigframe.h> | 32 | #include <asm/sigframe.h> |
33 | #include <asm/sighandling.h> | 33 | #include <asm/sighandling.h> |
34 | #include <asm/sys_ia32.h> | 34 | #include <asm/sys_ia32.h> |
35 | #include <asm/smap.h> | ||
35 | 36 | ||
36 | #define FIX_EFLAGS __FIX_EFLAGS | 37 | #define FIX_EFLAGS __FIX_EFLAGS |
37 | 38 | ||
@@ -162,7 +163,8 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr, | |||
162 | } | 163 | } |
163 | seg = get_fs(); | 164 | seg = get_fs(); |
164 | set_fs(KERNEL_DS); | 165 | set_fs(KERNEL_DS); |
165 | ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->sp); | 166 | ret = do_sigaltstack((stack_t __force __user *) (uss_ptr ? &uss : NULL), |
167 | (stack_t __force __user *) &uoss, regs->sp); | ||
166 | set_fs(seg); | 168 | set_fs(seg); |
167 | if (ret >= 0 && uoss_ptr) { | 169 | if (ret >= 0 && uoss_ptr) { |
168 | if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t))) | 170 | if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t))) |
@@ -250,11 +252,12 @@ static int ia32_restore_sigcontext(struct pt_regs *regs, | |||
250 | 252 | ||
251 | get_user_ex(tmp, &sc->fpstate); | 253 | get_user_ex(tmp, &sc->fpstate); |
252 | buf = compat_ptr(tmp); | 254 | buf = compat_ptr(tmp); |
253 | err |= restore_i387_xstate_ia32(buf); | ||
254 | 255 | ||
255 | get_user_ex(*pax, &sc->ax); | 256 | get_user_ex(*pax, &sc->ax); |
256 | } get_user_catch(err); | 257 | } get_user_catch(err); |
257 | 258 | ||
259 | err |= restore_xstate_sig(buf, 1); | ||
260 | |||
258 | return err; | 261 | return err; |
259 | } | 262 | } |
260 | 263 | ||
@@ -361,7 +364,7 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, | |||
361 | */ | 364 | */ |
362 | static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | 365 | static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, |
363 | size_t frame_size, | 366 | size_t frame_size, |
364 | void **fpstate) | 367 | void __user **fpstate) |
365 | { | 368 | { |
366 | unsigned long sp; | 369 | unsigned long sp; |
367 | 370 | ||
@@ -381,9 +384,12 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | |||
381 | sp = (unsigned long) ka->sa.sa_restorer; | 384 | sp = (unsigned long) ka->sa.sa_restorer; |
382 | 385 | ||
383 | if (used_math()) { | 386 | if (used_math()) { |
384 | sp = sp - sig_xstate_ia32_size; | 387 | unsigned long fx_aligned, math_size; |
385 | *fpstate = (struct _fpstate_ia32 *) sp; | 388 | |
386 | if (save_i387_xstate_ia32(*fpstate) < 0) | 389 | sp = alloc_mathframe(sp, 1, &fx_aligned, &math_size); |
390 | *fpstate = (struct _fpstate_ia32 __user *) sp; | ||
391 | if (save_xstate_sig(*fpstate, (void __user *)fx_aligned, | ||
392 | math_size) < 0) | ||
387 | return (void __user *) -1L; | 393 | return (void __user *) -1L; |
388 | } | 394 | } |
389 | 395 | ||
@@ -448,7 +454,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka, | |||
448 | * These are actually not used anymore, but left because some | 454 | * These are actually not used anymore, but left because some |
449 | * gdb versions depend on them as a marker. | 455 | * gdb versions depend on them as a marker. |
450 | */ | 456 | */ |
451 | put_user_ex(*((u64 *)&code), (u64 *)frame->retcode); | 457 | put_user_ex(*((u64 *)&code), (u64 __user *)frame->retcode); |
452 | } put_user_catch(err); | 458 | } put_user_catch(err); |
453 | 459 | ||
454 | if (err) | 460 | if (err) |
@@ -502,7 +508,6 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
502 | put_user_ex(sig, &frame->sig); | 508 | put_user_ex(sig, &frame->sig); |
503 | put_user_ex(ptr_to_compat(&frame->info), &frame->pinfo); | 509 | put_user_ex(ptr_to_compat(&frame->info), &frame->pinfo); |
504 | put_user_ex(ptr_to_compat(&frame->uc), &frame->puc); | 510 | put_user_ex(ptr_to_compat(&frame->uc), &frame->puc); |
505 | err |= copy_siginfo_to_user32(&frame->info, info); | ||
506 | 511 | ||
507 | /* Create the ucontext. */ | 512 | /* Create the ucontext. */ |
508 | if (cpu_has_xsave) | 513 | if (cpu_has_xsave) |
@@ -514,9 +519,6 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
514 | put_user_ex(sas_ss_flags(regs->sp), | 519 | put_user_ex(sas_ss_flags(regs->sp), |
515 | &frame->uc.uc_stack.ss_flags); | 520 | &frame->uc.uc_stack.ss_flags); |
516 | put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size); | 521 | put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size); |
517 | err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate, | ||
518 | regs, set->sig[0]); | ||
519 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | ||
520 | 522 | ||
521 | if (ka->sa.sa_flags & SA_RESTORER) | 523 | if (ka->sa.sa_flags & SA_RESTORER) |
522 | restorer = ka->sa.sa_restorer; | 524 | restorer = ka->sa.sa_restorer; |
@@ -529,9 +531,14 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
529 | * Not actually used anymore, but left because some gdb | 531 | * Not actually used anymore, but left because some gdb |
530 | * versions need it. | 532 | * versions need it. |
531 | */ | 533 | */ |
532 | put_user_ex(*((u64 *)&code), (u64 *)frame->retcode); | 534 | put_user_ex(*((u64 *)&code), (u64 __user *)frame->retcode); |
533 | } put_user_catch(err); | 535 | } put_user_catch(err); |
534 | 536 | ||
537 | err |= copy_siginfo_to_user32(&frame->info, info); | ||
538 | err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate, | ||
539 | regs, set->sig[0]); | ||
540 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | ||
541 | |||
535 | if (err) | 542 | if (err) |
536 | return -EFAULT; | 543 | return -EFAULT; |
537 | 544 | ||