diff options
-rw-r--r-- | include/linux/sched.h | 2 | ||||
-rw-r--r-- | init/main.c | 2 | ||||
-rw-r--r-- | kernel/signal.c | 9 |
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 */ |
565 | static inline int signal_group_exit(const struct signal_struct *sig) | 567 | static 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)) { |