icmp: randomize the global rate limiter

Keyu Man reported that the ICMP rate limiter could be used
by attackers to get useful signal. Details will be provided
in an upcoming academic publication.

Our solution is to add some noise, so that the attackers
no longer can get help from the predictable token bucket limiter.

Fixes: 4cdf507d54 ("icmp: add a global rate limitation")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: Keyu Man <kman001@ucr.edu>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Eric Dumazet 2020-10-15 11:42:00 -07:00 committed by Jakub Kicinski
parent 137d23cea1
commit b38e7819ca
2 changed files with 8 additions and 3 deletions

View File

@ -1142,13 +1142,15 @@ icmp_ratelimit - INTEGER
icmp_msgs_per_sec - INTEGER icmp_msgs_per_sec - INTEGER
Limit maximal number of ICMP packets sent per second from this host. Limit maximal number of ICMP packets sent per second from this host.
Only messages whose type matches icmp_ratemask (see below) are Only messages whose type matches icmp_ratemask (see below) are
controlled by this limit. controlled by this limit. For security reasons, the precise count
of messages per second is randomized.
Default: 1000 Default: 1000
icmp_msgs_burst - INTEGER icmp_msgs_burst - INTEGER
icmp_msgs_per_sec controls number of ICMP packets sent per second, icmp_msgs_per_sec controls number of ICMP packets sent per second,
while icmp_msgs_burst controls the burst size of these packets. while icmp_msgs_burst controls the burst size of these packets.
For security reasons, the precise burst size is randomized.
Default: 50 Default: 50

View File

@ -239,7 +239,7 @@ static struct {
/** /**
* icmp_global_allow - Are we allowed to send one more ICMP message ? * icmp_global_allow - Are we allowed to send one more ICMP message ?
* *
* Uses a token bucket to limit our ICMP messages to sysctl_icmp_msgs_per_sec. * Uses a token bucket to limit our ICMP messages to ~sysctl_icmp_msgs_per_sec.
* Returns false if we reached the limit and can not send another packet. * Returns false if we reached the limit and can not send another packet.
* Note: called with BH disabled * Note: called with BH disabled
*/ */
@ -267,7 +267,10 @@ bool icmp_global_allow(void)
} }
credit = min_t(u32, icmp_global.credit + incr, sysctl_icmp_msgs_burst); credit = min_t(u32, icmp_global.credit + incr, sysctl_icmp_msgs_burst);
if (credit) { if (credit) {
credit--; /* We want to use a credit of one in average, but need to randomize
* it for security reasons.
*/
credit = max_t(int, credit - prandom_u32_max(3), 0);
rc = true; rc = true;
} }
WRITE_ONCE(icmp_global.credit, credit); WRITE_ONCE(icmp_global.credit, credit);