1) net_ratelimit()用於保護內核網絡調試信息的打印, 當它返回(TRUE)時則可以打印調試信息,返回零則禁止信息打印. 它的特性為當"極快地"調用net_ratelimit()時,它最多只允許連續打印前10條信息, 後繼信息每隔5秒允許打印一次.這樣可防止攻擊者使內核不斷產生調試信息來使系統過載的拒絕服務攻擊.2) net_ratelimit()定義了一個時間計數器變量(toks), 它隨著系統時鐘計數線性增長,但不超時50秒時鐘計數(net_msg_burst). 當計時器的值大於或等於5秒時鐘計數(net_msg_cost)時,則允許打印信息. 每允許打印一條信息, 計時器就減去5秒計數, 當計時器的值小於5秒時, 就不允許打印信息了.; net/core/utils.c:
int net_msg_cost = 5*HZ; /*在擁塞時, 每條網絡消息記錄所間隔的時間*/
int net_msg_burst = 10*5*HZ; /*連續記錄網絡突發消息的間隔(最多連續記錄10條消息)*/
/*
* This enforces a rate limit: not more than one kernel message
* every 5secs to make a denial-of-service attack impossible.
*
* All warning printk()s should be guarded by this function.
*/
int net_ratelimit(void)
{
static spinlock_t ratelimit_lock = SPIN_LOCK_UNLOCKED;
static unsigned long toks = 10*5*HZ; /*50秒量程的計時器,每打印一條消息,計時器減5秒時間*/
static unsigned long last_msg; /*上一次調用net_ratelimit()的時戳*/
static int missed; /*兩次net_ratelimit()調用之間所丟棄的信息數量*/
unsigned long flags;
unsigned long now = jiffies; /*取當前時戳*/
spin_lock_irqsave(&ratelimit_lock, flags);
toks += now - last_msg;
/*計時器加上兩次net_ratelimit()調用的時間差,表現為計時時間的線性增長*/
last_msg = now;
if (toks > net_msg_burst) /*計時器累積時間超時50秒時*/
toks = net_msg_burst;/* 設置計時上限*/
if (toks >= net_msg_cost) { /*當計時大於或等於5秒時可以打印信息*/
int lost = missed;
missed = 0;
toks -= net_msg_cost; /*減去5秒時間*/
spin_unlock_irqrestore(&ratelimit_lock, flags);
if (lost)
printk(KERN_WARNING "NET: %d messages suppressed.\n", lost);
return 1;
}
missed++;
spin_unlock_irqrestore(&ratelimit_lock, flags);
return 0;
}
/*linux 2.6內核直接調用__printk_ratelimit()*/
int net_ratelimit(void)
{
return __printk_ratelimit(net_msg_cost, net_msg_burst);
}
kernel/printk.c
/*
* 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(int ratelimit_jiffies, int ratelimit_burst)
{
static DEFINE_SPINLOCK(ratelimit_lock);
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 > (ratelimit_burst * ratelimit_jiffies))
toks = ratelimit_burst * ratelimit_jiffies;
if (toks >= ratelimit_jiffies) {
int lost = mis12下一頁