]> git.ipfire.org Git - thirdparty/ipset.git/commitdiff
netfilter: ipset: Missing gc cancellations fixed
authorJozsef Kadlecsik <kadlec@netfilter.org>
Sun, 4 Feb 2024 15:09:09 +0000 (16:09 +0100)
committerJozsef Kadlecsik <kadlec@netfilter.org>
Sun, 4 Feb 2024 15:33:40 +0000 (16:33 +0100)
The patch fdb8e12cc2cc ("netfilter: ipset: fix performance regression
in swap operation") missed to add the calls to gc cancellations
at the error path of create operations and at module unload. Also,
because the half of the destroy operations now executed by a
function registered by call_rcu(), neither NFNL_SUBSYS_IPSET mutex
or rcu read lock is held and therefore the checking of them results
false warnings.

Reported-by: syzbot+52bbc0ad036f6f0d4a25@syzkaller.appspotmail.com
Reported-by: Brad Spengler <spender@grsecurity.net>
Reported-by: Стас Ничипорович <stasn77@gmail.com>
Fixes: fdb8e12cc2cc ("netfilter: ipset: fix performance regression in swap operation")
Tested-by: Brad Spengler <spender@grsecurity.net>
Tested-by: Стас Ничипорович <stasn77@gmail.com>
Signed-off-by: Jozsef Kadlecsik <kadlec@netfilter.org>
kernel/net/netfilter/ipset/ip_set_core.c
kernel/net/netfilter/ipset/ip_set_hash_gen.h

index 126312d749c3ad9a6789c122070092c97adfcb8c..94cc91309907dbdb1564c0661b9be821ce56437a 100644 (file)
@@ -1164,6 +1164,7 @@ IPSET_CBFN(ip_set_create, struct net *n, struct sock *ctnl,
        return ret;
 
 cleanup:
+       set->variant->cancel_gc(set);
        set->variant->destroy(set);
 put_out:
        module_put(set->type->me);
@@ -2487,6 +2488,7 @@ ip_set_net_exit(struct net *net)
                set = ip_set(inst, i);
                if (set) {
                        ip_set(inst, i) = NULL;
+                       set->variant->cancel_gc(set);
                        ip_set_destroy_set(set);
                }
        }
index a88acf405bc968c8ed3a9873ccc1835a8d8f6467..cbb2427952fe6ac178883199b5a19f26b4184046 100644 (file)
@@ -432,7 +432,7 @@ mtype_ahash_destroy(struct ip_set *set, struct htable *t, bool ext_destroy)
        u32 i;
 
        for (i = 0; i < jhash_size(t->htable_bits); i++) {
-               n = __ipset_dereference(hbucket(t, i));
+               n = hbucket(t, i);
                if (!n)
                        continue;
                if (set->extensions & IPSET_EXT_DESTROY && ext_destroy)
@@ -452,7 +452,7 @@ mtype_destroy(struct ip_set *set)
        struct htype *h = set->data;
        struct list_head *l, *lt;
 
-       mtype_ahash_destroy(set, ipset_dereference_nfnl(h->table), true);
+       mtype_ahash_destroy(set, h->table, true);
        list_for_each_safe(l, lt, &h->ad) {
                list_del(l);
                kfree(l);