]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
netfilter: nf_tables: do not remove elements if set backend implements .abort
authorPablo Neira Ayuso <pablo@netfilter.org>
Mon, 15 Jul 2024 11:32:31 +0000 (13:32 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 10 Oct 2024 10:03:12 +0000 (12:03 +0200)
[ Upstream commit c9526aeb4998393171d85225ff540e28c7d4ab86 ]

pipapo set backend maintains two copies of the datastructure, removing
the elements from the copy that is going to be discarded slows down
the abort path significantly, from several minutes to few seconds after
this patch.

This patch was previously reverted by

  f86fb94011ae ("netfilter: nf_tables: revert do not remove elements if set backend implements .abort")

but it is now possible since recent work by Florian Westphal to perform
on-demand clone from insert/remove path:

  532aec7e878b ("netfilter: nft_set_pipapo: remove dirty flag")
  3f1d886cc7c3 ("netfilter: nft_set_pipapo: move cloning of match info to insert/removal path")
  a238106703ab ("netfilter: nft_set_pipapo: prepare pipapo_get helper for on-demand clone")
  c5444786d0ea ("netfilter: nft_set_pipapo: merge deactivate helper into caller")
  6c108d9bee44 ("netfilter: nft_set_pipapo: prepare walk function for on-demand clone")
  8b8a2417558c ("netfilter: nft_set_pipapo: prepare destroy function for on-demand clone")
  80efd2997fb9 ("netfilter: nft_set_pipapo: make pipapo_clone helper return NULL")
  a590f4760922 ("netfilter: nft_set_pipapo: move prove_locking helper around")

after this series, the clone is fully released once aborted, no need to
take it back to previous state. Thus, no stale reference to elements can
occur.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/netfilter/nf_tables_api.c

index 472f211472db4851041f70d7aea29723f1e331df..e792f153f9587bab8542d036dbff701f78c8d41f 100644 (file)
@@ -10795,7 +10795,10 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
                                break;
                        }
                        te = nft_trans_container_elem(trans);
-                       nft_setelem_remove(net, te->set, te->elem_priv);
+                       if (!te->set->ops->abort ||
+                           nft_setelem_is_catchall(te->set, te->elem_priv))
+                               nft_setelem_remove(net, te->set, te->elem_priv);
+
                        if (!nft_setelem_is_catchall(te->set, te->elem_priv))
                                atomic_dec(&te->set->nelems);