[RAMEN9610-21992]icmp: randomize the global rate limiter
authorEric Dumazet <edumazet@google.com>
Thu, 15 Oct 2020 18:42:00 +0000 (11:42 -0700)
committerlingsen1 <lingsen1@lenovo.com>
Thu, 1 Apr 2021 13:30:04 +0000 (21:30 +0800)
[ Upstream commit b38e7819cae946e2edf869e604af1e65a5d241c5 ]

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: 4cdf507d5452 ("icmp: add a global rate limitation")
Change-Id: Ib1a0ee70e55123a17d88b79a83664a3b2ac70034
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: Keyu Man <kman001@ucr.edu>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Documentation/networking/ip-sysctl.txt
net/ipv4/icmp.c

index 6a98ad3b3586f8edef5b9ddd5ea8c920d1320b86..258d049b4ab2c26899f57a758278e9cdfb28a9ce 100644 (file)
@@ -906,12 +906,14 @@ icmp_ratelimit - INTEGER
 icmp_msgs_per_sec - INTEGER
        Limit maximal number of ICMP packets sent per second from this host.
        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
 
 icmp_msgs_burst - INTEGER
        icmp_msgs_per_sec controls number of ICMP packets sent per second,
        while icmp_msgs_burst controls the burst size of these packets.
+       For security reasons, the precise burst size is randomized.
        Default: 50
 
 icmp_ratemask - INTEGER
index f9d790b058d24f616646c1b0737a7f12973f62af..d4772218fe44b7e8002c271b2dd5aa53bfe9673d 100644 (file)
@@ -244,7 +244,7 @@ static struct {
 /**
  * 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.
  * Note: called with BH disabled
  */
@@ -271,7 +271,10 @@ bool icmp_global_allow(void)
        }
        credit = min_t(u32, icmp_global.credit + incr, sysctl_icmp_msgs_burst);
        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;
        }
        icmp_global.credit = credit;