aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter/nf_conntrack_expect.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/netfilter/nf_conntrack_expect.c')
-rw-r--r--net/netfilter/nf_conntrack_expect.c34
1 files changed, 20 insertions, 14 deletions
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index a20fb0bd1ef..cd1e8e0970f 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -319,7 +319,8 @@ static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
319 const struct nf_conntrack_expect_policy *p; 319 const struct nf_conntrack_expect_policy *p;
320 unsigned int h = nf_ct_expect_dst_hash(&exp->tuple); 320 unsigned int h = nf_ct_expect_dst_hash(&exp->tuple);
321 321
322 atomic_inc(&exp->use); 322 /* two references : one for hash insert, one for the timer */
323 atomic_add(2, &exp->use);
323 324
324 if (master_help) { 325 if (master_help) {
325 hlist_add_head(&exp->lnode, &master_help->expectations); 326 hlist_add_head(&exp->lnode, &master_help->expectations);
@@ -333,12 +334,14 @@ static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
333 setup_timer(&exp->timeout, nf_ct_expectation_timed_out, 334 setup_timer(&exp->timeout, nf_ct_expectation_timed_out,
334 (unsigned long)exp); 335 (unsigned long)exp);
335 if (master_help) { 336 if (master_help) {
336 p = &master_help->helper->expect_policy[exp->class]; 337 p = &rcu_dereference_protected(
338 master_help->helper,
339 lockdep_is_held(&nf_conntrack_lock)
340 )->expect_policy[exp->class];
337 exp->timeout.expires = jiffies + p->timeout * HZ; 341 exp->timeout.expires = jiffies + p->timeout * HZ;
338 } 342 }
339 add_timer(&exp->timeout); 343 add_timer(&exp->timeout);
340 344
341 atomic_inc(&exp->use);
342 NF_CT_STAT_INC(net, expect_create); 345 NF_CT_STAT_INC(net, expect_create);
343} 346}
344 347
@@ -369,7 +372,10 @@ static inline int refresh_timer(struct nf_conntrack_expect *i)
369 if (!del_timer(&i->timeout)) 372 if (!del_timer(&i->timeout))
370 return 0; 373 return 0;
371 374
372 p = &master_help->helper->expect_policy[i->class]; 375 p = &rcu_dereference_protected(
376 master_help->helper,
377 lockdep_is_held(&nf_conntrack_lock)
378 )->expect_policy[i->class];
373 i->timeout.expires = jiffies + p->timeout * HZ; 379 i->timeout.expires = jiffies + p->timeout * HZ;
374 add_timer(&i->timeout); 380 add_timer(&i->timeout);
375 return 1; 381 return 1;
@@ -407,7 +413,10 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect)
407 } 413 }
408 /* Will be over limit? */ 414 /* Will be over limit? */
409 if (master_help) { 415 if (master_help) {
410 p = &master_help->helper->expect_policy[expect->class]; 416 p = &rcu_dereference_protected(
417 master_help->helper,
418 lockdep_is_held(&nf_conntrack_lock)
419 )->expect_policy[expect->class];
411 if (p->max_expected && 420 if (p->max_expected &&
412 master_help->expecting[expect->class] >= p->max_expected) { 421 master_help->expecting[expect->class] >= p->max_expected) {
413 evict_oldest_expect(master, expect); 422 evict_oldest_expect(master, expect);
@@ -478,7 +487,7 @@ static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
478 struct hlist_node *n; 487 struct hlist_node *n;
479 488
480 for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) { 489 for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) {
481 n = rcu_dereference(net->ct.expect_hash[st->bucket].first); 490 n = rcu_dereference(hlist_first_rcu(&net->ct.expect_hash[st->bucket]));
482 if (n) 491 if (n)
483 return n; 492 return n;
484 } 493 }
@@ -491,11 +500,11 @@ static struct hlist_node *ct_expect_get_next(struct seq_file *seq,
491 struct net *net = seq_file_net(seq); 500 struct net *net = seq_file_net(seq);
492 struct ct_expect_iter_state *st = seq->private; 501 struct ct_expect_iter_state *st = seq->private;
493 502
494 head = rcu_dereference(head->next); 503 head = rcu_dereference(hlist_next_rcu(head));
495 while (head == NULL) { 504 while (head == NULL) {
496 if (++st->bucket >= nf_ct_expect_hsize) 505 if (++st->bucket >= nf_ct_expect_hsize)
497 return NULL; 506 return NULL;
498 head = rcu_dereference(net->ct.expect_hash[st->bucket].first); 507 head = rcu_dereference(hlist_first_rcu(&net->ct.expect_hash[st->bucket]));
499 } 508 }
500 return head; 509 return head;
501} 510}
@@ -630,8 +639,7 @@ int nf_conntrack_expect_init(struct net *net)
630 } 639 }
631 640
632 net->ct.expect_count = 0; 641 net->ct.expect_count = 0;
633 net->ct.expect_hash = nf_ct_alloc_hashtable(&nf_ct_expect_hsize, 642 net->ct.expect_hash = nf_ct_alloc_hashtable(&nf_ct_expect_hsize, 0);
634 &net->ct.expect_vmalloc, 0);
635 if (net->ct.expect_hash == NULL) 643 if (net->ct.expect_hash == NULL)
636 goto err1; 644 goto err1;
637 645
@@ -653,8 +661,7 @@ err3:
653 if (net_eq(net, &init_net)) 661 if (net_eq(net, &init_net))
654 kmem_cache_destroy(nf_ct_expect_cachep); 662 kmem_cache_destroy(nf_ct_expect_cachep);
655err2: 663err2:
656 nf_ct_free_hashtable(net->ct.expect_hash, net->ct.expect_vmalloc, 664 nf_ct_free_hashtable(net->ct.expect_hash, nf_ct_expect_hsize);
657 nf_ct_expect_hsize);
658err1: 665err1:
659 return err; 666 return err;
660} 667}
@@ -666,6 +673,5 @@ void nf_conntrack_expect_fini(struct net *net)
666 rcu_barrier(); /* Wait for call_rcu() before destroy */ 673 rcu_barrier(); /* Wait for call_rcu() before destroy */
667 kmem_cache_destroy(nf_ct_expect_cachep); 674 kmem_cache_destroy(nf_ct_expect_cachep);
668 } 675 }
669 nf_ct_free_hashtable(net->ct.expect_hash, net->ct.expect_vmalloc, 676 nf_ct_free_hashtable(net->ct.expect_hash, nf_ct_expect_hsize);
670 nf_ct_expect_hsize);
671} 677}