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 b9d7c3d..c0fd8f5 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 e1ebf5e..d94041b 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 4fc511b..f44b99f 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 81afb40..c563a84 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 0b81279..c029222 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;