aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/kernel-parameters.txt11
-rw-r--r--include/linux/sched.h13
-rw-r--r--kernel/signal.c46
3 files changed, 52 insertions, 18 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 332fe3b47e0c..1d28812260cd 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -2031,8 +2031,15 @@ and is between 256 and 4096 characters. It is defined in the file
2031 2031
2032 print-fatal-signals= 2032 print-fatal-signals=
2033 [KNL] debug: print fatal signals 2033 [KNL] debug: print fatal signals
2034 print-fatal-signals=1: print segfault info to 2034
2035 the kernel console. 2035 If enabled, warn about various signal handling
2036 related application anomalies: too many signals,
2037 too many POSIX.1 timers, fatal signals causing a
2038 coredump - etc.
2039
2040 If you hit the warning due to signal overflow,
2041 you might want to try "ulimit -i unlimited".
2042
2036 default: off. 2043 default: off.
2037 2044
2038 printk.time= Show timing data prefixed to each printk message line 2045 printk.time= Show timing data prefixed to each printk message line
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 49be8f7c05f6..882dc48163b4 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2086,11 +2086,18 @@ static inline int is_si_special(const struct siginfo *info)
2086 return info <= SEND_SIG_FORCED; 2086 return info <= SEND_SIG_FORCED;
2087} 2087}
2088 2088
2089/* True if we are on the alternate signal stack. */ 2089/*
2090 2090 * True if we are on the alternate signal stack.
2091 */
2091static inline int on_sig_stack(unsigned long sp) 2092static inline int on_sig_stack(unsigned long sp)
2092{ 2093{
2093 return (sp - current->sas_ss_sp < current->sas_ss_size); 2094#ifdef CONFIG_STACK_GROWSUP
2095 return sp >= current->sas_ss_sp &&
2096 sp - current->sas_ss_sp < current->sas_ss_size;
2097#else
2098 return sp > current->sas_ss_sp &&
2099 sp - current->sas_ss_sp <= current->sas_ss_size;
2100#endif
2094} 2101}
2095 2102
2096static inline int sas_ss_flags(unsigned long sp) 2103static inline int sas_ss_flags(unsigned long sp)
diff --git a/kernel/signal.c b/kernel/signal.c
index 6705320784fd..fe08008133da 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/ratelimit.h>
25#include <linux/tracehook.h> 26#include <linux/tracehook.h>
26#include <linux/capability.h> 27#include <linux/capability.h>
27#include <linux/freezer.h> 28#include <linux/freezer.h>
@@ -41,6 +42,8 @@
41 42
42static struct kmem_cache *sigqueue_cachep; 43static struct kmem_cache *sigqueue_cachep;
43 44
45int print_fatal_signals __read_mostly;
46
44static void __user *sig_handler(struct task_struct *t, int sig) 47static void __user *sig_handler(struct task_struct *t, int sig)
45{ 48{
46 return t->sighand->action[sig - 1].sa.sa_handler; 49 return t->sighand->action[sig - 1].sa.sa_handler;
@@ -159,7 +162,7 @@ int next_signal(struct sigpending *pending, sigset_t *mask)
159{ 162{
160 unsigned long i, *s, *m, x; 163 unsigned long i, *s, *m, x;
161 int sig = 0; 164 int sig = 0;
162 165
163 s = pending->signal.sig; 166 s = pending->signal.sig;
164 m = mask->sig; 167 m = mask->sig;
165 switch (_NSIG_WORDS) { 168 switch (_NSIG_WORDS) {
@@ -184,17 +187,31 @@ int next_signal(struct sigpending *pending, sigset_t *mask)
184 sig = ffz(~x) + 1; 187 sig = ffz(~x) + 1;
185 break; 188 break;
186 } 189 }
187 190
188 return sig; 191 return sig;
189} 192}
190 193
194static inline void print_dropped_signal(int sig)
195{
196 static DEFINE_RATELIMIT_STATE(ratelimit_state, 5 * HZ, 10);
197
198 if (!print_fatal_signals)
199 return;
200
201 if (!__ratelimit(&ratelimit_state))
202 return;
203
204 printk(KERN_INFO "%s/%d: reached RLIMIT_SIGPENDING, dropped signal %d\n",
205 current->comm, current->pid, sig);
206}
207
191/* 208/*
192 * allocate a new signal queue record 209 * allocate a new signal queue record
193 * - this may be called without locks if and only if t == current, otherwise an 210 * - this may be called without locks if and only if t == current, otherwise an
194 * appopriate lock must be held to stop the target task from exiting 211 * appopriate lock must be held to stop the target task from exiting
195 */ 212 */
196static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags, 213static struct sigqueue *
197 int override_rlimit) 214__sigqueue_alloc(int sig, struct task_struct *t, gfp_t flags, int override_rlimit)
198{ 215{
199 struct sigqueue *q = NULL; 216 struct sigqueue *q = NULL;
200 struct user_struct *user; 217 struct user_struct *user;
@@ -207,10 +224,15 @@ static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags,
207 */ 224 */
208 user = get_uid(__task_cred(t)->user); 225 user = get_uid(__task_cred(t)->user);
209 atomic_inc(&user->sigpending); 226 atomic_inc(&user->sigpending);
227
210 if (override_rlimit || 228 if (override_rlimit ||
211 atomic_read(&user->sigpending) <= 229 atomic_read(&user->sigpending) <=
212 t->signal->rlim[RLIMIT_SIGPENDING].rlim_cur) 230 t->signal->rlim[RLIMIT_SIGPENDING].rlim_cur) {
213 q = kmem_cache_alloc(sigqueue_cachep, flags); 231 q = kmem_cache_alloc(sigqueue_cachep, flags);
232 } else {
233 print_dropped_signal(sig);
234 }
235
214 if (unlikely(q == NULL)) { 236 if (unlikely(q == NULL)) {
215 atomic_dec(&user->sigpending); 237 atomic_dec(&user->sigpending);
216 free_uid(user); 238 free_uid(user);
@@ -869,7 +891,7 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
869 else 891 else
870 override_rlimit = 0; 892 override_rlimit = 0;
871 893
872 q = __sigqueue_alloc(t, GFP_ATOMIC | __GFP_NOTRACK_FALSE_POSITIVE, 894 q = __sigqueue_alloc(sig, t, GFP_ATOMIC | __GFP_NOTRACK_FALSE_POSITIVE,
873 override_rlimit); 895 override_rlimit);
874 if (q) { 896 if (q) {
875 list_add_tail(&q->list, &pending->list); 897 list_add_tail(&q->list, &pending->list);
@@ -925,8 +947,6 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
925 return __send_signal(sig, info, t, group, from_ancestor_ns); 947 return __send_signal(sig, info, t, group, from_ancestor_ns);
926} 948}
927 949
928int print_fatal_signals;
929
930static void print_fatal_signal(struct pt_regs *regs, int signr) 950static void print_fatal_signal(struct pt_regs *regs, int signr)
931{ 951{
932 printk("%s/%d: potentially unexpected fatal signal %d.\n", 952 printk("%s/%d: potentially unexpected fatal signal %d.\n",
@@ -1293,19 +1313,19 @@ EXPORT_SYMBOL(kill_pid);
1293 * These functions support sending signals using preallocated sigqueue 1313 * These functions support sending signals using preallocated sigqueue
1294 * structures. This is needed "because realtime applications cannot 1314 * structures. This is needed "because realtime applications cannot
1295 * afford to lose notifications of asynchronous events, like timer 1315 * afford to lose notifications of asynchronous events, like timer
1296 * expirations or I/O completions". In the case of Posix Timers 1316 * expirations or I/O completions". In the case of Posix Timers
1297 * we allocate the sigqueue structure from the timer_create. If this 1317 * we allocate the sigqueue structure from the timer_create. If this
1298 * allocation fails we are able to report the failure to the application 1318 * allocation fails we are able to report the failure to the application
1299 * with an EAGAIN error. 1319 * with an EAGAIN error.
1300 */ 1320 */
1301
1302struct sigqueue *sigqueue_alloc(void) 1321struct sigqueue *sigqueue_alloc(void)
1303{ 1322{
1304 struct sigqueue *q; 1323 struct sigqueue *q = __sigqueue_alloc(-1, current, GFP_KERNEL, 0);
1305 1324
1306 if ((q = __sigqueue_alloc(current, GFP_KERNEL, 0))) 1325 if (q)
1307 q->flags |= SIGQUEUE_PREALLOC; 1326 q->flags |= SIGQUEUE_PREALLOC;
1308 return(q); 1327
1328 return q;
1309} 1329}
1310 1330
1311void sigqueue_free(struct sigqueue *q) 1331void sigqueue_free(struct sigqueue *q)