summaryrefslogtreecommitdiff
blob: e58cc184ce4b8478488cbb62bd268704e9882712 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# ChangeSet
#   2005/01/25 10:10:51+00:00 aia21@cantab.net 
#   NTFS: Add printk rate limiting for ntfs_warning() and ntfs_error() when
#         compiled without debug.  This avoids a possible denial of service
#         attack.  Thanks to Carl-Daniel Hailfinger from SuSE for pointing this
#         out.
# 
# <plasmaroo>: printk_ratelimit() backported from 2.6.
#
diff -Nru a/fs/ntfs/debug.c b/fs/ntfs/debug.c
--- a/fs/ntfs/debug.c	2005-02-15 12:38:26 -08:00
+++ b/fs/ntfs/debug.c	2005-02-15 12:38:26 -08:00
@@ -25,6 +25,48 @@
 #endif
 
 #include "debug.h"
+#include <linux/sched.h>
+
+/* minimum time in jiffies between messages */
+int ntfs_debug_printk_ratelimit_jiffies = 5*HZ;
+
+/* number of messages we send before ratelimiting */
+int ntfs_debug_printk_ratelimit_burst = 10;
+
+/*
+ * printk rate limiting, lifted from the networking subsystem.
+ *
+ * This enforces a rate limit: not more than one kernel message
+ * every printk_ratelimit_jiffies to make a denial-of-service
+ * attack impossible.
+ */
+int ntfs_debug_printk_ratelimit(void)
+{
+	static spinlock_t ratelimit_lock = SPIN_LOCK_UNLOCKED;
+	static unsigned long toks = 10*5*HZ;
+	static unsigned long last_msg;
+	static int missed;
+	unsigned long flags;
+	unsigned long now = jiffies;
+
+	spin_lock_irqsave(&ratelimit_lock, flags);
+	toks += now - last_msg;
+	last_msg = now;
+	if (toks > (ntfs_debug_printk_ratelimit_burst * ntfs_debug_printk_ratelimit_jiffies))
+		toks = ntfs_debug_printk_ratelimit_burst * ntfs_debug_printk_ratelimit_jiffies;
+	if (toks >= ntfs_debug_printk_ratelimit_jiffies) {
+		int lost = missed;
+		missed = 0;
+		toks -= ntfs_debug_printk_ratelimit_jiffies;
+		spin_unlock_irqrestore(&ratelimit_lock, flags);
+		if (lost)
+			printk(KERN_WARNING "printk: %d messages suppressed.\n", lost);
+		return 1;
+	}
+	missed++;
+	spin_unlock_irqrestore(&ratelimit_lock, flags);
+	return 0;
+}
 
 /*
  * A static buffer to hold the error string being displayed and a spinlock
@@ -53,6 +53,10 @@
 	va_list args;
 	int flen = 0;
 
+#ifndef DEBUG
+	if (!ntfs_debug_printk_ratelimit())
+		return;
+#endif
 	if (function)
 		flen = strlen(function);
 	spin_lock(&err_buf_lock);
@@ -93,6 +97,10 @@
 	va_list args;
 	int flen = 0;
 
+#ifndef DEBUG
+	if (!ntfs_debug_printk_ratelimit())
+		return;
+#endif
 	if (function)
 		flen = strlen(function);
 	spin_lock(&err_buf_lock);