diff options
-rw-r--r-- | include/linux/tracehook.h | 21 | ||||
-rw-r--r-- | kernel/signal.c | 9 |
2 files changed, 26 insertions, 4 deletions
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h index 8cffd34f88d5..8b4c15e208fe 100644 --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h | |||
@@ -331,4 +331,25 @@ static inline int tracehook_consider_ignored_signal(struct task_struct *task, | |||
331 | return (task_ptrace(task) & PT_PTRACED) != 0; | 331 | return (task_ptrace(task) & PT_PTRACED) != 0; |
332 | } | 332 | } |
333 | 333 | ||
334 | /** | ||
335 | * tracehook_consider_fatal_signal - suppress special handling of fatal signal | ||
336 | * @task: task receiving the signal | ||
337 | * @sig: signal number being sent | ||
338 | * @handler: %SIG_DFL or %SIG_IGN | ||
339 | * | ||
340 | * Return nonzero to prevent special handling of this termination signal. | ||
341 | * Normally @handler is %SIG_DFL. It can be %SIG_IGN if @sig is ignored, | ||
342 | * in which case force_sig() is about to reset it to %SIG_DFL. | ||
343 | * When this returns zero, this signal might cause a quick termination | ||
344 | * that does not give the debugger a chance to intercept the signal. | ||
345 | * | ||
346 | * Called with or without @task->sighand->siglock held. | ||
347 | */ | ||
348 | static inline int tracehook_consider_fatal_signal(struct task_struct *task, | ||
349 | int sig, | ||
350 | void __user *handler) | ||
351 | { | ||
352 | return (task_ptrace(task) & PT_PTRACED) != 0; | ||
353 | } | ||
354 | |||
334 | #endif /* <linux/tracehook.h> */ | 355 | #endif /* <linux/tracehook.h> */ |
diff --git a/kernel/signal.c b/kernel/signal.c index 9efd1cee6d0b..1a942ce32ba0 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -300,12 +300,12 @@ flush_signal_handlers(struct task_struct *t, int force_default) | |||
300 | 300 | ||
301 | int unhandled_signal(struct task_struct *tsk, int sig) | 301 | int unhandled_signal(struct task_struct *tsk, int sig) |
302 | { | 302 | { |
303 | void __user *handler = tsk->sighand->action[sig-1].sa.sa_handler; | ||
303 | if (is_global_init(tsk)) | 304 | if (is_global_init(tsk)) |
304 | return 1; | 305 | return 1; |
305 | if (tsk->ptrace & PT_PTRACED) | 306 | if (handler != SIG_IGN && handler != SIG_DFL) |
306 | return 0; | 307 | return 0; |
307 | return (tsk->sighand->action[sig-1].sa.sa_handler == SIG_IGN) || | 308 | return !tracehook_consider_fatal_signal(tsk, sig, handler); |
308 | (tsk->sighand->action[sig-1].sa.sa_handler == SIG_DFL); | ||
309 | } | 309 | } |
310 | 310 | ||
311 | 311 | ||
@@ -761,7 +761,8 @@ static void complete_signal(int sig, struct task_struct *p, int group) | |||
761 | if (sig_fatal(p, sig) && | 761 | if (sig_fatal(p, sig) && |
762 | !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) && | 762 | !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) && |
763 | !sigismember(&t->real_blocked, sig) && | 763 | !sigismember(&t->real_blocked, sig) && |
764 | (sig == SIGKILL || !(t->ptrace & PT_PTRACED))) { | 764 | (sig == SIGKILL || |
765 | !tracehook_consider_fatal_signal(t, sig, SIG_DFL))) { | ||
765 | /* | 766 | /* |
766 | * This signal will be fatal to the whole group. | 767 | * This signal will be fatal to the whole group. |
767 | */ | 768 | */ |