netfilter: nf_tables: avoid false-positive lockdep splats in set walker
authorFlorian Westphal <fw@strlen.de>
Mon, 4 Nov 2024 09:41:16 +0000 (10:41 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Tue, 5 Nov 2024 21:06:22 +0000 (22:06 +0100)
Its not possible to add or delete elements from hash and bitmap sets,
as long as caller is holding the transaction mutex, so its ok to iterate
the list outside of rcu read side critical section.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/netfilter/nft_set_bitmap.c
net/netfilter/nft_set_hash.c

index 1caa04619dc6da37f845acc65c8ca86c173096de..12390d2e994fc6e5aa800396ec2f2385e53efa21 100644 (file)
@@ -88,13 +88,15 @@ bool nft_bitmap_lookup(const struct net *net, const struct nft_set *set,
 }
 
 static struct nft_bitmap_elem *
-nft_bitmap_elem_find(const struct nft_set *set, struct nft_bitmap_elem *this,
+nft_bitmap_elem_find(const struct net *net,
+                    const struct nft_set *set, struct nft_bitmap_elem *this,
                     u8 genmask)
 {
        const struct nft_bitmap *priv = nft_set_priv(set);
        struct nft_bitmap_elem *be;
 
-       list_for_each_entry_rcu(be, &priv->list, head) {
+       list_for_each_entry_rcu(be, &priv->list, head,
+                               lockdep_is_held(&nft_pernet(net)->commit_mutex)) {
                if (memcmp(nft_set_ext_key(&be->ext),
                           nft_set_ext_key(&this->ext), set->klen) ||
                    !nft_set_elem_active(&be->ext, genmask))
@@ -132,7 +134,7 @@ static int nft_bitmap_insert(const struct net *net, const struct nft_set *set,
        u8 genmask = nft_genmask_next(net);
        u32 idx, off;
 
-       be = nft_bitmap_elem_find(set, new, genmask);
+       be = nft_bitmap_elem_find(net, set, new, genmask);
        if (be) {
                *elem_priv = &be->priv;
                return -EEXIST;
@@ -201,7 +203,7 @@ nft_bitmap_deactivate(const struct net *net, const struct nft_set *set,
 
        nft_bitmap_location(set, elem->key.val.data, &idx, &off);
 
-       be = nft_bitmap_elem_find(set, this, genmask);
+       be = nft_bitmap_elem_find(net, set, this, genmask);
        if (!be)
                return NULL;
 
index daa56dda737ae2e6b4727c2d3930d68e58a33efb..65bd291318f2ac4a813feaadbf06e09bbca044e3 100644 (file)
@@ -647,7 +647,8 @@ static void nft_hash_walk(const struct nft_ctx *ctx, struct nft_set *set,
        int i;
 
        for (i = 0; i < priv->buckets; i++) {
-               hlist_for_each_entry_rcu(he, &priv->table[i], node) {
+               hlist_for_each_entry_rcu(he, &priv->table[i], node,
+                                        lockdep_is_held(&nft_pernet(ctx->net)->commit_mutex)) {
                        if (iter->count < iter->skip)
                                goto cont;