# 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. # # : 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 + +/* minimum time in jiffies between messages */ +int printk_ratelimit_jiffies = 5*HZ; + +/* number of messages we send before ratelimiting */ +int 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 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 > (printk_ratelimit_burst * printk_ratelimit_jiffies)) + toks = printk_ratelimit_burst * printk_ratelimit_jiffies; + if (toks >= printk_ratelimit_jiffies) { + int lost = missed; + missed = 0; + toks -= 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 (!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 (!printk_ratelimit()) + return; +#endif if (function) flen = strlen(function); spin_lock(&err_buf_lock);