aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2008-11-24 18:56:17 -0500
committerDavid S. Miller <davem@davemloft.net>2008-11-24 18:56:17 -0500
commitb54ad409fd09a395b839fb81f300880d76861c0e (patch)
tree580b23b89c04c85ad9795b37f81174e1bbb5311b
parent5147d14e995c097571d383fe1287fb33345a51ee (diff)
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: Zoltan Borbely <bozo@andrews.hu> Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/netfilter/nf_conntrack_core.c2
-rw-r--r--net/netfilter/nf_conntrack_netlink.c5
2 files changed, 3 insertions, 4 deletions
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 622d7c671cb7..233fdd2d7d21 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -305,9 +305,7 @@ void nf_conntrack_hash_insert(struct nf_conn *ct)
305 hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); 305 hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
306 repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); 306 repl_hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
307 307
308 spin_lock_bh(&nf_conntrack_lock);
309 __nf_conntrack_hash_insert(ct, hash, repl_hash); 308 __nf_conntrack_hash_insert(ct, hash, repl_hash);
310 spin_unlock_bh(&nf_conntrack_lock);
311} 309}
312EXPORT_SYMBOL_GPL(nf_conntrack_hash_insert); 310EXPORT_SYMBOL_GPL(nf_conntrack_hash_insert);
313 311
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index a040d46f85d6..3b009a3e8549 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1090,7 +1090,7 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
1090 struct nf_conn_help *help; 1090 struct nf_conn_help *help;
1091 struct nf_conntrack_helper *helper; 1091 struct nf_conntrack_helper *helper;
1092 1092
1093 ct = nf_conntrack_alloc(&init_net, otuple, rtuple, GFP_KERNEL); 1093 ct = nf_conntrack_alloc(&init_net, otuple, rtuple, GFP_ATOMIC);
1094 if (ct == NULL || IS_ERR(ct)) 1094 if (ct == NULL || IS_ERR(ct))
1095 return -ENOMEM; 1095 return -ENOMEM;
1096 1096
@@ -1212,13 +1212,14 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
1212 atomic_inc(&master_ct->ct_general.use); 1212 atomic_inc(&master_ct->ct_general.use);
1213 } 1213 }
1214 1214
1215 spin_unlock_bh(&nf_conntrack_lock);
1216 err = -ENOENT; 1215 err = -ENOENT;
1217 if (nlh->nlmsg_flags & NLM_F_CREATE) 1216 if (nlh->nlmsg_flags & NLM_F_CREATE)
1218 err = ctnetlink_create_conntrack(cda, 1217 err = ctnetlink_create_conntrack(cda,
1219 &otuple, 1218 &otuple,
1220 &rtuple, 1219 &rtuple,
1221 master_ct); 1220 master_ct);
1221 spin_unlock_bh(&nf_conntrack_lock);
1222
1222 if (err < 0 && master_ct) 1223 if (err < 0 && master_ct)
1223 nf_ct_put(master_ct); 1224 nf_ct_put(master_ct);
1224 1225