aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2009-06-22 08:14:16 -0400
committerPatrick McHardy <kaber@trash.net>2009-06-22 08:14:16 -0400
commit5c8ec910e789a92229978d8fd1fce7b62e8ac711 (patch)
treed24884793a0804bf2f96afac2248189b358b8ae2
parent8cc20198cfccd06cef705c14fd50bde603e2e306 (diff)
netfilter: nf_conntrack: fix confirmation race condition
New connection tracking entries are inserted into the hash before they are fully set up, namely the CONFIRMED bit is not set and the timer not started yet. This can theoretically lead to a race with timer, which would set the timeout value to a relative value, most likely already in the past. Perform hash insertion as the final step to fix this. Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r--net/netfilter/nf_conntrack_core.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 5276a2dd56fe..b0b06c7a9483 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -425,7 +425,6 @@ __nf_conntrack_confirm(struct sk_buff *skb)
425 /* Remove from unconfirmed list */ 425 /* Remove from unconfirmed list */
426 hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode); 426 hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode);
427 427
428 __nf_conntrack_hash_insert(ct, hash, repl_hash);
429 /* Timer relative to confirmation time, not original 428 /* Timer relative to confirmation time, not original
430 setting time, otherwise we'd get timer wrap in 429 setting time, otherwise we'd get timer wrap in
431 weird delay cases. */ 430 weird delay cases. */
@@ -433,8 +432,16 @@ __nf_conntrack_confirm(struct sk_buff *skb)
433 add_timer(&ct->timeout); 432 add_timer(&ct->timeout);
434 atomic_inc(&ct->ct_general.use); 433 atomic_inc(&ct->ct_general.use);
435 set_bit(IPS_CONFIRMED_BIT, &ct->status); 434 set_bit(IPS_CONFIRMED_BIT, &ct->status);
435
436 /* Since the lookup is lockless, hash insertion must be done after
437 * starting the timer and setting the CONFIRMED bit. The RCU barriers
438 * guarantee that no other CPU can find the conntrack before the above
439 * stores are visible.
440 */
441 __nf_conntrack_hash_insert(ct, hash, repl_hash);
436 NF_CT_STAT_INC(net, insert); 442 NF_CT_STAT_INC(net, insert);
437 spin_unlock_bh(&nf_conntrack_lock); 443 spin_unlock_bh(&nf_conntrack_lock);
444
438 help = nfct_help(ct); 445 help = nfct_help(ct);
439 if (help && help->helper) 446 if (help && help->helper)
440 nf_conntrack_event_cache(IPCT_HELPER, ct); 447 nf_conntrack_event_cache(IPCT_HELPER, ct);