netfilter: nf_conntrack: fix ct refcount leak in l4proto->error()
authorPablo Neira Ayuso <pablo@netfilter.org>
Thu, 2 Jun 2011 13:08:45 +0000 (15:08 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Sun, 5 Jun 2011 23:37:02 +0000 (01:37 +0200)
This patch fixes a refcount leak of ct objects that may occur if
l4proto->error() assigns one conntrack object to one skbuff. In
that case, we have to skip further processing in nf_conntrack_in().

With this patch, we can also fix wrong return values (-NF_ACCEPT)
for special cases in ICMP[v6] that should not bump the invalid/error
statistic counters.

Reported-by: Zoltan Menyhart <Zoltan.Menyhart@bull.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/ipv4/netfilter/nf_conntrack_proto_icmp.c
net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
net/netfilter/nf_conntrack_core.c

index 7404bde959943d4fbbcee7901f3006bb4a971574..ab5b27a2916f70b79430f1a90ac7d7af6cceaebe 100644 (file)
@@ -160,7 +160,7 @@ icmp_error_message(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
        /* Update skb to refer to this connection */
        skb->nfct = &nf_ct_tuplehash_to_ctrack(h)->ct_general;
        skb->nfctinfo = *ctinfo;
-       return -NF_ACCEPT;
+       return NF_ACCEPT;
 }
 
 /* Small and modified version of icmp_rcv */
index 1df3c8b6bf4723668e6b8c43666b3e31f4583fd8..7c05e7eacbc6561744566168c4ff3c3f64fc828d 100644 (file)
@@ -177,7 +177,7 @@ icmpv6_error_message(struct net *net, struct nf_conn *tmpl,
        /* Update skb to refer to this connection */
        skb->nfct = &nf_ct_tuplehash_to_ctrack(h)->ct_general;
        skb->nfctinfo = *ctinfo;
-       return -NF_ACCEPT;
+       return NF_ACCEPT;
 }
 
 static int
index 0bd5689294034ca9d9d78341a26d50768fd457b8..f7af8b866017040600fb842d9441ff4fa9912fc7 100644 (file)
@@ -922,6 +922,9 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
                        ret = -ret;
                        goto out;
                }
+               /* ICMP[v6] protocol trackers may assign one conntrack. */
+               if (skb->nfct)
+                       goto out;
        }
 
        ct = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum,