]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
icmp: move icmp_global.credit and icmp_global.stamp to per netns storage
authorEric Dumazet <edumazet@google.com>
Thu, 29 Aug 2024 14:46:40 +0000 (14:46 +0000)
committerJakub Kicinski <kuba@kernel.org>
Fri, 30 Aug 2024 18:14:06 +0000 (11:14 -0700)
Host wide ICMP ratelimiter should be per netns, to provide better isolation.

Following patch in this series makes the sysctl per netns.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Link: https://patch.msgid.link/20240829144641.3880376-3-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/net/ip.h
include/net/netns/ipv4.h
net/ipv4/icmp.c
net/ipv6/icmp.c

index 82248813619e3f21e09d52976accbdc76c7668c2..d3bca4e83979f681c4931e9ff62db5941a059c11 100644 (file)
@@ -794,8 +794,8 @@ static inline void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb)
        ip_cmsg_recv_offset(msg, skb->sk, skb, 0, 0);
 }
 
-bool icmp_global_allow(void);
-void icmp_global_consume(void);
+bool icmp_global_allow(struct net *net);
+void icmp_global_consume(struct net *net);
 
 extern int sysctl_icmp_msgs_per_sec;
 extern int sysctl_icmp_msgs_burst;
index 5fcd61ada62289253844be9cbe25387dd92385a5..54fe7c079fffb285b7a8a069f3d57f9440a6655a 100644 (file)
@@ -122,7 +122,8 @@ struct netns_ipv4 {
        u8 sysctl_icmp_errors_use_inbound_ifaddr;
        int sysctl_icmp_ratelimit;
        int sysctl_icmp_ratemask;
-
+       atomic_t icmp_global_credit;
+       u32 icmp_global_stamp;
        u32 ip_rt_min_pmtu;
        int ip_rt_mtu_expires;
        int ip_rt_min_advmss;
index 0078e8fb2e86d0552ef85eb5bf5bef947b0f1c3d..2e1d81dbdbb6fe93ea53398bbe3b3627b35852b0 100644 (file)
@@ -223,19 +223,15 @@ static inline void icmp_xmit_unlock(struct sock *sk)
 int sysctl_icmp_msgs_per_sec __read_mostly = 1000;
 int sysctl_icmp_msgs_burst __read_mostly = 50;
 
-static struct {
-       atomic_t        credit;
-       u32             stamp;
-} icmp_global;
-
 /**
  * icmp_global_allow - Are we allowed to send one more ICMP message ?
+ * @net: network namespace
  *
  * 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.
  * Works in tandem with icmp_global_consume().
  */
-bool icmp_global_allow(void)
+bool icmp_global_allow(struct net *net)
 {
        u32 delta, now, oldstamp;
        int incr, new, old;
@@ -244,11 +240,11 @@ bool icmp_global_allow(void)
         * Then later icmp_global_consume() could consume more credits,
         * this is an acceptable race.
         */
-       if (atomic_read(&icmp_global.credit) > 0)
+       if (atomic_read(&net->ipv4.icmp_global_credit) > 0)
                return true;
 
        now = jiffies;
-       oldstamp = READ_ONCE(icmp_global.stamp);
+       oldstamp = READ_ONCE(net->ipv4.icmp_global_stamp);
        delta = min_t(u32, now - oldstamp, HZ);
        if (delta < HZ / 50)
                return false;
@@ -257,23 +253,23 @@ bool icmp_global_allow(void)
        if (!incr)
                return false;
 
-       if (cmpxchg(&icmp_global.stamp, oldstamp, now) == oldstamp) {
-               old = atomic_read(&icmp_global.credit);
+       if (cmpxchg(&net->ipv4.icmp_global_stamp, oldstamp, now) == oldstamp) {
+               old = atomic_read(&net->ipv4.icmp_global_credit);
                do {
                        new = min(old + incr, READ_ONCE(sysctl_icmp_msgs_burst));
-               } while (!atomic_try_cmpxchg(&icmp_global.credit, &old, new));
+               } while (!atomic_try_cmpxchg(&net->ipv4.icmp_global_credit, &old, new));
        }
        return true;
 }
 EXPORT_SYMBOL(icmp_global_allow);
 
-void icmp_global_consume(void)
+void icmp_global_consume(struct net *net)
 {
        int credits = get_random_u32_below(3);
 
        /* Note: this might make icmp_global.credit negative. */
        if (credits)
-               atomic_sub(credits, &icmp_global.credit);
+               atomic_sub(credits, &net->ipv4.icmp_global_credit);
 }
 EXPORT_SYMBOL(icmp_global_consume);
 
@@ -299,7 +295,7 @@ static bool icmpv4_global_allow(struct net *net, int type, int code,
        if (icmpv4_mask_allow(net, type, code))
                return true;
 
-       if (icmp_global_allow()) {
+       if (icmp_global_allow(net)) {
                *apply_ratelimit = true;
                return true;
        }
@@ -337,7 +333,7 @@ out:
        if (!rc)
                __ICMP_INC_STATS(net, ICMP_MIB_RATELIMITHOST);
        else
-               icmp_global_consume();
+               icmp_global_consume(net);
        return rc;
 }
 
index 46f70e4a835139ef7d8925c49440865355048193..071b0bc1179d81b18c340ce415cef21e02a30cd7 100644 (file)
@@ -181,7 +181,7 @@ static bool icmpv6_global_allow(struct net *net, int type,
        if (icmpv6_mask_allow(net, type))
                return true;
 
-       if (icmp_global_allow()) {
+       if (icmp_global_allow(net)) {
                *apply_ratelimit = true;
                return true;
        }
@@ -231,7 +231,7 @@ static bool icmpv6_xrlim_allow(struct sock *sk, u8 type,
                __ICMP6_INC_STATS(net, ip6_dst_idev(dst),
                                  ICMP6_MIB_RATELIMITHOST);
        else
-               icmp_global_consume();
+               icmp_global_consume(net);
        dst_release(dst);
        return res;
 }