Commit b54ad409 authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller

netfilter: ctnetlink: fix conntrack creation race

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: default avatarZoltan Borbely <bozo@andrews.hu>
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5147d14e
...@@ -305,9 +305,7 @@ void nf_conntrack_hash_insert(struct nf_conn *ct) ...@@ -305,9 +305,7 @@ void nf_conntrack_hash_insert(struct nf_conn *ct)
hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].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); __nf_conntrack_hash_insert(ct, hash, repl_hash);
spin_unlock_bh(&nf_conntrack_lock);
} }
EXPORT_SYMBOL_GPL(nf_conntrack_hash_insert); EXPORT_SYMBOL_GPL(nf_conntrack_hash_insert);
......
...@@ -1090,7 +1090,7 @@ ctnetlink_create_conntrack(struct nlattr *cda[], ...@@ -1090,7 +1090,7 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
struct nf_conn_help *help; struct nf_conn_help *help;
struct nf_conntrack_helper *helper; 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)) if (ct == NULL || IS_ERR(ct))
return -ENOMEM; return -ENOMEM;
...@@ -1212,13 +1212,14 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, ...@@ -1212,13 +1212,14 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
atomic_inc(&master_ct->ct_general.use); atomic_inc(&master_ct->ct_general.use);
} }
spin_unlock_bh(&nf_conntrack_lock);
err = -ENOENT; err = -ENOENT;
if (nlh->nlmsg_flags & NLM_F_CREATE) if (nlh->nlmsg_flags & NLM_F_CREATE)
err = ctnetlink_create_conntrack(cda, err = ctnetlink_create_conntrack(cda,
&otuple, &otuple,
&rtuple, &rtuple,
master_ct); master_ct);
spin_unlock_bh(&nf_conntrack_lock);
if (err < 0 && master_ct) if (err < 0 && master_ct)
nf_ct_put(master_ct); nf_ct_put(master_ct);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment