diff options
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 27 |
1 files changed, 16 insertions, 11 deletions
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 | ||
40 | static struct kmem_cache *sigqueue_cachep; | 41 | static struct kmem_cache *sigqueue_cachep; |
41 | 42 | ||
42 | static int __sig_ignored(struct task_struct *t, int sig) | 43 | static 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 | ||
48 | static 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 | ||
53 | static int sig_ignored(struct task_struct *t, int sig) | 55 | static 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); |