Mirror the previous patch on the IPv6 side: report
SKB_DROP_REASON_GRE_TUNNEL_NOT_FOUND when no tunnel matches the packet,
and tell that apart from a header that cannot be pulled
(SKB_DROP_REASON_HDR_TRUNC) or a metadata allocation failure
(SKB_DROP_REASON_NOMEM), which so far all ended up in the same plain
kfree_skb() in gre_rcv().

ip6gre_rcv() and ip6erspan_rcv() get the same output parameter as their
IPv4 counterparts.

Assisted-by: Claude-Code:claude-opus-5
Signed-off-by: Anton Danilov <[email protected]>
---
 net/ipv6/ip6_gre.c | 36 ++++++++++++++++++++++++++----------
 1 file changed, 26 insertions(+), 10 deletions(-)

diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 736eefdb528f..27fbe175beec 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -454,7 +454,8 @@ static int ip6gre_err(struct sk_buff *skb, struct 
inet6_skb_parm *opt,
        return 0;
 }
 
-static int ip6gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)
+static int ip6gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
+                     enum skb_drop_reason *reason)
 {
        const struct ipv6hdr *ipv6h;
        struct ip6_tnl *tunnel;
@@ -473,8 +474,10 @@ static int ip6gre_rcv(struct sk_buff *skb, const struct 
tnl_ptk_info *tpi)
                        tun_id = key32_to_tunnel_id(tpi->key);
 
                        tun_dst = ipv6_tun_rx_dst(skb, flags, tun_id, 0);
-                       if (!tun_dst)
+                       if (!tun_dst) {
+                               *reason = SKB_DROP_REASON_NOMEM;
                                return PACKET_REJECT;
+                       }
 
                        ip6_tnl_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
                } else {
@@ -484,12 +487,14 @@ static int ip6gre_rcv(struct sk_buff *skb, const struct 
tnl_ptk_info *tpi)
                return PACKET_RCVD;
        }
 
+       *reason = SKB_DROP_REASON_GRE_TUNNEL_NOT_FOUND;
        return PACKET_REJECT;
 }
 
 static int ip6erspan_rcv(struct sk_buff *skb,
                         struct tnl_ptk_info *tpi,
-                        int gre_hdr_len)
+                        int gre_hdr_len,
+                        enum skb_drop_reason *reason)
 {
        struct erspan_base_hdr *ershdr;
        const struct ipv6hdr *ipv6h;
@@ -497,8 +502,10 @@ static int ip6erspan_rcv(struct sk_buff *skb,
        struct ip6_tnl *tunnel;
        u8 ver;
 
-       if (unlikely(!pskb_may_pull(skb, sizeof(*ershdr))))
+       if (unlikely(!pskb_may_pull(skb, sizeof(*ershdr)))) {
+               *reason = SKB_DROP_REASON_HDR_TRUNC;
                return PACKET_REJECT;
+       }
 
        ipv6h = ipv6_hdr(skb);
        ershdr = (struct erspan_base_hdr *)skb->data;
@@ -510,13 +517,17 @@ static int ip6erspan_rcv(struct sk_buff *skb,
        if (tunnel) {
                int len = erspan_hdr_len(ver);
 
-               if (unlikely(!pskb_may_pull(skb, len)))
+               if (unlikely(!pskb_may_pull(skb, len))) {
+                       *reason = SKB_DROP_REASON_HDR_TRUNC;
                        return PACKET_REJECT;
+               }
 
                if (__iptunnel_pull_header(skb, len,
                                           htons(ETH_P_TEB),
-                                          false, false) < 0)
+                                          false, false) < 0) {
+                       *reason = SKB_DROP_REASON_HDR_TRUNC;
                        return PACKET_REJECT;
+               }
 
                if (tunnel->parms.collect_md) {
                        struct erspan_metadata *pkt_md, *md;
@@ -532,8 +543,10 @@ static int ip6erspan_rcv(struct sk_buff *skb,
 
                        tun_dst = ipv6_tun_rx_dst(skb, flags, tun_id,
                                                  sizeof(*md));
-                       if (!tun_dst)
+                       if (!tun_dst) {
+                               *reason = SKB_DROP_REASON_NOMEM;
                                return PACKET_REJECT;
+                       }
 
                        /* MUST set options_len before referencing options */
                        info = &tun_dst->u.tun_info;
@@ -564,6 +577,7 @@ static int ip6erspan_rcv(struct sk_buff *skb,
                return PACKET_RCVD;
        }
 
+       *reason = SKB_DROP_REASON_GRE_TUNNEL_NOT_FOUND;
        return PACKET_REJECT;
 }
 
@@ -577,17 +591,19 @@ static int gre_rcv(struct sk_buff *skb)
        if (hdr_len < 0)
                goto drop;
 
-       if (iptunnel_pull_header(skb, hdr_len, tpi.proto, false))
+       if (iptunnel_pull_header(skb, hdr_len, tpi.proto, false)) {
+               reason = SKB_DROP_REASON_HDR_TRUNC;
                goto drop;
+       }
 
        if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) ||
                     tpi.proto == htons(ETH_P_ERSPAN2))) {
-               if (ip6erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
+               if (ip6erspan_rcv(skb, &tpi, hdr_len, &reason) == PACKET_RCVD)
                        return 0;
                goto out;
        }
 
-       if (ip6gre_rcv(skb, &tpi) == PACKET_RCVD)
+       if (ip6gre_rcv(skb, &tpi, &reason) == PACKET_RCVD)
                return 0;
 
 out:
-- 
2.47.3


Reply via email to