aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/signal.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index 7fe874d12fae..bfdb5686fa3e 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -791,22 +791,31 @@ out:
791/* 791/*
792 * Force a signal that the process can't ignore: if necessary 792 * Force a signal that the process can't ignore: if necessary
793 * we unblock the signal and change any SIG_IGN to SIG_DFL. 793 * we unblock the signal and change any SIG_IGN to SIG_DFL.
794 *
795 * Note: If we unblock the signal, we always reset it to SIG_DFL,
796 * since we do not want to have a signal handler that was blocked
797 * be invoked when user space had explicitly blocked it.
798 *
799 * We don't want to have recursive SIGSEGV's etc, for example.
794 */ 800 */
795
796int 801int
797force_sig_info(int sig, struct siginfo *info, struct task_struct *t) 802force_sig_info(int sig, struct siginfo *info, struct task_struct *t)
798{ 803{
799 unsigned long int flags; 804 unsigned long int flags;
800 int ret; 805 int ret, blocked, ignored;
806 struct k_sigaction *action;
801 807
802 spin_lock_irqsave(&t->sighand->siglock, flags); 808 spin_lock_irqsave(&t->sighand->siglock, flags);
803 if (t->sighand->action[sig-1].sa.sa_handler == SIG_IGN) { 809 action = &t->sighand->action[sig-1];
804 t->sighand->action[sig-1].sa.sa_handler = SIG_DFL; 810 ignored = action->sa.sa_handler == SIG_IGN;
805 } 811 blocked = sigismember(&t->blocked, sig);
806 if (sigismember(&t->blocked, sig)) { 812 if (blocked || ignored) {
807 sigdelset(&t->blocked, sig); 813 action->sa.sa_handler = SIG_DFL;
814 if (blocked) {
815 sigdelset(&t->blocked, sig);
816 recalc_sigpending_tsk(t);
817 }
808 } 818 }
809 recalc_sigpending_tsk(t);
810 ret = specific_send_sig_info(sig, info, t); 819 ret = specific_send_sig_info(sig, info, t);
811 spin_unlock_irqrestore(&t->sighand->siglock, flags); 820 spin_unlock_irqrestore(&t->sighand->siglock, flags);
812 821