Skip to content

Commit 4780ec1

Browse files
ummakynesFlorian Westphal
authored andcommitted
netfilter: nft_set_rbtree: check for partial overlaps in anonymous sets
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>
1 parent 7f9203f commit 4780ec1

1 file changed

Lines changed: 25 additions & 5 deletions

File tree

net/netfilter/nft_set_rbtree.c

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

254+
/* Only for anonymous sets which do not allow updates, all element are active. */
255+
static struct nft_rbtree_elem *nft_rbtree_prev_active(struct nft_rbtree_elem *rbe)
256+
{
257+
struct rb_node *node;
258+
259+
node = rb_prev(&rbe->node);
260+
if (!node)
261+
return NULL;
262+
263+
return rb_entry(node, struct nft_rbtree_elem, node);
264+
}
265+
254266
static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
255267
struct nft_rbtree_elem *new,
256268
struct nft_elem_priv **elem_priv)
257269
{
258-
struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL;
270+
struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev;
259271
struct rb_node *node, *next, *parent, **p, *first = NULL;
260272
struct nft_rbtree *priv = nft_set_priv(set);
261273
u8 cur_genmask = nft_genmask_cur(net);
@@ -393,11 +405,19 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
393405
/* - new start element with existing closest, less or equal key value
394406
* being a start element: partial overlap, reported as -ENOTEMPTY.
395407
* Anonymous sets allow for two consecutive start element since they
396-
* are constant, skip them to avoid bogus overlap reports.
408+
* are constant, but validate that this new start element does not
409+
* sit in between an existing start and end elements: partial overlap,
410+
* reported as -ENOTEMPTY.
397411
*/
398-
if (!nft_set_is_anonymous(set) && rbe_le &&
399-
nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new))
400-
return -ENOTEMPTY;
412+
if (rbe_le &&
413+
nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) {
414+
if (!nft_set_is_anonymous(set))
415+
return -ENOTEMPTY;
416+
417+
rbe_prev = nft_rbtree_prev_active(rbe_le);
418+
if (rbe_prev && nft_rbtree_interval_end(rbe_prev))
419+
return -ENOTEMPTY;
420+
}
401421

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

0 commit comments

Comments
 (0)