[NETFILTER]: Keep conntrack reference until IPsec policy checks are done
authorPatrick McHardy <kaber@trash.net>
Sat, 7 Jan 2006 07:06:10 +0000 (23:06 -0800)
committerDavid S. Miller <davem@sunset.davemloft.net>
Sat, 7 Jan 2006 20:57:36 +0000 (12:57 -0800)
Keep the conntrack reference until policy checks have been performed for
IPsec NAT support. The reference needs to be dropped before a packet is
queued to avoid having the conntrack module unloadable.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/dccp/ipv4.c
net/ipv4/ip_input.c
net/ipv4/raw.c
net/ipv4/tcp_ipv4.c
net/ipv4/udp.c
net/sctp/input.c

index 3f244670764ae94fad1826439a748f860d1b808c..23ba177c11506a83b46fffde00f2d4bb84882971 100644 (file)
@@ -1099,6 +1099,7 @@ int dccp_v4_destroy_sock(struct sock *sk)
                kfree_skb(sk->sk_send_head);
                sk->sk_send_head = NULL;
        }
+       nf_reset(skb);
 
        /* Clean up a referenced DCCP bind bucket. */
        if (inet_csk(sk)->icsk_bind_hash != NULL)
index e45846ae570bba9c3b3da568e5e8b7e46598e7f3..18d7fad474d72510e18177837912e5ff26ea4acb 100644 (file)
@@ -185,7 +185,6 @@ int ip_call_ra_chain(struct sk_buff *skb)
                                        raw_rcv(last, skb2);
                        }
                        last = sk;
-                       nf_reset(skb);
                }
        }
 
@@ -204,10 +203,6 @@ static inline int ip_local_deliver_finish(struct sk_buff *skb)
 
        __skb_pull(skb, ihl);
 
-       /* Free reference early: we don't need it any more, and it may
-           hold ip_conntrack module loaded indefinitely. */
-       nf_reset(skb);
-
         /* Point into the IP datagram, just past the header. */
         skb->h.raw = skb->data;
 
@@ -232,10 +227,12 @@ static inline int ip_local_deliver_finish(struct sk_buff *skb)
                if ((ipprot = rcu_dereference(inet_protos[hash])) != NULL) {
                        int ret;
 
-                       if (!ipprot->no_policy &&
-                           !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
-                               kfree_skb(skb);
-                               goto out;
+                       if (!ipprot->no_policy) {
+                               if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
+                                       kfree_skb(skb);
+                                       goto out;
+                               }
+                               nf_reset(skb);
                        }
                        ret = ipprot->handler(skb);
                        if (ret < 0) {
index 4b0d7e4d62698a44acd992fd3e2a01e14b3037f0..165a4d81efa4a75663e72e12d3cfa12eddb9f969 100644 (file)
@@ -255,6 +255,7 @@ int raw_rcv(struct sock *sk, struct sk_buff *skb)
                kfree_skb(skb);
                return NET_RX_DROP;
        }
+       nf_reset(skb);
 
        skb_push(skb, skb->data - skb->nh.raw);
 
index e9f83e5b28ce93a7e2a3e76a878526ec227ad497..6ea353907af5757de1abc84e6b87274afa4d26fe 100644 (file)
@@ -1080,6 +1080,7 @@ process:
 
        if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
                goto discard_and_relse;
+       nf_reset(skb);
 
        if (sk_filter(sk, skb, 0))
                goto discard_and_relse;
index 223abaa72bc53b24b0e39356582cacf86c18e988..00840474a44947eaaf8ce917bee7d22ccc4a4a63 100644 (file)
@@ -989,6 +989,7 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
                kfree_skb(skb);
                return -1;
        }
+       nf_reset(skb);
 
        if (up->encap_type) {
                /*
@@ -1149,6 +1150,7 @@ int udp_rcv(struct sk_buff *skb)
 
        if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
                goto drop;
+       nf_reset(skb);
 
        /* No socket. Drop packet silently, if checksum is wrong */
        if (udp_checksum_complete(skb))
index 238f1bffa6845e94b3e0bec1f6d5ad0da4c0e695..4aa6fc60357ca10f76bf3c918a76d88fe1ba2b00 100644 (file)
@@ -225,6 +225,7 @@ int sctp_rcv(struct sk_buff *skb)
 
        if (!xfrm_policy_check(sk, XFRM_POLICY_IN, skb, family))
                goto discard_release;
+       nf_reset(skb);
 
        ret = sk_filter(sk, skb, 1);
        if (ret)