aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/tracehook.h19
-rw-r--r--kernel/signal.c27
2 files changed, 35 insertions, 11 deletions
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h
index 2d1426f8e33b..8cffd34f88d5 100644
--- a/include/linux/tracehook.h
+++ b/include/linux/tracehook.h
@@ -312,4 +312,23 @@ static inline void tracehook_signal_handler(int sig, siginfo_t *info,
312 ptrace_notify(SIGTRAP); 312 ptrace_notify(SIGTRAP);
313} 313}
314 314
315/**
316 * tracehook_consider_ignored_signal - suppress short-circuit of ignored signal
317 * @task: task receiving the signal
318 * @sig: signal number being sent
319 * @handler: %SIG_IGN or %SIG_DFL
320 *
321 * Return zero iff tracing doesn't care to examine this ignored signal,
322 * so it can short-circuit normal delivery and never even get queued.
323 * Either @handler is %SIG_DFL and @sig's default is ignore, or it's %SIG_IGN.
324 *
325 * Called with @task->sighand->siglock held.
326 */
327static inline int tracehook_consider_ignored_signal(struct task_struct *task,
328 int sig,
329 void __user *handler)
330{
331 return (task_ptrace(task) & PT_PTRACED) != 0;
332}
333
315#endif /* <linux/tracehook.h> */ 334#endif /* <linux/tracehook.h> */
diff --git a/kernel/signal.c b/kernel/signal.c
index 8715c18b27b9..9efd1cee6d0b 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -22,6 +22,7 @@
22#include <linux/ptrace.h> 22#include <linux/ptrace.h>
23#include <linux/signal.h> 23#include <linux/signal.h>
24#include <linux/signalfd.h> 24#include <linux/signalfd.h>
25#include <linux/tracehook.h>
25#include <linux/capability.h> 26#include <linux/capability.h>
26#include <linux/freezer.h> 27#include <linux/freezer.h>
27#include <linux/pid_namespace.h> 28#include <linux/pid_namespace.h>
@@ -39,24 +40,21 @@
39 40
40static struct kmem_cache *sigqueue_cachep; 41static struct kmem_cache *sigqueue_cachep;
41 42
42static int __sig_ignored(struct task_struct *t, int sig) 43static void __user *sig_handler(struct task_struct *t, int sig)
43{ 44{
44 void __user *handler; 45 return t->sighand->action[sig - 1].sa.sa_handler;
46}
45 47
48static int sig_handler_ignored(void __user *handler, int sig)
49{
46 /* Is it explicitly or implicitly ignored? */ 50 /* Is it explicitly or implicitly ignored? */
47
48 handler = t->sighand->action[sig - 1].sa.sa_handler;
49 return handler == SIG_IGN || 51 return handler == SIG_IGN ||
50 (handler == SIG_DFL && sig_kernel_ignore(sig)); 52 (handler == SIG_DFL && sig_kernel_ignore(sig));
51} 53}
52 54
53static int sig_ignored(struct task_struct *t, int sig) 55static int sig_ignored(struct task_struct *t, int sig)
54{ 56{
55 /* 57 void __user *handler;
56 * Tracers always want to know about signals..
57 */
58 if (t->ptrace & PT_PTRACED)
59 return 0;
60 58
61 /* 59 /*
62 * Blocked signals are never ignored, since the 60 * Blocked signals are never ignored, since the
@@ -66,7 +64,14 @@ static int sig_ignored(struct task_struct *t, int sig)
66 if (sigismember(&t->blocked, sig) || sigismember(&t->real_blocked, sig)) 64 if (sigismember(&t->blocked, sig) || sigismember(&t->real_blocked, sig))
67 return 0; 65 return 0;
68 66
69 return __sig_ignored(t, sig); 67 handler = sig_handler(t, sig);
68 if (!sig_handler_ignored(handler, sig))
69 return 0;
70
71 /*
72 * Tracers may want to know about even ignored signals.
73 */
74 return !tracehook_consider_ignored_signal(t, sig, handler);
70} 75}
71 76
72/* 77/*
@@ -2298,7 +2303,7 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
2298 * (for example, SIGCHLD), shall cause the pending signal to 2303 * (for example, SIGCHLD), shall cause the pending signal to
2299 * be discarded, whether or not it is blocked" 2304 * be discarded, whether or not it is blocked"
2300 */ 2305 */
2301 if (__sig_ignored(t, sig)) { 2306 if (sig_handler_ignored(sig_handler(t, sig), sig)) {
2302 sigemptyset(&mask); 2307 sigemptyset(&mask);
2303 sigaddset(&mask, sig); 2308 sigaddset(&mask, sig);
2304 rm_from_queue_full(&mask, &t->signal->shared_pending); 2309 rm_from_queue_full(&mask, &t->signal->shared_pending);