aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2013-04-30 15:23:18 -0400
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2013-09-30 15:33:25 -0400
commita0f28dc754bb6e78158eb41bf729342f7c2bcd70 (patch)
treeb8ccf07c6f87131c35705a19a0161f5ebbb2edfc
parentb3aabd149c201a7c2a5f9ee673376948ae0724d8 (diff)
netfilter: ipset: Fix sparse warnings due to missing rcu annotations
Reported-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
-rw-r--r--net/netfilter/ipset/ip_set_hash_gen.h87
1 files changed, 55 insertions, 32 deletions
diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h
index 7ff20ecbe185..09a21dd5f120 100644
--- a/net/netfilter/ipset/ip_set_hash_gen.h
+++ b/net/netfilter/ipset/ip_set_hash_gen.h
@@ -15,6 +15,8 @@
15#define rcu_dereference_bh(p) rcu_dereference(p) 15#define rcu_dereference_bh(p) rcu_dereference(p)
16#endif 16#endif
17 17
18#define rcu_dereference_bh_nfnl(p) rcu_dereference_bh_check(p, 1)
19
18#define CONCAT(a, b) a##b 20#define CONCAT(a, b) a##b
19#define TOKEN(a, b) CONCAT(a, b) 21#define TOKEN(a, b) CONCAT(a, b)
20 22
@@ -269,7 +271,7 @@ hbucket_elem_add(struct hbucket *n, u8 ahash_max, size_t dsize)
269 271
270/* The generic hash structure */ 272/* The generic hash structure */
271struct htype { 273struct htype {
272 struct htable *table; /* the hash table */ 274 struct htable __rcu *table; /* the hash table */
273 u32 maxelem; /* max elements in the hash */ 275 u32 maxelem; /* max elements in the hash */
274 u32 elements; /* current element (vs timeout) */ 276 u32 elements; /* current element (vs timeout) */
275 u32 initval; /* random jhash init value */ 277 u32 initval; /* random jhash init value */
@@ -347,10 +349,10 @@ mtype_del_cidr(struct htype *h, u8 cidr, u8 nets_length)
347 349
348/* Calculate the actual memory size of the set data */ 350/* Calculate the actual memory size of the set data */
349static size_t 351static size_t
350mtype_ahash_memsize(const struct htype *h, u8 nets_length) 352mtype_ahash_memsize(const struct htype *h, const struct htable *t,
353 u8 nets_length)
351{ 354{
352 u32 i; 355 u32 i;
353 struct htable *t = h->table;
354 size_t memsize = sizeof(*h) 356 size_t memsize = sizeof(*h)
355 + sizeof(*t) 357 + sizeof(*t)
356#ifdef IP_SET_HASH_WITH_NETS 358#ifdef IP_SET_HASH_WITH_NETS
@@ -369,10 +371,11 @@ static void
369mtype_flush(struct ip_set *set) 371mtype_flush(struct ip_set *set)
370{ 372{
371 struct htype *h = set->data; 373 struct htype *h = set->data;
372 struct htable *t = h->table; 374 struct htable *t;
373 struct hbucket *n; 375 struct hbucket *n;
374 u32 i; 376 u32 i;
375 377
378 t = rcu_dereference_bh_nfnl(h->table);
376 for (i = 0; i < jhash_size(t->htable_bits); i++) { 379 for (i = 0; i < jhash_size(t->htable_bits); i++) {
377 n = hbucket(t, i); 380 n = hbucket(t, i);
378 if (n->size) { 381 if (n->size) {
@@ -397,7 +400,7 @@ mtype_destroy(struct ip_set *set)
397 if (set->extensions & IPSET_EXT_TIMEOUT) 400 if (set->extensions & IPSET_EXT_TIMEOUT)
398 del_timer_sync(&h->gc); 401 del_timer_sync(&h->gc);
399 402
400 ahash_destroy(h->table); 403 ahash_destroy(rcu_dereference_bh_nfnl(h->table));
401#ifdef IP_SET_HASH_WITH_RBTREE 404#ifdef IP_SET_HASH_WITH_RBTREE
402 rbtree_destroy(&h->rbtree); 405 rbtree_destroy(&h->rbtree);
403#endif 406#endif
@@ -443,12 +446,14 @@ mtype_same_set(const struct ip_set *a, const struct ip_set *b)
443static void 446static void
444mtype_expire(struct htype *h, u8 nets_length, size_t dsize) 447mtype_expire(struct htype *h, u8 nets_length, size_t dsize)
445{ 448{
446 struct htable *t = h->table; 449 struct htable *t;
447 struct hbucket *n; 450 struct hbucket *n;
448 struct mtype_elem *data; 451 struct mtype_elem *data;
449 u32 i; 452 u32 i;
450 int j; 453 int j;
451 454
455 rcu_read_lock_bh();
456 t = rcu_dereference_bh(h->table);
452 for (i = 0; i < jhash_size(t->htable_bits); i++) { 457 for (i = 0; i < jhash_size(t->htable_bits); i++) {
453 n = hbucket(t, i); 458 n = hbucket(t, i);
454 for (j = 0; j < n->pos; j++) { 459 for (j = 0; j < n->pos; j++) {
@@ -481,6 +486,7 @@ mtype_expire(struct htype *h, u8 nets_length, size_t dsize)
481 n->value = tmp; 486 n->value = tmp;
482 } 487 }
483 } 488 }
489 rcu_read_unlock_bh();
484} 490}
485 491
486static void 492static void
@@ -505,7 +511,7 @@ static int
505mtype_resize(struct ip_set *set, bool retried) 511mtype_resize(struct ip_set *set, bool retried)
506{ 512{
507 struct htype *h = set->data; 513 struct htype *h = set->data;
508 struct htable *t, *orig = h->table; 514 struct htable *t, *orig = rcu_dereference_bh_nfnl(h->table);
509 u8 htable_bits = orig->htable_bits; 515 u8 htable_bits = orig->htable_bits;
510#ifdef IP_SET_HASH_WITH_NETS 516#ifdef IP_SET_HASH_WITH_NETS
511 u8 flags; 517 u8 flags;
@@ -682,13 +688,15 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
682 struct ip_set_ext *mext, u32 flags) 688 struct ip_set_ext *mext, u32 flags)
683{ 689{
684 struct htype *h = set->data; 690 struct htype *h = set->data;
685 struct htable *t = h->table; 691 struct htable *t;
686 const struct mtype_elem *d = value; 692 const struct mtype_elem *d = value;
687 struct mtype_elem *data; 693 struct mtype_elem *data;
688 struct hbucket *n; 694 struct hbucket *n;
689 int i; 695 int i, ret = -IPSET_ERR_EXIST;
690 u32 key, multi = 0; 696 u32 key, multi = 0;
691 697
698 rcu_read_lock_bh();
699 t = rcu_dereference_bh(h->table);
692 key = HKEY(value, h->initval, t->htable_bits); 700 key = HKEY(value, h->initval, t->htable_bits);
693 n = hbucket(t, key); 701 n = hbucket(t, key);
694 for (i = 0; i < n->pos; i++) { 702 for (i = 0; i < n->pos; i++) {
@@ -697,7 +705,7 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
697 continue; 705 continue;
698 if (SET_WITH_TIMEOUT(set) && 706 if (SET_WITH_TIMEOUT(set) &&
699 ip_set_timeout_expired(ext_timeout(data, h))) 707 ip_set_timeout_expired(ext_timeout(data, h)))
700 return -IPSET_ERR_EXIST; 708 goto out;
701 if (i != n->pos - 1) 709 if (i != n->pos - 1)
702 /* Not last one */ 710 /* Not last one */
703 memcpy(data, ahash_data(n, n->pos - 1, h->dsize), 711 memcpy(data, ahash_data(n, n->pos - 1, h->dsize),
@@ -712,17 +720,22 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
712 void *tmp = kzalloc((n->size - AHASH_INIT_SIZE) 720 void *tmp = kzalloc((n->size - AHASH_INIT_SIZE)
713 * h->dsize, 721 * h->dsize,
714 GFP_ATOMIC); 722 GFP_ATOMIC);
715 if (!tmp) 723 if (!tmp) {
716 return 0; 724 ret = 0;
725 goto out;
726 }
717 n->size -= AHASH_INIT_SIZE; 727 n->size -= AHASH_INIT_SIZE;
718 memcpy(tmp, n->value, n->size * h->dsize); 728 memcpy(tmp, n->value, n->size * h->dsize);
719 kfree(n->value); 729 kfree(n->value);
720 n->value = tmp; 730 n->value = tmp;
721 } 731 }
722 return 0; 732 ret = 0;
733 goto out;
723 } 734 }
724 735
725 return -IPSET_ERR_EXIST; 736out:
737 rcu_read_unlock_bh();
738 return ret;
726} 739}
727 740
728static inline int 741static inline int
@@ -745,7 +758,7 @@ mtype_test_cidrs(struct ip_set *set, struct mtype_elem *d,
745 struct ip_set_ext *mext, u32 flags) 758 struct ip_set_ext *mext, u32 flags)
746{ 759{
747 struct htype *h = set->data; 760 struct htype *h = set->data;
748 struct htable *t = h->table; 761 struct htable *t = rcu_dereference_bh(h->table);
749 struct hbucket *n; 762 struct hbucket *n;
750 struct mtype_elem *data; 763 struct mtype_elem *data;
751 int i, j = 0; 764 int i, j = 0;
@@ -785,18 +798,22 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext,
785 struct ip_set_ext *mext, u32 flags) 798 struct ip_set_ext *mext, u32 flags)
786{ 799{
787 struct htype *h = set->data; 800 struct htype *h = set->data;
788 struct htable *t = h->table; 801 struct htable *t;
789 struct mtype_elem *d = value; 802 struct mtype_elem *d = value;
790 struct hbucket *n; 803 struct hbucket *n;
791 struct mtype_elem *data; 804 struct mtype_elem *data;
792 int i; 805 int i, ret = 0;
793 u32 key, multi = 0; 806 u32 key, multi = 0;
794 807
808 rcu_read_lock_bh();
809 t = rcu_dereference_bh(h->table);
795#ifdef IP_SET_HASH_WITH_NETS 810#ifdef IP_SET_HASH_WITH_NETS
796 /* If we test an IP address and not a network address, 811 /* If we test an IP address and not a network address,
797 * try all possible network sizes */ 812 * try all possible network sizes */
798 if (CIDR(d->cidr) == SET_HOST_MASK(set->family)) 813 if (CIDR(d->cidr) == SET_HOST_MASK(set->family)) {
799 return mtype_test_cidrs(set, d, ext, mext, flags); 814 ret = mtype_test_cidrs(set, d, ext, mext, flags);
815 goto out;
816 }
800#endif 817#endif
801 818
802 key = HKEY(d, h->initval, t->htable_bits); 819 key = HKEY(d, h->initval, t->htable_bits);
@@ -805,10 +822,14 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext,
805 data = ahash_data(n, i, h->dsize); 822 data = ahash_data(n, i, h->dsize);
806 if (mtype_data_equal(data, d, &multi) && 823 if (mtype_data_equal(data, d, &multi) &&
807 !(SET_WITH_TIMEOUT(set) && 824 !(SET_WITH_TIMEOUT(set) &&
808 ip_set_timeout_expired(ext_timeout(data, h)))) 825 ip_set_timeout_expired(ext_timeout(data, h)))) {
809 return mtype_data_match(data, ext, mext, set, flags); 826 ret = mtype_data_match(data, ext, mext, set, flags);
827 goto out;
828 }
810 } 829 }
811 return 0; 830out:
831 rcu_read_unlock_bh();
832 return ret;
812} 833}
813 834
814/* Reply a HEADER request: fill out the header part of the set */ 835/* Reply a HEADER request: fill out the header part of the set */
@@ -816,18 +837,18 @@ static int
816mtype_head(struct ip_set *set, struct sk_buff *skb) 837mtype_head(struct ip_set *set, struct sk_buff *skb)
817{ 838{
818 const struct htype *h = set->data; 839 const struct htype *h = set->data;
840 const struct htable *t;
819 struct nlattr *nested; 841 struct nlattr *nested;
820 size_t memsize; 842 size_t memsize;
821 843
822 read_lock_bh(&set->lock); 844 t = rcu_dereference_bh_nfnl(h->table);
823 memsize = mtype_ahash_memsize(h, NETS_LENGTH(set->family)); 845 memsize = mtype_ahash_memsize(h, t, NETS_LENGTH(set->family));
824 read_unlock_bh(&set->lock);
825 846
826 nested = ipset_nest_start(skb, IPSET_ATTR_DATA); 847 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
827 if (!nested) 848 if (!nested)
828 goto nla_put_failure; 849 goto nla_put_failure;
829 if (nla_put_net32(skb, IPSET_ATTR_HASHSIZE, 850 if (nla_put_net32(skb, IPSET_ATTR_HASHSIZE,
830 htonl(jhash_size(h->table->htable_bits))) || 851 htonl(jhash_size(t->htable_bits))) ||
831 nla_put_net32(skb, IPSET_ATTR_MAXELEM, htonl(h->maxelem))) 852 nla_put_net32(skb, IPSET_ATTR_MAXELEM, htonl(h->maxelem)))
832 goto nla_put_failure; 853 goto nla_put_failure;
833#ifdef IP_SET_HASH_WITH_NETMASK 854#ifdef IP_SET_HASH_WITH_NETMASK
@@ -856,7 +877,7 @@ mtype_list(const struct ip_set *set,
856 struct sk_buff *skb, struct netlink_callback *cb) 877 struct sk_buff *skb, struct netlink_callback *cb)
857{ 878{
858 const struct htype *h = set->data; 879 const struct htype *h = set->data;
859 const struct htable *t = h->table; 880 const struct htable *t = rcu_dereference_bh_nfnl(h->table);
860 struct nlattr *atd, *nested; 881 struct nlattr *atd, *nested;
861 const struct hbucket *n; 882 const struct hbucket *n;
862 const struct mtype_elem *e; 883 const struct mtype_elem *e;
@@ -956,6 +977,7 @@ TOKEN(HTYPE, _create)(struct ip_set *set, struct nlattr *tb[], u32 flags)
956#endif 977#endif
957 size_t hsize; 978 size_t hsize;
958 struct HTYPE *h; 979 struct HTYPE *h;
980 struct htable *t;
959 981
960 if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) 982 if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
961 return -IPSET_ERR_INVALID_FAMILY; 983 return -IPSET_ERR_INVALID_FAMILY;
@@ -1013,12 +1035,13 @@ TOKEN(HTYPE, _create)(struct ip_set *set, struct nlattr *tb[], u32 flags)
1013 kfree(h); 1035 kfree(h);
1014 return -ENOMEM; 1036 return -ENOMEM;
1015 } 1037 }
1016 h->table = ip_set_alloc(hsize); 1038 t = ip_set_alloc(hsize);
1017 if (!h->table) { 1039 if (!t) {
1018 kfree(h); 1040 kfree(h);
1019 return -ENOMEM; 1041 return -ENOMEM;
1020 } 1042 }
1021 h->table->htable_bits = hbits; 1043 t->htable_bits = hbits;
1044 rcu_assign_pointer(h->table, t);
1022 1045
1023 set->data = h; 1046 set->data = h;
1024 if (set->family == NFPROTO_IPV4) 1047 if (set->family == NFPROTO_IPV4)
@@ -1096,8 +1119,8 @@ TOKEN(HTYPE, _create)(struct ip_set *set, struct nlattr *tb[], u32 flags)
1096 } 1119 }
1097 1120
1098 pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n", 1121 pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
1099 set->name, jhash_size(h->table->htable_bits), 1122 set->name, jhash_size(t->htable_bits),
1100 h->table->htable_bits, h->maxelem, set->data, h->table); 1123 t->htable_bits, h->maxelem, set->data, t);
1101 1124
1102 return 0; 1125 return 0;
1103} 1126}