inet: ping: avoid skb_clone() dance in ping_rcv()
authorEric Dumazet <edumazet@google.com>
Wed, 26 Feb 2025 18:34:37 +0000 (18:34 +0000)
committerJakub Kicinski <kuba@kernel.org>
Fri, 28 Feb 2025 22:41:33 +0000 (14:41 -0800)
ping_rcv() callers currently call skb_free() or consume_skb(),
forcing ping_rcv() to clone the skb.

After this patch ping_rcv() is now 'consuming' the original skb,
either moving to a socket receive queue, or dropping it.

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

index 058d4c1e300d0c0be7a04fd67e8e39924dfcd2cc..717cb7d3607a1c77a3f54b56d2bb98b1064dd878 100644 (file)
@@ -1274,9 +1274,10 @@ int icmp_rcv(struct sk_buff *skb)
                }
        }
 
-       if (icmph->type == ICMP_EXT_ECHOREPLY) {
+       if (icmph->type == ICMP_EXT_ECHOREPLY ||
+           icmph->type == ICMP_ECHOREPLY) {
                reason = ping_rcv(skb);
-               goto reason_check;
+               return reason ? NET_RX_DROP : NET_RX_SUCCESS;
        }
 
        /*
index 85d09f2ecadcb690f01985771afa37ce2cd0befc..c14baa6589c748026b49416688cbea399e6d461a 100644 (file)
@@ -966,10 +966,9 @@ EXPORT_SYMBOL_GPL(ping_queue_rcv_skb);
 
 enum skb_drop_reason ping_rcv(struct sk_buff *skb)
 {
-       enum skb_drop_reason reason = SKB_DROP_REASON_NO_SOCKET;
-       struct sock *sk;
        struct net *net = dev_net(skb->dev);
        struct icmphdr *icmph = icmp_hdr(skb);
+       struct sock *sk;
 
        /* We assume the packet has already been checked by icmp_rcv */
 
@@ -980,20 +979,11 @@ enum skb_drop_reason ping_rcv(struct sk_buff *skb)
        skb_push(skb, skb->data - (u8 *)icmph);
 
        sk = ping_lookup(net, skb, ntohs(icmph->un.echo.id));
-       if (sk) {
-               struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
-
-               pr_debug("rcv on socket %p\n", sk);
-               if (skb2)
-                       reason = __ping_queue_rcv_skb(sk, skb2);
-               else
-                       reason = SKB_DROP_REASON_NOMEM;
-       }
-
-       if (reason)
-               pr_debug("no socket, dropping\n");
+       if (sk)
+               return __ping_queue_rcv_skb(sk, skb);
 
-       return reason;
+       kfree_skb_reason(skb, SKB_DROP_REASON_NO_SOCKET);
+       return SKB_DROP_REASON_NO_SOCKET;
 }
 EXPORT_SYMBOL_GPL(ping_rcv);
 
index 4d14ab7f7e99f152cd5f5adaa023f0280957f275..3fd19a84b358d169bbdc351c43ede830c60afcf3 100644 (file)
@@ -957,12 +957,9 @@ static int icmpv6_rcv(struct sk_buff *skb)
                break;
 
        case ICMPV6_ECHO_REPLY:
-               reason = ping_rcv(skb);
-               break;
-
        case ICMPV6_EXT_ECHO_REPLY:
-               reason = ping_rcv(skb);
-               break;
+               ping_rcv(skb);
+               return 0;
 
        case ICMPV6_PKT_TOOBIG:
                /* BUGGG_FUTURE: if packet contains rthdr, we cannot update