netfilter: keep conntrack reference until IPsecv6 policy checks are done
authorMadhu Koriginja <madhu.koriginja@nxp.com>
Tue, 21 Mar 2023 15:58:44 +0000 (21:28 +0530)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 11 May 2023 14:03:18 +0000 (23:03 +0900)
[ Upstream commit b0e214d212030fe497d4d150bb3474e50ad5d093 ]

Keep the conntrack reference until policy checks have been performed for
IPsec V6 NAT support, just like ipv4.

The reference needs to be dropped before a packet is
queued to avoid having the conntrack module unloadable.

Fixes: 58a317f1061c ("netfilter: ipv6: add IPv6 NAT support")
Signed-off-by: Madhu Koriginja <madhu.koriginja@nxp.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/dccp/ipv6.c
net/ipv6/ip6_input.c
net/ipv6/raw.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c

index b9d7c3dd1cb39852be3a03556e976c09757d391d..c0fd8f5f3b94e90b15bc8f90dfcfd2f7e47f57fd 100644 (file)
@@ -783,6 +783,7 @@ lookup:
 
        if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
                goto discard_and_relse;
+       nf_reset_ct(skb);
 
        return __sk_receive_skb(sk, skb, 1, dh->dccph_doff * 4,
                                refcounted) ? -1 : 0;
index e1ebf5e42ebe9ac39c13f109b03853c557ff2718..d94041bb42872f02eaaa5bd2f64ae2301a8a48a4 100644 (file)
@@ -404,10 +404,6 @@ resubmit_final:
                        /* Only do this once for first final protocol */
                        have_final = true;
 
-                       /* Free reference early: we don't need it any more,
-                          and it may hold ip_conntrack module loaded
-                          indefinitely. */
-                       nf_reset_ct(skb);
 
                        skb_postpull_rcsum(skb, skb_network_header(skb),
                                           skb_network_header_len(skb));
@@ -430,10 +426,12 @@ resubmit_final:
                                goto discard;
                        }
                }
-               if (!(ipprot->flags & INET6_PROTO_NOPOLICY) &&
-                   !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
-                       SKB_DR_SET(reason, XFRM_POLICY);
-                       goto discard;
+               if (!(ipprot->flags & INET6_PROTO_NOPOLICY)) {
+                       if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
+                               SKB_DR_SET(reason, XFRM_POLICY);
+                               goto discard;
+                       }
+                       nf_reset_ct(skb);
                }
 
                ret = INDIRECT_CALL_2(ipprot->handler, tcp_v6_rcv, udpv6_rcv,
index 4fc511bdf176c1d0c8d43287cb4b3e350b77c021..f44b99f7ecdcc04c3b687ba040ff3855c3013cf1 100644 (file)
@@ -193,10 +193,8 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
                        struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC);
 
                        /* Not releasing hash table! */
-                       if (clone) {
-                               nf_reset_ct(clone);
+                       if (clone)
                                rawv6_rcv(sk, clone);
-                       }
                }
        }
        rcu_read_unlock();
@@ -387,6 +385,7 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb)
                kfree_skb(skb);
                return NET_RX_DROP;
        }
+       nf_reset_ct(skb);
 
        if (!rp->checksum)
                skb->ip_summed = CHECKSUM_UNNECESSARY;
index 81afb40bfc0bbef069393ac8aac41bf4f83bbe56..c563a84d67b4614bb30b49183783b4ee20f622ee 100644 (file)
@@ -1722,6 +1722,8 @@ process:
        if (drop_reason)
                goto discard_and_relse;
 
+       nf_reset_ct(skb);
+
        if (tcp_filter(sk, skb)) {
                drop_reason = SKB_DROP_REASON_SOCKET_FILTER;
                goto discard_and_relse;
index 0b8127988adb78c2510cebae529a184a6b3e89be..c029222ce46b0589e00a4ac355cea50df8439f3b 100644 (file)
@@ -701,6 +701,7 @@ static int udpv6_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
                drop_reason = SKB_DROP_REASON_XFRM_POLICY;
                goto drop;
        }
+       nf_reset_ct(skb);
 
        if (static_branch_unlikely(&udpv6_encap_needed_key) && up->encap_type) {
                int (*encap_rcv)(struct sock *sk, struct sk_buff *skb);
@@ -1024,6 +1025,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
 
        if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
                goto discard;
+       nf_reset_ct(skb);
 
        if (udp_lib_checksum_complete(skb))
                goto csum_error;