Skip to content
/ linux Public

Commit 05feaf8

Browse files
ummakynesSasha Levin
authored andcommitted
netfilter: nft_set_rbtree: check for partial overlaps in anonymous sets
[ Upstream commit 4780ec1 ] Userspace provides an optimized representation in case intervals are adjacent, where the end element is omitted. The existing partial overlap detection logic skips anonymous set checks on start elements for this reason. However, it is possible to add intervals that overlap to this anonymous where two start elements with the same, eg. A-B, A-C where C < B. start end A B start end A C Restore the check on overlapping start elements to report an overlap. Fixes: c9e6978 ("netfilter: nft_set_rbtree: Switch to node list walk for overlap detection") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent afe1a28 commit 05feaf8

File tree

1 file changed

+25
-5
lines changed

1 file changed

+25
-5
lines changed

net/netfilter/nft_set_rbtree.c

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -309,11 +309,23 @@ static bool nft_rbtree_update_first(const struct nft_set *set,
309309
return false;
310310
}
311311

312+
/* Only for anonymous sets which do not allow updates, all element are active. */
313+
static struct nft_rbtree_elem *nft_rbtree_prev_active(struct nft_rbtree_elem *rbe)
314+
{
315+
struct rb_node *node;
316+
317+
node = rb_prev(&rbe->node);
318+
if (!node)
319+
return NULL;
320+
321+
return rb_entry(node, struct nft_rbtree_elem, node);
322+
}
323+
312324
static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
313325
struct nft_rbtree_elem *new,
314326
struct nft_elem_priv **elem_priv)
315327
{
316-
struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL;
328+
struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev;
317329
struct rb_node *node, *next, *parent, **p, *first = NULL;
318330
struct nft_rbtree *priv = nft_set_priv(set);
319331
u8 cur_genmask = nft_genmask_cur(net);
@@ -451,11 +463,19 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
451463
/* - new start element with existing closest, less or equal key value
452464
* being a start element: partial overlap, reported as -ENOTEMPTY.
453465
* Anonymous sets allow for two consecutive start element since they
454-
* are constant, skip them to avoid bogus overlap reports.
466+
* are constant, but validate that this new start element does not
467+
* sit in between an existing start and end elements: partial overlap,
468+
* reported as -ENOTEMPTY.
455469
*/
456-
if (!nft_set_is_anonymous(set) && rbe_le &&
457-
nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new))
458-
return -ENOTEMPTY;
470+
if (rbe_le &&
471+
nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) {
472+
if (!nft_set_is_anonymous(set))
473+
return -ENOTEMPTY;
474+
475+
rbe_prev = nft_rbtree_prev_active(rbe_le);
476+
if (rbe_prev && nft_rbtree_interval_end(rbe_prev))
477+
return -ENOTEMPTY;
478+
}
459479

460480
/* - new end element with existing closest, less or equal key value
461481
* being a end element: partial overlap, reported as -ENOTEMPTY.

0 commit comments

Comments
 (0)