]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
netfilter: ipset: Don't use test_bit() in lockless RCU readers in hash types
authorJozsef Kadlecsik <kadlec@netfilter.org>
Wed, 17 Jun 2026 08:41:22 +0000 (10:41 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Sat, 20 Jun 2026 22:18:26 +0000 (00:18 +0200)
Sashiko pointed out that there are a few lockless RCU readers
using test_bit() which is a relaxed atomic operation and
provides no memory barrier guarantees. Use test_bit_acquire()
instead where the operation may run parallel with add/del/gc,
i.e. is not one from the next cases

- protected by region lock
- in a set destroy phase
- in a new/temporary set creation phase

Fixes: 18f84d41d34f ("netfilter: ipset: Introduce RCU locking in hash:* types")
Signed-off-by: Jozsef Kadlecsik <kadlec@netfilter.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/netfilter/ipset/ip_set_hash_gen.h

index 04e4627ddfc10e94570539ed436d166aee9d35fc..00c27b95207f79967da8f1c700708765546a6a81 100644 (file)
@@ -689,7 +689,7 @@ retry:
                                continue;
                        pos = smp_load_acquire(&n->pos);
                        for (j = 0; j < pos; j++) {
-                               if (!test_bit(j, n->used))
+                               if (!test_bit_acquire(j, n->used))
                                        continue;
                                data = ahash_data(n, j, dsize);
                                if (SET_ELEM_EXPIRED(set, data))
@@ -826,7 +826,7 @@ mtype_ext_size(struct ip_set *set, u32 *elements, size_t *ext_size)
                                continue;
                        pos = smp_load_acquire(&n->pos);
                        for (j = 0; j < pos; j++) {
-                               if (!test_bit(j, n->used))
+                               if (!test_bit_acquire(j, n->used))
                                        continue;
                                data = ahash_data(n, j, set->dsize);
                                if (!SET_ELEM_EXPIRED(set, data))
@@ -1201,7 +1201,7 @@ mtype_test_cidrs(struct ip_set *set, struct mtype_elem *d,
                        continue;
                pos = smp_load_acquire(&n->pos);
                for (i = 0; i < pos; i++) {
-                       if (!test_bit(i, n->used))
+                       if (!test_bit_acquire(i, n->used))
                                continue;
                        data = ahash_data(n, i, set->dsize);
                        if (!mtype_data_equal(data, d, &multi))
@@ -1259,7 +1259,7 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext,
        }
        pos = smp_load_acquire(&n->pos);
        for (i = 0; i < pos; i++) {
-               if (!test_bit(i, n->used))
+               if (!test_bit_acquire(i, n->used))
                        continue;
                data = ahash_data(n, i, set->dsize);
                if (!mtype_data_equal(data, d, &multi))
@@ -1396,7 +1396,7 @@ mtype_list(const struct ip_set *set,
                        continue;
                pos = smp_load_acquire(&n->pos);
                for (i = 0; i < pos; i++) {
-                       if (!test_bit(i, n->used))
+                       if (!test_bit_acquire(i, n->used))
                                continue;
                        e = ahash_data(n, i, set->dsize);
                        if (SET_ELEM_EXPIRED(set, e))