Skip to content

Commit 849a44d

Browse files
netoptimizerdavem330
authored andcommitted
net: don't global ICMP rate limit packets originating from loopback
Florian Weimer seems to have a glibc test-case which requires that loopback interfaces does not get ICMP ratelimited. This was broken by commit c0303ef ("net: reduce cycles spend on ICMP replies that gets rate limited"). An ICMP response will usually be routed back-out the same incoming interface. Thus, take advantage of this and skip global ICMP ratelimit when the incoming device is loopback. In the unlikely event that the outgoing it not loopback, due to strange routing policy rules, ICMP rate limiting still works via peer ratelimiting via icmpv4_xrlim_allow(). Thus, we should still comply with RFC1812 (section 4.3.2.8 "Rate Limiting"). This seems to fix the reproducer given by Florian. While still avoiding to perform expensive and unneeded outgoing route lookup for rate limited packets (in the non-loopback case). Fixes: c0303ef ("net: reduce cycles spend on ICMP replies that gets rate limited") Reported-by: Florian Weimer <fweimer@redhat.com> Reported-by: "H.J. Lu" <hjl.tools@gmail.com> Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent c4f65b0 commit 849a44d

File tree

2 files changed

+7
-3
lines changed

2 files changed

+7
-3
lines changed

net/ipv4/icmp.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -657,8 +657,12 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
657657
/* Needed by both icmp_global_allow and icmp_xmit_lock */
658658
local_bh_disable();
659659

660-
/* Check global sysctl_icmp_msgs_per_sec ratelimit */
661-
if (!icmpv4_global_allow(net, type, code))
660+
/* Check global sysctl_icmp_msgs_per_sec ratelimit, unless
661+
* incoming dev is loopback. If outgoing dev change to not be
662+
* loopback, then peer ratelimit still work (in icmpv4_xrlim_allow)
663+
*/
664+
if (!(skb_in->dev && (skb_in->dev->flags&IFF_LOOPBACK)) &&
665+
!icmpv4_global_allow(net, type, code))
662666
goto out_bh_enable;
663667

664668
sk = icmp_xmit_lock(net);

net/ipv6/icmp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
491491
local_bh_disable();
492492

493493
/* Check global sysctl_icmp_msgs_per_sec ratelimit */
494-
if (!icmpv6_global_allow(type))
494+
if (!(skb->dev->flags&IFF_LOOPBACK) && !icmpv6_global_allow(type))
495495
goto out_bh_enable;
496496

497497
mip6_addr_swap(skb);

0 commit comments

Comments
 (0)