aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorChangli Gao <xiaosuo@gmail.com>2010-09-16 13:55:03 -0400
committerPatrick McHardy <kaber@trash.net>2010-09-16 13:55:03 -0400
commitb23909695c33f53df5f1d16696b1aa5b874c1904 (patch)
tree94293e4d5c9a71751dacf5b2a34735428010ff2e /net/netfilter
parented0b6d7581b54455062f09ccac123814e70cd02f (diff)
netfilter: nf_conntrack: fix the hash random initializing race
nf_conntrack_alloc() isn't called with nf_conntrack_lock locked, so hash random initializing code maybe executed more than once on different CPUs. Signed-off-by: Changli Gao <xiaosuo@gmail.com> Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/nf_conntrack_core.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index df3eedb142f..4c0ad9b4dba 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -65,8 +65,7 @@ EXPORT_SYMBOL_GPL(nf_conntrack_max);
65DEFINE_PER_CPU(struct nf_conn, nf_conntrack_untracked); 65DEFINE_PER_CPU(struct nf_conn, nf_conntrack_untracked);
66EXPORT_PER_CPU_SYMBOL(nf_conntrack_untracked); 66EXPORT_PER_CPU_SYMBOL(nf_conntrack_untracked);
67 67
68static int nf_conntrack_hash_rnd_initted; 68static unsigned int nf_conntrack_hash_rnd __read_mostly;
69static unsigned int nf_conntrack_hash_rnd;
70 69
71static u_int32_t __hash_conntrack(const struct nf_conntrack_tuple *tuple, 70static u_int32_t __hash_conntrack(const struct nf_conntrack_tuple *tuple,
72 u16 zone, unsigned int size, unsigned int rnd) 71 u16 zone, unsigned int size, unsigned int rnd)
@@ -574,10 +573,18 @@ struct nf_conn *nf_conntrack_alloc(struct net *net, u16 zone,
574{ 573{
575 struct nf_conn *ct; 574 struct nf_conn *ct;
576 575
577 if (unlikely(!nf_conntrack_hash_rnd_initted)) { 576 if (unlikely(!nf_conntrack_hash_rnd)) {
578 get_random_bytes(&nf_conntrack_hash_rnd, 577 unsigned int rand;
579 sizeof(nf_conntrack_hash_rnd)); 578
580 nf_conntrack_hash_rnd_initted = 1; 579 /*
580 * Why not initialize nf_conntrack_rnd in a "init()" function ?
581 * Because there isn't enough entropy when system initializing,
582 * and we initialize it as late as possible.
583 */
584 do {
585 get_random_bytes(&rand, sizeof(rand));
586 } while (!rand);
587 cmpxchg(&nf_conntrack_hash_rnd, 0, rand);
581 } 588 }
582 589
583 /* We don't want any race condition at early drop stage */ 590 /* We don't want any race condition at early drop stage */