__ip6_tnl_rcv() mirrors its IPv4 counterpart: five distinct failures
share a single plain kfree_skb().  Reuse the drop reasons introduced
for ip_tunnel_rcv() and the ones the length helpers already return.

Note that skb_vlan_inet_prepare() returns an enum skb_drop_reason that
was simply discarded, and that pskb_may_pull_reason() has been
available all along.

__ip6_tnl_rcv() is reached through ip6_tnl_rcv() from both ip6_tunnel
(ip4ip6, ip6ip6) and ip6_gre (ip6gre, ip6gretap, erspan).  As on the
IPv4 side, only ip6_gre sets the checksum and sequence number bits, so
the option mismatch and the old sequence reasons are reachable through
it alone.

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

diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index d5ff50a2ac01..85578fa125bc 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -814,21 +814,29 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct 
sk_buff *skb,
                         bool log_ecn_err)
 {
        const struct ipv6hdr *ipv6h;
+       enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
        int nh, err;
 
        if (test_bit(IP_TUNNEL_CSUM_BIT, tunnel->parms.i_flags) !=
            test_bit(IP_TUNNEL_CSUM_BIT, tpi->flags)) {
                DEV_STATS_INC(tunnel->dev, rx_crc_errors);
                DEV_STATS_INC(tunnel->dev, rx_errors);
+               reason = SKB_DROP_REASON_IP_TUNNEL_CFG_OPTS_MISMATCH;
                goto drop;
        }
 
        if (test_bit(IP_TUNNEL_SEQ_BIT, tunnel->parms.i_flags)) {
-               if (!test_bit(IP_TUNNEL_SEQ_BIT, tpi->flags) ||
-                   (tunnel->i_seqno &&
-                    (s32)(ntohl(tpi->seq) - tunnel->i_seqno) < 0)) {
+               if (!test_bit(IP_TUNNEL_SEQ_BIT, tpi->flags)) {
                        DEV_STATS_INC(tunnel->dev, rx_fifo_errors);
                        DEV_STATS_INC(tunnel->dev, rx_errors);
+                       reason = SKB_DROP_REASON_IP_TUNNEL_CFG_OPTS_MISMATCH;
+                       goto drop;
+               }
+               if (tunnel->i_seqno &&
+                   (s32)(ntohl(tpi->seq) - tunnel->i_seqno) < 0) {
+                       DEV_STATS_INC(tunnel->dev, rx_fifo_errors);
+                       DEV_STATS_INC(tunnel->dev, rx_errors);
+                       reason = SKB_DROP_REASON_IP_TUNNEL_OLD_SEQ;
                        goto drop;
                }
                tunnel->i_seqno = ntohl(tpi->seq) + 1;
@@ -838,7 +846,8 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct 
sk_buff *skb,
 
        /* Warning: All skb pointers will be invalidated! */
        if (tunnel->dev->type == ARPHRD_ETHER) {
-               if (!pskb_may_pull(skb, ETH_HLEN)) {
+               reason = pskb_may_pull_reason(skb, ETH_HLEN);
+               if (reason) {
                        DEV_STATS_INC(tunnel->dev, rx_length_errors);
                        DEV_STATS_INC(tunnel->dev, rx_errors);
                        goto drop;
@@ -859,7 +868,8 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct 
sk_buff *skb,
 
        skb_reset_network_header(skb);
 
-       if (skb_vlan_inet_prepare(skb, true)) {
+       reason = skb_vlan_inet_prepare(skb, true);
+       if (reason) {
                DEV_STATS_INC(tunnel->dev, rx_length_errors);
                DEV_STATS_INC(tunnel->dev, rx_errors);
                goto drop;
@@ -881,6 +891,7 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct 
sk_buff *skb,
                if (err > 1) {
                        DEV_STATS_INC(tunnel->dev, rx_frame_errors);
                        DEV_STATS_INC(tunnel->dev, rx_errors);
+                       reason = SKB_DROP_REASON_IP_TUNNEL_ECN;
                        goto drop;
                }
        }
@@ -898,7 +909,7 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct 
sk_buff *skb,
 drop:
        if (tun_dst)
                dst_release((struct dst_entry *)tun_dst);
-       kfree_skb(skb);
+       kfree_skb_reason(skb, reason);
        return 0;
 }
 
-- 
2.47.3


Reply via email to