aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/signal.c')
-rw-r--r--arch/x86/kernel/signal.c60
1 files changed, 13 insertions, 47 deletions
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index 2e937a5ad531..21af737053aa 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -555,7 +555,6 @@ unsigned long sys_sigreturn(struct pt_regs *regs)
555 sizeof(frame->extramask)))) 555 sizeof(frame->extramask))))
556 goto badframe; 556 goto badframe;
557 557
558 sigdelsetmask(&set, ~_BLOCKABLE);
559 set_current_blocked(&set); 558 set_current_blocked(&set);
560 559
561 if (restore_sigcontext(regs, &frame->sc, &ax)) 560 if (restore_sigcontext(regs, &frame->sc, &ax))
@@ -581,7 +580,6 @@ long sys_rt_sigreturn(struct pt_regs *regs)
581 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) 580 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
582 goto badframe; 581 goto badframe;
583 582
584 sigdelsetmask(&set, ~_BLOCKABLE);
585 set_current_blocked(&set); 583 set_current_blocked(&set);
586 584
587 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) 585 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
@@ -647,42 +645,28 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
647 struct pt_regs *regs) 645 struct pt_regs *regs)
648{ 646{
649 int usig = signr_convert(sig); 647 int usig = signr_convert(sig);
650 sigset_t *set = &current->blocked; 648 sigset_t *set = sigmask_to_save();
651 int ret;
652
653 if (current_thread_info()->status & TS_RESTORE_SIGMASK)
654 set = &current->saved_sigmask;
655 649
656 /* Set up the stack frame */ 650 /* Set up the stack frame */
657 if (is_ia32) { 651 if (is_ia32) {
658 if (ka->sa.sa_flags & SA_SIGINFO) 652 if (ka->sa.sa_flags & SA_SIGINFO)
659 ret = ia32_setup_rt_frame(usig, ka, info, set, regs); 653 return ia32_setup_rt_frame(usig, ka, info, set, regs);
660 else 654 else
661 ret = ia32_setup_frame(usig, ka, set, regs); 655 return ia32_setup_frame(usig, ka, set, regs);
662#ifdef CONFIG_X86_X32_ABI 656#ifdef CONFIG_X86_X32_ABI
663 } else if (is_x32) { 657 } else if (is_x32) {
664 ret = x32_setup_rt_frame(usig, ka, info, 658 return x32_setup_rt_frame(usig, ka, info,
665 (compat_sigset_t *)set, regs); 659 (compat_sigset_t *)set, regs);
666#endif 660#endif
667 } else { 661 } else {
668 ret = __setup_rt_frame(sig, ka, info, set, regs); 662 return __setup_rt_frame(sig, ka, info, set, regs);
669 }
670
671 if (ret) {
672 force_sigsegv(sig, current);
673 return -EFAULT;
674 } 663 }
675
676 current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
677 return ret;
678} 664}
679 665
680static int 666static void
681handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, 667handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
682 struct pt_regs *regs) 668 struct pt_regs *regs)
683{ 669{
684 int ret;
685
686 /* Are we from a system call? */ 670 /* Are we from a system call? */
687 if (syscall_get_nr(current, regs) >= 0) { 671 if (syscall_get_nr(current, regs) >= 0) {
688 /* If so, check system call restarting.. */ 672 /* If so, check system call restarting.. */
@@ -713,10 +697,10 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
713 likely(test_and_clear_thread_flag(TIF_FORCED_TF))) 697 likely(test_and_clear_thread_flag(TIF_FORCED_TF)))
714 regs->flags &= ~X86_EFLAGS_TF; 698 regs->flags &= ~X86_EFLAGS_TF;
715 699
716 ret = setup_rt_frame(sig, ka, info, regs); 700 if (setup_rt_frame(sig, ka, info, regs) < 0) {
717 701 force_sigsegv(sig, current);
718 if (ret) 702 return;
719 return ret; 703 }
720 704
721 /* 705 /*
722 * Clear the direction flag as per the ABI for function entry. 706 * Clear the direction flag as per the ABI for function entry.
@@ -731,12 +715,8 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
731 */ 715 */
732 regs->flags &= ~X86_EFLAGS_TF; 716 regs->flags &= ~X86_EFLAGS_TF;
733 717
734 block_sigmask(ka, sig); 718 signal_delivered(sig, info, ka, regs,
735 719 test_thread_flag(TIF_SINGLESTEP));
736 tracehook_signal_handler(sig, info, ka, regs,
737 test_thread_flag(TIF_SINGLESTEP));
738
739 return 0;
740} 720}
741 721
742#ifdef CONFIG_X86_32 722#ifdef CONFIG_X86_32
@@ -757,16 +737,6 @@ static void do_signal(struct pt_regs *regs)
757 siginfo_t info; 737 siginfo_t info;
758 int signr; 738 int signr;
759 739
760 /*
761 * We want the common case to go fast, which is why we may in certain
762 * cases get here from kernel mode. Just return without doing anything
763 * if so.
764 * X86_32: vm86 regs switched out by assembly code before reaching
765 * here, so testing against kernel CS suffices.
766 */
767 if (!user_mode(regs))
768 return;
769
770 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 740 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
771 if (signr > 0) { 741 if (signr > 0) {
772 /* Whee! Actually deliver the signal. */ 742 /* Whee! Actually deliver the signal. */
@@ -796,10 +766,7 @@ static void do_signal(struct pt_regs *regs)
796 * If there's no signal to deliver, we just put the saved sigmask 766 * If there's no signal to deliver, we just put the saved sigmask
797 * back. 767 * back.
798 */ 768 */
799 if (current_thread_info()->status & TS_RESTORE_SIGMASK) { 769 restore_saved_sigmask();
800 current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
801 set_current_blocked(&current->saved_sigmask);
802 }
803} 770}
804 771
805/* 772/*
@@ -934,7 +901,6 @@ asmlinkage long sys32_x32_rt_sigreturn(struct pt_regs *regs)
934 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) 901 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
935 goto badframe; 902 goto badframe;
936 903
937 sigdelsetmask(&set, ~_BLOCKABLE);
938 set_current_blocked(&set); 904 set_current_blocked(&set);
939 905
940 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) 906 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))