]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
netfilter: ctnetlink: fix conntrack creation race
authorPatrick McHardy <kaber@trash.net>
Mon, 24 Nov 2008 23:56:17 +0000 (15:56 -0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 24 Nov 2008 23:56:17 +0000 (15:56 -0800)
Conntrack creation through ctnetlink has two races:

- the timer may expire and free the conntrack concurrently, causing an
  invalid memory access when attempting to put it in the hash tables

- an identical conntrack entry may be created in the packet processing
  path in the time between the lookup and hash insertion

Hold the conntrack lock between the lookup and insertion to avoid this.

Reported-by: Zoltan Borbely <bozo@andrews.hu>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_netlink.c

index 622d7c671cb78533082f9bf0b655a3bbffcd2f92..233fdd2d7d2186b03fd6bac169d4090dbab562a3 100644 (file)
@@ -305,9 +305,7 @@ void nf_conntrack_hash_insert(struct nf_conn *ct)
        hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
        repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
 
-       spin_lock_bh(&nf_conntrack_lock);
        __nf_conntrack_hash_insert(ct, hash, repl_hash);
-       spin_unlock_bh(&nf_conntrack_lock);
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_hash_insert);
 
index a040d46f85d6c8967f88af6c549f23206e6416c7..3b009a3e85496944ea2b1f70cad0fbb7729e525e 100644 (file)
@@ -1090,7 +1090,7 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
        struct nf_conn_help *help;
        struct nf_conntrack_helper *helper;
 
-       ct = nf_conntrack_alloc(&init_net, otuple, rtuple, GFP_KERNEL);
+       ct = nf_conntrack_alloc(&init_net, otuple, rtuple, GFP_ATOMIC);
        if (ct == NULL || IS_ERR(ct))
                return -ENOMEM;
 
@@ -1212,13 +1212,14 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
                        atomic_inc(&master_ct->ct_general.use);
                }
 
-               spin_unlock_bh(&nf_conntrack_lock);
                err = -ENOENT;
                if (nlh->nlmsg_flags & NLM_F_CREATE)
                        err = ctnetlink_create_conntrack(cda,
                                                         &otuple,
                                                         &rtuple,
                                                         master_ct);
+               spin_unlock_bh(&nf_conntrack_lock);
+
                if (err < 0 && master_ct)
                        nf_ct_put(master_ct);