diff options
Diffstat (limited to 'net/netfilter')
-rw-r--r-- | net/netfilter/x_tables.c | 26 |
1 files changed, 21 insertions, 5 deletions
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index bfbf521f6ea..bfcac92d556 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c | |||
@@ -625,6 +625,20 @@ void xt_free_table_info(struct xt_table_info *info) | |||
625 | } | 625 | } |
626 | EXPORT_SYMBOL(xt_free_table_info); | 626 | EXPORT_SYMBOL(xt_free_table_info); |
627 | 627 | ||
628 | void xt_table_entry_swap_rcu(struct xt_table_info *oldinfo, | ||
629 | struct xt_table_info *newinfo) | ||
630 | { | ||
631 | unsigned int cpu; | ||
632 | |||
633 | for_each_possible_cpu(cpu) { | ||
634 | void *p = oldinfo->entries[cpu]; | ||
635 | rcu_assign_pointer(oldinfo->entries[cpu], newinfo->entries[cpu]); | ||
636 | newinfo->entries[cpu] = p; | ||
637 | } | ||
638 | |||
639 | } | ||
640 | EXPORT_SYMBOL_GPL(xt_table_entry_swap_rcu); | ||
641 | |||
628 | /* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ | 642 | /* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ |
629 | struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af, | 643 | struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af, |
630 | const char *name) | 644 | const char *name) |
@@ -671,21 +685,22 @@ xt_replace_table(struct xt_table *table, | |||
671 | struct xt_table_info *oldinfo, *private; | 685 | struct xt_table_info *oldinfo, *private; |
672 | 686 | ||
673 | /* Do the substitution. */ | 687 | /* Do the substitution. */ |
674 | write_lock_bh(&table->lock); | 688 | mutex_lock(&table->lock); |
675 | private = table->private; | 689 | private = table->private; |
676 | /* Check inside lock: is the old number correct? */ | 690 | /* Check inside lock: is the old number correct? */ |
677 | if (num_counters != private->number) { | 691 | if (num_counters != private->number) { |
678 | duprintf("num_counters != table->private->number (%u/%u)\n", | 692 | duprintf("num_counters != table->private->number (%u/%u)\n", |
679 | num_counters, private->number); | 693 | num_counters, private->number); |
680 | write_unlock_bh(&table->lock); | 694 | mutex_unlock(&table->lock); |
681 | *error = -EAGAIN; | 695 | *error = -EAGAIN; |
682 | return NULL; | 696 | return NULL; |
683 | } | 697 | } |
684 | oldinfo = private; | 698 | oldinfo = private; |
685 | table->private = newinfo; | 699 | rcu_assign_pointer(table->private, newinfo); |
686 | newinfo->initial_entries = oldinfo->initial_entries; | 700 | newinfo->initial_entries = oldinfo->initial_entries; |
687 | write_unlock_bh(&table->lock); | 701 | mutex_unlock(&table->lock); |
688 | 702 | ||
703 | synchronize_net(); | ||
689 | return oldinfo; | 704 | return oldinfo; |
690 | } | 705 | } |
691 | EXPORT_SYMBOL_GPL(xt_replace_table); | 706 | EXPORT_SYMBOL_GPL(xt_replace_table); |
@@ -719,7 +734,8 @@ struct xt_table *xt_register_table(struct net *net, struct xt_table *table, | |||
719 | 734 | ||
720 | /* Simplifies replace_table code. */ | 735 | /* Simplifies replace_table code. */ |
721 | table->private = bootstrap; | 736 | table->private = bootstrap; |
722 | rwlock_init(&table->lock); | 737 | mutex_init(&table->lock); |
738 | |||
723 | if (!xt_replace_table(table, 0, newinfo, &ret)) | 739 | if (!xt_replace_table(table, 0, newinfo, &ret)) |
724 | goto unlock; | 740 | goto unlock; |
725 | 741 | ||