diff options
Diffstat (limited to 'arch/x86/kernel/signal.c')
-rw-r--r-- | arch/x86/kernel/signal.c | 60 |
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 = ¤t->blocked; | 648 | sigset_t *set = sigmask_to_save(); |
651 | int ret; | ||
652 | |||
653 | if (current_thread_info()->status & TS_RESTORE_SIGMASK) | ||
654 | set = ¤t->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 | ||
680 | static int | 666 | static void |
681 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | 667 | handle_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(¤t->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)) |