aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/sched.h2
-rw-r--r--init/main.c2
-rw-r--r--kernel/signal.c9
3 files changed, 10 insertions, 3 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 0917b3df12d5..fe970cdca83c 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -561,6 +561,8 @@ struct signal_struct {
561#define SIGNAL_CLD_CONTINUED 0x00000020 561#define SIGNAL_CLD_CONTINUED 0x00000020
562#define SIGNAL_CLD_MASK (SIGNAL_CLD_STOPPED|SIGNAL_CLD_CONTINUED) 562#define SIGNAL_CLD_MASK (SIGNAL_CLD_STOPPED|SIGNAL_CLD_CONTINUED)
563 563
564#define SIGNAL_UNKILLABLE 0x00000040 /* for init: ignore fatal signals */
565
564/* If true, all threads except ->group_exit_task have pending SIGKILL */ 566/* If true, all threads except ->group_exit_task have pending SIGKILL */
565static inline int signal_group_exit(const struct signal_struct *sig) 567static inline int signal_group_exit(const struct signal_struct *sig)
566{ 568{
diff --git a/init/main.c b/init/main.c
index 624266b524d4..1f4406477f83 100644
--- a/init/main.c
+++ b/init/main.c
@@ -802,6 +802,8 @@ static int noinline init_post(void)
802 (void) sys_dup(0); 802 (void) sys_dup(0);
803 (void) sys_dup(0); 803 (void) sys_dup(0);
804 804
805 current->signal->flags |= SIGNAL_UNKILLABLE;
806
805 if (ramdisk_execute_command) { 807 if (ramdisk_execute_command) {
806 run_init_process(ramdisk_execute_command); 808 run_init_process(ramdisk_execute_command);
807 printk(KERN_WARNING "Failed to execute %s\n", 809 printk(KERN_WARNING "Failed to execute %s\n",
diff --git a/kernel/signal.c b/kernel/signal.c
index 02ef3548aeb0..646a8765696a 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -728,7 +728,8 @@ static void complete_signal(int sig, struct task_struct *p, int group)
728 * Found a killable thread. If the signal will be fatal, 728 * Found a killable thread. If the signal will be fatal,
729 * then start taking the whole group down immediately. 729 * then start taking the whole group down immediately.
730 */ 730 */
731 if (sig_fatal(p, sig) && !(signal->flags & SIGNAL_GROUP_EXIT) && 731 if (sig_fatal(p, sig) &&
732 !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) &&
732 !sigismember(&t->real_blocked, sig) && 733 !sigismember(&t->real_blocked, sig) &&
733 (sig == SIGKILL || !(t->ptrace & PT_PTRACED))) { 734 (sig == SIGKILL || !(t->ptrace & PT_PTRACED))) {
734 /* 735 /*
@@ -1615,7 +1616,8 @@ static int do_signal_stop(int signr)
1615 } else { 1616 } else {
1616 struct task_struct *t; 1617 struct task_struct *t;
1617 1618
1618 if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED) || 1619 if (unlikely((sig->flags & (SIGNAL_STOP_DEQUEUED | SIGNAL_UNKILLABLE))
1620 != SIGNAL_STOP_DEQUEUED) ||
1619 unlikely(signal_group_exit(sig))) 1621 unlikely(signal_group_exit(sig)))
1620 return 0; 1622 return 0;
1621 /* 1623 /*
@@ -1761,7 +1763,8 @@ relock:
1761 /* 1763 /*
1762 * Global init gets no signals it doesn't want. 1764 * Global init gets no signals it doesn't want.
1763 */ 1765 */
1764 if (is_global_init(current)) 1766 if (unlikely(signal->flags & SIGNAL_UNKILLABLE) &&
1767 !signal_group_exit(signal))
1765 continue; 1768 continue;
1766 1769
1767 if (sig_kernel_stop(signr)) { 1770 if (sig_kernel_stop(signr)) {