Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: c9e6978e2725 ("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>

authored by

Pablo Neira Ayuso and committed by
Florian Westphal
4780ec14 7f9203f4

+25 -5
+25 -5
net/netfilter/nft_set_rbtree.c
··· 251 251 return false; 252 252 } 253 253 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 + 254 266 static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, 255 267 struct nft_rbtree_elem *new, 256 268 struct nft_elem_priv **elem_priv) 257 269 { 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; 259 271 struct rb_node *node, *next, *parent, **p, *first = NULL; 260 272 struct nft_rbtree *priv = nft_set_priv(set); 261 273 u8 cur_genmask = nft_genmask_cur(net); ··· 405 393 /* - new start element with existing closest, less or equal key value 406 394 * being a start element: partial overlap, reported as -ENOTEMPTY. 407 395 * Anonymous sets allow for two consecutive start element since they 408 - * are constant, skip them to avoid bogus overlap reports. 396 + * are constant, but validate that this new start element does not 397 + * sit in between an existing start and end elements: partial overlap, 398 + * reported as -ENOTEMPTY. 409 399 */ 410 - if (!nft_set_is_anonymous(set) && rbe_le && 411 - nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) 412 - return -ENOTEMPTY; 400 + if (rbe_le && 401 + nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) { 402 + if (!nft_set_is_anonymous(set)) 403 + return -ENOTEMPTY; 404 + 405 + rbe_prev = nft_rbtree_prev_active(rbe_le); 406 + if (rbe_prev && nft_rbtree_interval_end(rbe_prev)) 407 + return -ENOTEMPTY; 408 + } 413 409 414 410 /* - new end element with existing closest, less or equal key value 415 411 * being a end element: partial overlap, reported as -ENOTEMPTY.