]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/netfilter/nf_conntrack_core.c
[NETFILTER]: conntrack: fix race condition in early_drop
[linux-2.6-omap-h63xx.git] / net / netfilter / nf_conntrack_core.c
index 927137b8b3b5d520339743f9b197c5e310682d02..adeafa2cc339ea8773750d08f0250df7e64686be 100644 (file)
@@ -848,11 +848,15 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
                nf_conntrack_hash_rnd_initted = 1;
        }
 
+       /* We don't want any race condition at early drop stage */
+       atomic_inc(&nf_conntrack_count);
+
        if (nf_conntrack_max
-           && atomic_read(&nf_conntrack_count) >= nf_conntrack_max) {
+           && atomic_read(&nf_conntrack_count) > nf_conntrack_max) {
                unsigned int hash = hash_conntrack(orig);
                /* Try dropping from this hash chain. */
                if (!early_drop(&nf_conntrack_hash[hash])) {
+                       atomic_dec(&nf_conntrack_count);
                        if (net_ratelimit())
                                printk(KERN_WARNING
                                       "nf_conntrack: table full, dropping"
@@ -903,10 +907,12 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
        init_timer(&conntrack->timeout);
        conntrack->timeout.data = (unsigned long)conntrack;
        conntrack->timeout.function = death_by_timeout;
+       read_unlock_bh(&nf_ct_cache_lock);
 
-       atomic_inc(&nf_conntrack_count);
+       return conntrack;
 out:
        read_unlock_bh(&nf_ct_cache_lock);
+       atomic_dec(&nf_conntrack_count);
        return conntrack;
 }