netfilter: nft_set_rbtree: continue traversal if element is inactive
authorFlorian Westphal <fw@strlen.de>
Wed, 10 Sep 2025 08:02:19 +0000 (10:02 +0200)
committerFlorian Westphal <fw@strlen.de>
Wed, 10 Sep 2025 18:30:37 +0000 (20:30 +0200)
commita60f7bf4a1524d8896b76ba89623080aebf44272
treef35c9e84dfdd0fb7af2580f11e272e26f7acadd2
parentc4eaca2e1052adfd67bed0a36a9d4b8e515666e4
netfilter: nft_set_rbtree: continue traversal if element is inactive

When the rbtree lookup function finds a match in the rbtree, it sets the
range start interval to a potentially inactive element.

Then, after tree lookup, if the matching element is inactive, it returns
NULL and suppresses a matching result.

This is wrong and leads to false negative matches when a transaction has
already entered the commit phase.

cpu0 cpu1
  has added new elements to clone
  has marked elements as being
  inactive in new generation
perform lookup in the set
  enters commit phase:
I) increments the genbit
A) observes new genbit
B) finds matching range
C) returns no match: found
range invalid in new generation
II) removes old elements from the tree
C New nft_lookup happening now
          will find matching element,
  because it is no longer
  obscured by old, inactive one.

Consider a packet matching range r1-r2:

cpu0 processes following transaction:
1. remove r1-r2
2. add r1-r3

P is contained in both ranges. Therefore, cpu1 should always find a match
for P.  Due to above race, this is not the case:

cpu1 does find r1-r2, but then ignores it due to the genbit indicating
the range has been removed.  It does NOT test for further matches.

The situation persists for all lookups until after cpu0 hits II) after
which r1-r3 range start node is tested for the first time.

Move the "interval start is valid" check ahead so that tree traversal
continues if the starting interval is not valid in this generation.

Thanks to Stefan Hanreich for providing an initial reproducer for this
bug.

Reported-by: Stefan Hanreich <s.hanreich@proxmox.com>
Fixes: c1eda3c6394f ("netfilter: nft_rbtree: ignore inactive matching element with no descendants")
Signed-off-by: Florian Westphal <fw@strlen.de>
net/netfilter/nft_set_rbtree.c