Skip to content

Commit

Permalink
netfilter: nft_set_rbtree: skip elements in transaction from garbage …
Browse files Browse the repository at this point in the history
…collection

[ Upstream commit 5d235d6 ]

Skip interference with an ongoing transaction, do not perform garbage
collection on inactive elements. Reset annotated previous end interval
if the expired element is marked as busy (control plane removed the
element right before expiration).

Fixes: 8d8540c ("netfilter: nft_set_rbtree: add timeout support")
Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
ummakynes authored and gregkh committed Feb 1, 2023
1 parent 318cb24 commit 44d6de3
Showing 1 changed file with 15 additions and 1 deletion.
16 changes: 15 additions & 1 deletion net/netfilter/nft_set_rbtree.c
Expand Up @@ -563,23 +563,37 @@ static void nft_rbtree_gc(struct work_struct *work)
struct nft_rbtree *priv;
struct rb_node *node;
struct nft_set *set;
struct net *net;
u8 genmask;

priv = container_of(work, struct nft_rbtree, gc_work.work);
set = nft_set_container_of(priv);
net = read_pnet(&set->net);
genmask = nft_genmask_cur(net);

write_lock_bh(&priv->lock);
write_seqcount_begin(&priv->count);
for (node = rb_first(&priv->root); node != NULL; node = rb_next(node)) {
rbe = rb_entry(node, struct nft_rbtree_elem, node);

if (!nft_set_elem_active(&rbe->ext, genmask))
continue;

/* elements are reversed in the rbtree for historical reasons,
* from highest to lowest value, that is why end element is
* always visited before the start element.
*/
if (nft_rbtree_interval_end(rbe)) {
rbe_end = rbe;
continue;
}
if (!nft_set_elem_expired(&rbe->ext))
continue;
if (nft_set_elem_mark_busy(&rbe->ext))

if (nft_set_elem_mark_busy(&rbe->ext)) {
rbe_end = NULL;
continue;
}

if (rbe_prev) {
rb_erase(&rbe_prev->node, &priv->root);
Expand Down

0 comments on commit 44d6de3

Please sign in to comment.