VYPR
Unrated severityNVD Advisory· Published May 27, 2026· Updated May 27, 2026

CVE-2026-45873

CVE-2026-45873

Description

In the Linux kernel, the following vulnerability has been resolved:

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.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

In the Linux kernel's netfilter nft_set_rbtree, a missing check on overlapping start elements in anonymous interval sets could cause incorrect rule matching.

Vulnerability

The Linux kernel's netfilter subsystem contains a flaw in the nft_set_rbtree implementation (net/netfilter/nft_set_rbtree.c). The anonymous set interval overlap detection logic incorrectly skips checking start elements, assuming user space always provides an optimized representation where adjacent intervals omit the end element. This assumption allows two intervals with the same start value but different ends (e.g., A-B and A-C where C < B) to be added without detecting the partial overlap. The issue is present in the kernel versions that use this infrastructure.

Exploitation

An attacker with the ability to create or modify netfilter rulesets (requiring CAP_NET_ADMIN in a user namespace or root privileges) can craft a set definition containing overlapping anonymous intervals. By exploiting the missing check, the attacker can cause a conflict in the rbtree that may lead to unexpected rule matching behavior.

Impact

Successful exploitation results in incorrect firewall rule evaluation. An attacker could potentially bypass intended packet filtering rules, allowing malicious traffic that should be blocked to pass, or causing legitimate traffic to be dropped. The impact is limited to denial of service or bypass of network filters; no direct remote code execution or privilege escalation is described.

Mitigation

The fix is committed in the Linux kernel stable tree. References [1] and [2] point to the commit that restores the check on overlapping start elements in anonymous sets. Users should update to a kernel version containing commit 4780ec142cbb24b794129d3080eee5cac2943ffc (or the equivalent backport) as soon as possible. No workaround is available other than avoiding the use of anonymous interval sets with overlapping start elements.

AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

1

Patches

16
f1381ce0a1dd

netfilter: nft_set_rbtree: check for partial overlaps in anonymous sets

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitPablo Neira AyusoFixed in 6.1.165via kernel-cna
1 file changed · +25 6
  • net/netfilter/nft_set_rbtree.c+25 6 modified
    diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
    index 021d9e76129a5e..426becaad1b94f 100644
    --- a/net/netfilter/nft_set_rbtree.c
    +++ b/net/netfilter/nft_set_rbtree.c
    @@ -305,11 +305,23 @@ static bool nft_rbtree_update_first(const struct nft_set *set,
     	return false;
     }
     
    +/* Only for anonymous sets which do not allow updates, all element are active. */
    +static struct nft_rbtree_elem *nft_rbtree_prev_active(struct nft_rbtree_elem *rbe)
    +{
    +	struct rb_node *node;
    +
    +	node = rb_prev(&rbe->node);
    +	if (!node)
    +		return NULL;
    +
    +	return rb_entry(node, struct nft_rbtree_elem, node);
    +}
    +
     static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
     			       struct nft_rbtree_elem *new,
     			       struct nft_set_ext **ext)
     {
    -	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL;
    +	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev;
     	struct rb_node *node, *next, *parent, **p, *first = NULL;
     	struct nft_rbtree *priv = nft_set_priv(set);
     	u8 cur_genmask = nft_genmask_cur(net);
    @@ -441,11 +453,19 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
     	/* - new start element with existing closest, less or equal key value
     	 *   being a start element: partial overlap, reported as -ENOTEMPTY.
     	 *   Anonymous sets allow for two consecutive start element since they
    -	 *   are constant, skip them to avoid bogus overlap reports.
    +	 *   are constant, but validate that this new start element does not
    +	 *   sit in between an existing start and end elements: partial overlap,
    +	 *   reported as -ENOTEMPTY.
     	 */
    -	if (!nft_set_is_anonymous(set) && rbe_le &&
    -	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new))
    -		return -ENOTEMPTY;
    +	if (rbe_le &&
    +	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) {
    +		if (!nft_set_is_anonymous(set))
    +			return -ENOTEMPTY;
    +
    +		rbe_prev = nft_rbtree_prev_active(rbe_le);
    +		if (rbe_prev && nft_rbtree_interval_end(rbe_prev))
    +			return -ENOTEMPTY;
    +	}
     
     	/* - new end element with existing closest, less or equal key value
     	 *   being a end element: partial overlap, reported as -ENOTEMPTY.
    -- 
    cgit 1.3-korg
    
    
    
05feaf826390

netfilter: nft_set_rbtree: check for partial overlaps in anonymous sets

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitPablo Neira AyusoFixed in 6.12.75via kernel-cna
1 file changed · +25 6
  • net/netfilter/nft_set_rbtree.c+25 6 modified
    diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
    index 0bbce4505b9771..48ad51a448e7be 100644
    --- a/net/netfilter/nft_set_rbtree.c
    +++ b/net/netfilter/nft_set_rbtree.c
    @@ -309,11 +309,23 @@ static bool nft_rbtree_update_first(const struct nft_set *set,
     	return false;
     }
     
    +/* Only for anonymous sets which do not allow updates, all element are active. */
    +static struct nft_rbtree_elem *nft_rbtree_prev_active(struct nft_rbtree_elem *rbe)
    +{
    +	struct rb_node *node;
    +
    +	node = rb_prev(&rbe->node);
    +	if (!node)
    +		return NULL;
    +
    +	return rb_entry(node, struct nft_rbtree_elem, node);
    +}
    +
     static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
     			       struct nft_rbtree_elem *new,
     			       struct nft_elem_priv **elem_priv)
     {
    -	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL;
    +	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev;
     	struct rb_node *node, *next, *parent, **p, *first = NULL;
     	struct nft_rbtree *priv = nft_set_priv(set);
     	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,
     	/* - new start element with existing closest, less or equal key value
     	 *   being a start element: partial overlap, reported as -ENOTEMPTY.
     	 *   Anonymous sets allow for two consecutive start element since they
    -	 *   are constant, skip them to avoid bogus overlap reports.
    +	 *   are constant, but validate that this new start element does not
    +	 *   sit in between an existing start and end elements: partial overlap,
    +	 *   reported as -ENOTEMPTY.
     	 */
    -	if (!nft_set_is_anonymous(set) && rbe_le &&
    -	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new))
    -		return -ENOTEMPTY;
    +	if (rbe_le &&
    +	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) {
    +		if (!nft_set_is_anonymous(set))
    +			return -ENOTEMPTY;
    +
    +		rbe_prev = nft_rbtree_prev_active(rbe_le);
    +		if (rbe_prev && nft_rbtree_interval_end(rbe_prev))
    +			return -ENOTEMPTY;
    +	}
     
     	/* - new end element with existing closest, less or equal key value
     	 *   being a end element: partial overlap, reported as -ENOTEMPTY.
    -- 
    cgit 1.3-korg
    
    
    
4780ec142cbb

netfilter: nft_set_rbtree: check for partial overlaps in anonymous sets

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitPablo Neira AyusoFixed in 7.0via kernel-cna
1 file changed · +25 6
  • net/netfilter/nft_set_rbtree.c+25 6 modified
    diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
    index 2c240b0ade8701..14b4256bb00d0e 100644
    --- a/net/netfilter/nft_set_rbtree.c
    +++ b/net/netfilter/nft_set_rbtree.c
    @@ -251,11 +251,23 @@ static bool nft_rbtree_update_first(const struct nft_set *set,
     	return false;
     }
     
    +/* Only for anonymous sets which do not allow updates, all element are active. */
    +static struct nft_rbtree_elem *nft_rbtree_prev_active(struct nft_rbtree_elem *rbe)
    +{
    +	struct rb_node *node;
    +
    +	node = rb_prev(&rbe->node);
    +	if (!node)
    +		return NULL;
    +
    +	return rb_entry(node, struct nft_rbtree_elem, node);
    +}
    +
     static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
     			       struct nft_rbtree_elem *new,
     			       struct nft_elem_priv **elem_priv)
     {
    -	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL;
    +	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev;
     	struct rb_node *node, *next, *parent, **p, *first = NULL;
     	struct nft_rbtree *priv = nft_set_priv(set);
     	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,
     	/* - new start element with existing closest, less or equal key value
     	 *   being a start element: partial overlap, reported as -ENOTEMPTY.
     	 *   Anonymous sets allow for two consecutive start element since they
    -	 *   are constant, skip them to avoid bogus overlap reports.
    +	 *   are constant, but validate that this new start element does not
    +	 *   sit in between an existing start and end elements: partial overlap,
    +	 *   reported as -ENOTEMPTY.
     	 */
    -	if (!nft_set_is_anonymous(set) && rbe_le &&
    -	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new))
    -		return -ENOTEMPTY;
    +	if (rbe_le &&
    +	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) {
    +		if (!nft_set_is_anonymous(set))
    +			return -ENOTEMPTY;
    +
    +		rbe_prev = nft_rbtree_prev_active(rbe_le);
    +		if (rbe_prev && nft_rbtree_interval_end(rbe_prev))
    +			return -ENOTEMPTY;
    +	}
     
     	/* - new end element with existing closest, less or equal key value
     	 *   being a end element: partial overlap, reported as -ENOTEMPTY.
    -- 
    cgit 1.3-korg
    
    
    
7ca5813e1b21

netfilter: nft_set_rbtree: check for partial overlaps in anonymous sets

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitPablo Neira AyusoFixed in 5.10.252via kernel-cna
1 file changed · +25 6
  • net/netfilter/nft_set_rbtree.c+25 6 modified
    diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
    index bbced30113e4e2..e3cd66260c2d67 100644
    --- a/net/netfilter/nft_set_rbtree.c
    +++ b/net/netfilter/nft_set_rbtree.c
    @@ -307,11 +307,23 @@ static bool nft_rbtree_update_first(const struct nft_set *set,
     	return false;
     }
     
    +/* Only for anonymous sets which do not allow updates, all element are active. */
    +static struct nft_rbtree_elem *nft_rbtree_prev_active(struct nft_rbtree_elem *rbe)
    +{
    +	struct rb_node *node;
    +
    +	node = rb_prev(&rbe->node);
    +	if (!node)
    +		return NULL;
    +
    +	return rb_entry(node, struct nft_rbtree_elem, node);
    +}
    +
     static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
     			       struct nft_rbtree_elem *new,
     			       struct nft_set_ext **ext)
     {
    -	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL;
    +	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev;
     	struct rb_node *node, *next, *parent, **p, *first = NULL;
     	struct nft_rbtree *priv = nft_set_priv(set);
     	u8 cur_genmask = nft_genmask_cur(net);
    @@ -443,11 +455,19 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
     	/* - new start element with existing closest, less or equal key value
     	 *   being a start element: partial overlap, reported as -ENOTEMPTY.
     	 *   Anonymous sets allow for two consecutive start element since they
    -	 *   are constant, skip them to avoid bogus overlap reports.
    +	 *   are constant, but validate that this new start element does not
    +	 *   sit in between an existing start and end elements: partial overlap,
    +	 *   reported as -ENOTEMPTY.
     	 */
    -	if (!nft_set_is_anonymous(set) && rbe_le &&
    -	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new))
    -		return -ENOTEMPTY;
    +	if (rbe_le &&
    +	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) {
    +		if (!nft_set_is_anonymous(set))
    +			return -ENOTEMPTY;
    +
    +		rbe_prev = nft_rbtree_prev_active(rbe_le);
    +		if (rbe_prev && nft_rbtree_interval_end(rbe_prev))
    +			return -ENOTEMPTY;
    +	}
     
     	/* - new end element with existing closest, less or equal key value
     	 *   being a end element: partial overlap, reported as -ENOTEMPTY.
    -- 
    cgit 1.3-korg
    
    
    
029e5f6a95e9

netfilter: nft_set_rbtree: check for partial overlaps in anonymous sets

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitPablo Neira AyusoFixed in 5.15.202via kernel-cna
1 file changed · +25 6
  • net/netfilter/nft_set_rbtree.c+25 6 modified
    diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
    index 021d9e76129a5e..426becaad1b94f 100644
    --- a/net/netfilter/nft_set_rbtree.c
    +++ b/net/netfilter/nft_set_rbtree.c
    @@ -305,11 +305,23 @@ static bool nft_rbtree_update_first(const struct nft_set *set,
     	return false;
     }
     
    +/* Only for anonymous sets which do not allow updates, all element are active. */
    +static struct nft_rbtree_elem *nft_rbtree_prev_active(struct nft_rbtree_elem *rbe)
    +{
    +	struct rb_node *node;
    +
    +	node = rb_prev(&rbe->node);
    +	if (!node)
    +		return NULL;
    +
    +	return rb_entry(node, struct nft_rbtree_elem, node);
    +}
    +
     static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
     			       struct nft_rbtree_elem *new,
     			       struct nft_set_ext **ext)
     {
    -	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL;
    +	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev;
     	struct rb_node *node, *next, *parent, **p, *first = NULL;
     	struct nft_rbtree *priv = nft_set_priv(set);
     	u8 cur_genmask = nft_genmask_cur(net);
    @@ -441,11 +453,19 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
     	/* - new start element with existing closest, less or equal key value
     	 *   being a start element: partial overlap, reported as -ENOTEMPTY.
     	 *   Anonymous sets allow for two consecutive start element since they
    -	 *   are constant, skip them to avoid bogus overlap reports.
    +	 *   are constant, but validate that this new start element does not
    +	 *   sit in between an existing start and end elements: partial overlap,
    +	 *   reported as -ENOTEMPTY.
     	 */
    -	if (!nft_set_is_anonymous(set) && rbe_le &&
    -	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new))
    -		return -ENOTEMPTY;
    +	if (rbe_le &&
    +	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) {
    +		if (!nft_set_is_anonymous(set))
    +			return -ENOTEMPTY;
    +
    +		rbe_prev = nft_rbtree_prev_active(rbe_le);
    +		if (rbe_prev && nft_rbtree_interval_end(rbe_prev))
    +			return -ENOTEMPTY;
    +	}
     
     	/* - new end element with existing closest, less or equal key value
     	 *   being a end element: partial overlap, reported as -ENOTEMPTY.
    -- 
    cgit 1.3-korg
    
    
    
e6497e06a102

netfilter: nft_set_rbtree: check for partial overlaps in anonymous sets

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitPablo Neira AyusoFixed in 6.19.4via kernel-cna
1 file changed · +25 6
  • net/netfilter/nft_set_rbtree.c+25 6 modified
    diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
    index eacb3acc2b9579..f2a1aa88601849 100644
    --- a/net/netfilter/nft_set_rbtree.c
    +++ b/net/netfilter/nft_set_rbtree.c
    @@ -309,11 +309,23 @@ static bool nft_rbtree_update_first(const struct nft_set *set,
     	return false;
     }
     
    +/* Only for anonymous sets which do not allow updates, all element are active. */
    +static struct nft_rbtree_elem *nft_rbtree_prev_active(struct nft_rbtree_elem *rbe)
    +{
    +	struct rb_node *node;
    +
    +	node = rb_prev(&rbe->node);
    +	if (!node)
    +		return NULL;
    +
    +	return rb_entry(node, struct nft_rbtree_elem, node);
    +}
    +
     static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
     			       struct nft_rbtree_elem *new,
     			       struct nft_elem_priv **elem_priv)
     {
    -	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL;
    +	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev;
     	struct rb_node *node, *next, *parent, **p, *first = NULL;
     	struct nft_rbtree *priv = nft_set_priv(set);
     	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,
     	/* - new start element with existing closest, less or equal key value
     	 *   being a start element: partial overlap, reported as -ENOTEMPTY.
     	 *   Anonymous sets allow for two consecutive start element since they
    -	 *   are constant, skip them to avoid bogus overlap reports.
    +	 *   are constant, but validate that this new start element does not
    +	 *   sit in between an existing start and end elements: partial overlap,
    +	 *   reported as -ENOTEMPTY.
     	 */
    -	if (!nft_set_is_anonymous(set) && rbe_le &&
    -	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new))
    -		return -ENOTEMPTY;
    +	if (rbe_le &&
    +	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) {
    +		if (!nft_set_is_anonymous(set))
    +			return -ENOTEMPTY;
    +
    +		rbe_prev = nft_rbtree_prev_active(rbe_le);
    +		if (rbe_prev && nft_rbtree_interval_end(rbe_prev))
    +			return -ENOTEMPTY;
    +	}
     
     	/* - new end element with existing closest, less or equal key value
     	 *   being a end element: partial overlap, reported as -ENOTEMPTY.
    -- 
    cgit 1.3-korg
    
    
    
f1535d56fc3f

netfilter: nft_set_rbtree: check for partial overlaps in anonymous sets

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitPablo Neira AyusoFixed in 6.6.128via kernel-cna
1 file changed · +25 6
  • net/netfilter/nft_set_rbtree.c+25 6 modified
    diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
    index 04672238e17dce..9c9b07f2def1b1 100644
    --- a/net/netfilter/nft_set_rbtree.c
    +++ b/net/netfilter/nft_set_rbtree.c
    @@ -305,11 +305,23 @@ static bool nft_rbtree_update_first(const struct nft_set *set,
     	return false;
     }
     
    +/* Only for anonymous sets which do not allow updates, all element are active. */
    +static struct nft_rbtree_elem *nft_rbtree_prev_active(struct nft_rbtree_elem *rbe)
    +{
    +	struct rb_node *node;
    +
    +	node = rb_prev(&rbe->node);
    +	if (!node)
    +		return NULL;
    +
    +	return rb_entry(node, struct nft_rbtree_elem, node);
    +}
    +
     static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
     			       struct nft_rbtree_elem *new,
     			       struct nft_set_ext **ext)
     {
    -	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL;
    +	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev;
     	struct rb_node *node, *next, *parent, **p, *first = NULL;
     	struct nft_rbtree *priv = nft_set_priv(set);
     	u8 cur_genmask = nft_genmask_cur(net);
    @@ -441,11 +453,19 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
     	/* - new start element with existing closest, less or equal key value
     	 *   being a start element: partial overlap, reported as -ENOTEMPTY.
     	 *   Anonymous sets allow for two consecutive start element since they
    -	 *   are constant, skip them to avoid bogus overlap reports.
    +	 *   are constant, but validate that this new start element does not
    +	 *   sit in between an existing start and end elements: partial overlap,
    +	 *   reported as -ENOTEMPTY.
     	 */
    -	if (!nft_set_is_anonymous(set) && rbe_le &&
    -	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new))
    -		return -ENOTEMPTY;
    +	if (rbe_le &&
    +	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) {
    +		if (!nft_set_is_anonymous(set))
    +			return -ENOTEMPTY;
    +
    +		rbe_prev = nft_rbtree_prev_active(rbe_le);
    +		if (rbe_prev && nft_rbtree_interval_end(rbe_prev))
    +			return -ENOTEMPTY;
    +	}
     
     	/* - new end element with existing closest, less or equal key value
     	 *   being a end element: partial overlap, reported as -ENOTEMPTY.
    -- 
    cgit 1.3-korg
    
    
    
dad14d22dff1

netfilter: nft_set_rbtree: check for partial overlaps in anonymous sets

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitPablo Neira AyusoFixed in 6.18.14via kernel-cna
1 file changed · +25 6
  • net/netfilter/nft_set_rbtree.c+25 6 modified
    diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
    index eacb3acc2b9579..f2a1aa88601849 100644
    --- a/net/netfilter/nft_set_rbtree.c
    +++ b/net/netfilter/nft_set_rbtree.c
    @@ -309,11 +309,23 @@ static bool nft_rbtree_update_first(const struct nft_set *set,
     	return false;
     }
     
    +/* Only for anonymous sets which do not allow updates, all element are active. */
    +static struct nft_rbtree_elem *nft_rbtree_prev_active(struct nft_rbtree_elem *rbe)
    +{
    +	struct rb_node *node;
    +
    +	node = rb_prev(&rbe->node);
    +	if (!node)
    +		return NULL;
    +
    +	return rb_entry(node, struct nft_rbtree_elem, node);
    +}
    +
     static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
     			       struct nft_rbtree_elem *new,
     			       struct nft_elem_priv **elem_priv)
     {
    -	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL;
    +	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev;
     	struct rb_node *node, *next, *parent, **p, *first = NULL;
     	struct nft_rbtree *priv = nft_set_priv(set);
     	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,
     	/* - new start element with existing closest, less or equal key value
     	 *   being a start element: partial overlap, reported as -ENOTEMPTY.
     	 *   Anonymous sets allow for two consecutive start element since they
    -	 *   are constant, skip them to avoid bogus overlap reports.
    +	 *   are constant, but validate that this new start element does not
    +	 *   sit in between an existing start and end elements: partial overlap,
    +	 *   reported as -ENOTEMPTY.
     	 */
    -	if (!nft_set_is_anonymous(set) && rbe_le &&
    -	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new))
    -		return -ENOTEMPTY;
    +	if (rbe_le &&
    +	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) {
    +		if (!nft_set_is_anonymous(set))
    +			return -ENOTEMPTY;
    +
    +		rbe_prev = nft_rbtree_prev_active(rbe_le);
    +		if (rbe_prev && nft_rbtree_interval_end(rbe_prev))
    +			return -ENOTEMPTY;
    +	}
     
     	/* - new end element with existing closest, less or equal key value
     	 *   being a end element: partial overlap, reported as -ENOTEMPTY.
    -- 
    cgit 1.3-korg
    
    
    
dad14d22dff1

netfilter: nft_set_rbtree: check for partial overlaps in anonymous sets

1 file changed · +25 6
  • net/netfilter/nft_set_rbtree.c+25 6 modified
    diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
    index eacb3acc2b9579..f2a1aa88601849 100644
    --- a/net/netfilter/nft_set_rbtree.c
    +++ b/net/netfilter/nft_set_rbtree.c
    @@ -309,11 +309,23 @@ static bool nft_rbtree_update_first(const struct nft_set *set,
     	return false;
     }
     
    +/* Only for anonymous sets which do not allow updates, all element are active. */
    +static struct nft_rbtree_elem *nft_rbtree_prev_active(struct nft_rbtree_elem *rbe)
    +{
    +	struct rb_node *node;
    +
    +	node = rb_prev(&rbe->node);
    +	if (!node)
    +		return NULL;
    +
    +	return rb_entry(node, struct nft_rbtree_elem, node);
    +}
    +
     static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
     			       struct nft_rbtree_elem *new,
     			       struct nft_elem_priv **elem_priv)
     {
    -	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL;
    +	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev;
     	struct rb_node *node, *next, *parent, **p, *first = NULL;
     	struct nft_rbtree *priv = nft_set_priv(set);
     	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,
     	/* - new start element with existing closest, less or equal key value
     	 *   being a start element: partial overlap, reported as -ENOTEMPTY.
     	 *   Anonymous sets allow for two consecutive start element since they
    -	 *   are constant, skip them to avoid bogus overlap reports.
    +	 *   are constant, but validate that this new start element does not
    +	 *   sit in between an existing start and end elements: partial overlap,
    +	 *   reported as -ENOTEMPTY.
     	 */
    -	if (!nft_set_is_anonymous(set) && rbe_le &&
    -	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new))
    -		return -ENOTEMPTY;
    +	if (rbe_le &&
    +	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) {
    +		if (!nft_set_is_anonymous(set))
    +			return -ENOTEMPTY;
    +
    +		rbe_prev = nft_rbtree_prev_active(rbe_le);
    +		if (rbe_prev && nft_rbtree_interval_end(rbe_prev))
    +			return -ENOTEMPTY;
    +	}
     
     	/* - new end element with existing closest, less or equal key value
     	 *   being a end element: partial overlap, reported as -ENOTEMPTY.
    -- 
    cgit 1.3-korg
    
    
    
7ca5813e1b21

netfilter: nft_set_rbtree: check for partial overlaps in anonymous sets

1 file changed · +25 6
  • net/netfilter/nft_set_rbtree.c+25 6 modified
    diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
    index bbced30113e4e2..e3cd66260c2d67 100644
    --- a/net/netfilter/nft_set_rbtree.c
    +++ b/net/netfilter/nft_set_rbtree.c
    @@ -307,11 +307,23 @@ static bool nft_rbtree_update_first(const struct nft_set *set,
     	return false;
     }
     
    +/* Only for anonymous sets which do not allow updates, all element are active. */
    +static struct nft_rbtree_elem *nft_rbtree_prev_active(struct nft_rbtree_elem *rbe)
    +{
    +	struct rb_node *node;
    +
    +	node = rb_prev(&rbe->node);
    +	if (!node)
    +		return NULL;
    +
    +	return rb_entry(node, struct nft_rbtree_elem, node);
    +}
    +
     static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
     			       struct nft_rbtree_elem *new,
     			       struct nft_set_ext **ext)
     {
    -	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL;
    +	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev;
     	struct rb_node *node, *next, *parent, **p, *first = NULL;
     	struct nft_rbtree *priv = nft_set_priv(set);
     	u8 cur_genmask = nft_genmask_cur(net);
    @@ -443,11 +455,19 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
     	/* - new start element with existing closest, less or equal key value
     	 *   being a start element: partial overlap, reported as -ENOTEMPTY.
     	 *   Anonymous sets allow for two consecutive start element since they
    -	 *   are constant, skip them to avoid bogus overlap reports.
    +	 *   are constant, but validate that this new start element does not
    +	 *   sit in between an existing start and end elements: partial overlap,
    +	 *   reported as -ENOTEMPTY.
     	 */
    -	if (!nft_set_is_anonymous(set) && rbe_le &&
    -	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new))
    -		return -ENOTEMPTY;
    +	if (rbe_le &&
    +	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) {
    +		if (!nft_set_is_anonymous(set))
    +			return -ENOTEMPTY;
    +
    +		rbe_prev = nft_rbtree_prev_active(rbe_le);
    +		if (rbe_prev && nft_rbtree_interval_end(rbe_prev))
    +			return -ENOTEMPTY;
    +	}
     
     	/* - new end element with existing closest, less or equal key value
     	 *   being a end element: partial overlap, reported as -ENOTEMPTY.
    -- 
    cgit 1.3-korg
    
    
    
05feaf826390

netfilter: nft_set_rbtree: check for partial overlaps in anonymous sets

1 file changed · +25 6
  • net/netfilter/nft_set_rbtree.c+25 6 modified
    diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
    index 0bbce4505b9771..48ad51a448e7be 100644
    --- a/net/netfilter/nft_set_rbtree.c
    +++ b/net/netfilter/nft_set_rbtree.c
    @@ -309,11 +309,23 @@ static bool nft_rbtree_update_first(const struct nft_set *set,
     	return false;
     }
     
    +/* Only for anonymous sets which do not allow updates, all element are active. */
    +static struct nft_rbtree_elem *nft_rbtree_prev_active(struct nft_rbtree_elem *rbe)
    +{
    +	struct rb_node *node;
    +
    +	node = rb_prev(&rbe->node);
    +	if (!node)
    +		return NULL;
    +
    +	return rb_entry(node, struct nft_rbtree_elem, node);
    +}
    +
     static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
     			       struct nft_rbtree_elem *new,
     			       struct nft_elem_priv **elem_priv)
     {
    -	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL;
    +	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev;
     	struct rb_node *node, *next, *parent, **p, *first = NULL;
     	struct nft_rbtree *priv = nft_set_priv(set);
     	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,
     	/* - new start element with existing closest, less or equal key value
     	 *   being a start element: partial overlap, reported as -ENOTEMPTY.
     	 *   Anonymous sets allow for two consecutive start element since they
    -	 *   are constant, skip them to avoid bogus overlap reports.
    +	 *   are constant, but validate that this new start element does not
    +	 *   sit in between an existing start and end elements: partial overlap,
    +	 *   reported as -ENOTEMPTY.
     	 */
    -	if (!nft_set_is_anonymous(set) && rbe_le &&
    -	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new))
    -		return -ENOTEMPTY;
    +	if (rbe_le &&
    +	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) {
    +		if (!nft_set_is_anonymous(set))
    +			return -ENOTEMPTY;
    +
    +		rbe_prev = nft_rbtree_prev_active(rbe_le);
    +		if (rbe_prev && nft_rbtree_interval_end(rbe_prev))
    +			return -ENOTEMPTY;
    +	}
     
     	/* - new end element with existing closest, less or equal key value
     	 *   being a end element: partial overlap, reported as -ENOTEMPTY.
    -- 
    cgit 1.3-korg
    
    
    
f1535d56fc3f

netfilter: nft_set_rbtree: check for partial overlaps in anonymous sets

1 file changed · +25 6
  • net/netfilter/nft_set_rbtree.c+25 6 modified
    diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
    index 04672238e17dce..9c9b07f2def1b1 100644
    --- a/net/netfilter/nft_set_rbtree.c
    +++ b/net/netfilter/nft_set_rbtree.c
    @@ -305,11 +305,23 @@ static bool nft_rbtree_update_first(const struct nft_set *set,
     	return false;
     }
     
    +/* Only for anonymous sets which do not allow updates, all element are active. */
    +static struct nft_rbtree_elem *nft_rbtree_prev_active(struct nft_rbtree_elem *rbe)
    +{
    +	struct rb_node *node;
    +
    +	node = rb_prev(&rbe->node);
    +	if (!node)
    +		return NULL;
    +
    +	return rb_entry(node, struct nft_rbtree_elem, node);
    +}
    +
     static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
     			       struct nft_rbtree_elem *new,
     			       struct nft_set_ext **ext)
     {
    -	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL;
    +	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev;
     	struct rb_node *node, *next, *parent, **p, *first = NULL;
     	struct nft_rbtree *priv = nft_set_priv(set);
     	u8 cur_genmask = nft_genmask_cur(net);
    @@ -441,11 +453,19 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
     	/* - new start element with existing closest, less or equal key value
     	 *   being a start element: partial overlap, reported as -ENOTEMPTY.
     	 *   Anonymous sets allow for two consecutive start element since they
    -	 *   are constant, skip them to avoid bogus overlap reports.
    +	 *   are constant, but validate that this new start element does not
    +	 *   sit in between an existing start and end elements: partial overlap,
    +	 *   reported as -ENOTEMPTY.
     	 */
    -	if (!nft_set_is_anonymous(set) && rbe_le &&
    -	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new))
    -		return -ENOTEMPTY;
    +	if (rbe_le &&
    +	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) {
    +		if (!nft_set_is_anonymous(set))
    +			return -ENOTEMPTY;
    +
    +		rbe_prev = nft_rbtree_prev_active(rbe_le);
    +		if (rbe_prev && nft_rbtree_interval_end(rbe_prev))
    +			return -ENOTEMPTY;
    +	}
     
     	/* - new end element with existing closest, less or equal key value
     	 *   being a end element: partial overlap, reported as -ENOTEMPTY.
    -- 
    cgit 1.3-korg
    
    
    
e6497e06a102

netfilter: nft_set_rbtree: check for partial overlaps in anonymous sets

1 file changed · +25 6
  • net/netfilter/nft_set_rbtree.c+25 6 modified
    diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
    index eacb3acc2b9579..f2a1aa88601849 100644
    --- a/net/netfilter/nft_set_rbtree.c
    +++ b/net/netfilter/nft_set_rbtree.c
    @@ -309,11 +309,23 @@ static bool nft_rbtree_update_first(const struct nft_set *set,
     	return false;
     }
     
    +/* Only for anonymous sets which do not allow updates, all element are active. */
    +static struct nft_rbtree_elem *nft_rbtree_prev_active(struct nft_rbtree_elem *rbe)
    +{
    +	struct rb_node *node;
    +
    +	node = rb_prev(&rbe->node);
    +	if (!node)
    +		return NULL;
    +
    +	return rb_entry(node, struct nft_rbtree_elem, node);
    +}
    +
     static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
     			       struct nft_rbtree_elem *new,
     			       struct nft_elem_priv **elem_priv)
     {
    -	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL;
    +	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev;
     	struct rb_node *node, *next, *parent, **p, *first = NULL;
     	struct nft_rbtree *priv = nft_set_priv(set);
     	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,
     	/* - new start element with existing closest, less or equal key value
     	 *   being a start element: partial overlap, reported as -ENOTEMPTY.
     	 *   Anonymous sets allow for two consecutive start element since they
    -	 *   are constant, skip them to avoid bogus overlap reports.
    +	 *   are constant, but validate that this new start element does not
    +	 *   sit in between an existing start and end elements: partial overlap,
    +	 *   reported as -ENOTEMPTY.
     	 */
    -	if (!nft_set_is_anonymous(set) && rbe_le &&
    -	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new))
    -		return -ENOTEMPTY;
    +	if (rbe_le &&
    +	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) {
    +		if (!nft_set_is_anonymous(set))
    +			return -ENOTEMPTY;
    +
    +		rbe_prev = nft_rbtree_prev_active(rbe_le);
    +		if (rbe_prev && nft_rbtree_interval_end(rbe_prev))
    +			return -ENOTEMPTY;
    +	}
     
     	/* - new end element with existing closest, less or equal key value
     	 *   being a end element: partial overlap, reported as -ENOTEMPTY.
    -- 
    cgit 1.3-korg
    
    
    
4780ec142cbb

netfilter: nft_set_rbtree: check for partial overlaps in anonymous sets

1 file changed · +25 6
  • net/netfilter/nft_set_rbtree.c+25 6 modified
    diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
    index 2c240b0ade8701..14b4256bb00d0e 100644
    --- a/net/netfilter/nft_set_rbtree.c
    +++ b/net/netfilter/nft_set_rbtree.c
    @@ -251,11 +251,23 @@ static bool nft_rbtree_update_first(const struct nft_set *set,
     	return false;
     }
     
    +/* Only for anonymous sets which do not allow updates, all element are active. */
    +static struct nft_rbtree_elem *nft_rbtree_prev_active(struct nft_rbtree_elem *rbe)
    +{
    +	struct rb_node *node;
    +
    +	node = rb_prev(&rbe->node);
    +	if (!node)
    +		return NULL;
    +
    +	return rb_entry(node, struct nft_rbtree_elem, node);
    +}
    +
     static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
     			       struct nft_rbtree_elem *new,
     			       struct nft_elem_priv **elem_priv)
     {
    -	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL;
    +	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev;
     	struct rb_node *node, *next, *parent, **p, *first = NULL;
     	struct nft_rbtree *priv = nft_set_priv(set);
     	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,
     	/* - new start element with existing closest, less or equal key value
     	 *   being a start element: partial overlap, reported as -ENOTEMPTY.
     	 *   Anonymous sets allow for two consecutive start element since they
    -	 *   are constant, skip them to avoid bogus overlap reports.
    +	 *   are constant, but validate that this new start element does not
    +	 *   sit in between an existing start and end elements: partial overlap,
    +	 *   reported as -ENOTEMPTY.
     	 */
    -	if (!nft_set_is_anonymous(set) && rbe_le &&
    -	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new))
    -		return -ENOTEMPTY;
    +	if (rbe_le &&
    +	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) {
    +		if (!nft_set_is_anonymous(set))
    +			return -ENOTEMPTY;
    +
    +		rbe_prev = nft_rbtree_prev_active(rbe_le);
    +		if (rbe_prev && nft_rbtree_interval_end(rbe_prev))
    +			return -ENOTEMPTY;
    +	}
     
     	/* - new end element with existing closest, less or equal key value
     	 *   being a end element: partial overlap, reported as -ENOTEMPTY.
    -- 
    cgit 1.3-korg
    
    
    
f1381ce0a1dd

netfilter: nft_set_rbtree: check for partial overlaps in anonymous sets

1 file changed · +25 6
  • net/netfilter/nft_set_rbtree.c+25 6 modified
    diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
    index 021d9e76129a5e..426becaad1b94f 100644
    --- a/net/netfilter/nft_set_rbtree.c
    +++ b/net/netfilter/nft_set_rbtree.c
    @@ -305,11 +305,23 @@ static bool nft_rbtree_update_first(const struct nft_set *set,
     	return false;
     }
     
    +/* Only for anonymous sets which do not allow updates, all element are active. */
    +static struct nft_rbtree_elem *nft_rbtree_prev_active(struct nft_rbtree_elem *rbe)
    +{
    +	struct rb_node *node;
    +
    +	node = rb_prev(&rbe->node);
    +	if (!node)
    +		return NULL;
    +
    +	return rb_entry(node, struct nft_rbtree_elem, node);
    +}
    +
     static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
     			       struct nft_rbtree_elem *new,
     			       struct nft_set_ext **ext)
     {
    -	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL;
    +	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev;
     	struct rb_node *node, *next, *parent, **p, *first = NULL;
     	struct nft_rbtree *priv = nft_set_priv(set);
     	u8 cur_genmask = nft_genmask_cur(net);
    @@ -441,11 +453,19 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
     	/* - new start element with existing closest, less or equal key value
     	 *   being a start element: partial overlap, reported as -ENOTEMPTY.
     	 *   Anonymous sets allow for two consecutive start element since they
    -	 *   are constant, skip them to avoid bogus overlap reports.
    +	 *   are constant, but validate that this new start element does not
    +	 *   sit in between an existing start and end elements: partial overlap,
    +	 *   reported as -ENOTEMPTY.
     	 */
    -	if (!nft_set_is_anonymous(set) && rbe_le &&
    -	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new))
    -		return -ENOTEMPTY;
    +	if (rbe_le &&
    +	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) {
    +		if (!nft_set_is_anonymous(set))
    +			return -ENOTEMPTY;
    +
    +		rbe_prev = nft_rbtree_prev_active(rbe_le);
    +		if (rbe_prev && nft_rbtree_interval_end(rbe_prev))
    +			return -ENOTEMPTY;
    +	}
     
     	/* - new end element with existing closest, less or equal key value
     	 *   being a end element: partial overlap, reported as -ENOTEMPTY.
    -- 
    cgit 1.3-korg
    
    
    
029e5f6a95e9

netfilter: nft_set_rbtree: check for partial overlaps in anonymous sets

1 file changed · +25 6
  • net/netfilter/nft_set_rbtree.c+25 6 modified
    diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
    index 021d9e76129a5e..426becaad1b94f 100644
    --- a/net/netfilter/nft_set_rbtree.c
    +++ b/net/netfilter/nft_set_rbtree.c
    @@ -305,11 +305,23 @@ static bool nft_rbtree_update_first(const struct nft_set *set,
     	return false;
     }
     
    +/* Only for anonymous sets which do not allow updates, all element are active. */
    +static struct nft_rbtree_elem *nft_rbtree_prev_active(struct nft_rbtree_elem *rbe)
    +{
    +	struct rb_node *node;
    +
    +	node = rb_prev(&rbe->node);
    +	if (!node)
    +		return NULL;
    +
    +	return rb_entry(node, struct nft_rbtree_elem, node);
    +}
    +
     static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
     			       struct nft_rbtree_elem *new,
     			       struct nft_set_ext **ext)
     {
    -	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL;
    +	struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev;
     	struct rb_node *node, *next, *parent, **p, *first = NULL;
     	struct nft_rbtree *priv = nft_set_priv(set);
     	u8 cur_genmask = nft_genmask_cur(net);
    @@ -441,11 +453,19 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
     	/* - new start element with existing closest, less or equal key value
     	 *   being a start element: partial overlap, reported as -ENOTEMPTY.
     	 *   Anonymous sets allow for two consecutive start element since they
    -	 *   are constant, skip them to avoid bogus overlap reports.
    +	 *   are constant, but validate that this new start element does not
    +	 *   sit in between an existing start and end elements: partial overlap,
    +	 *   reported as -ENOTEMPTY.
     	 */
    -	if (!nft_set_is_anonymous(set) && rbe_le &&
    -	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new))
    -		return -ENOTEMPTY;
    +	if (rbe_le &&
    +	    nft_rbtree_interval_start(rbe_le) && nft_rbtree_interval_start(new)) {
    +		if (!nft_set_is_anonymous(set))
    +			return -ENOTEMPTY;
    +
    +		rbe_prev = nft_rbtree_prev_active(rbe_le);
    +		if (rbe_prev && nft_rbtree_interval_end(rbe_prev))
    +			return -ENOTEMPTY;
    +	}
     
     	/* - new end element with existing closest, less or equal key value
     	 *   being a end element: partial overlap, reported as -ENOTEMPTY.
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Missing overlap validation for start elements in anonymous rbtree sets allows inserting intervals that partially overlap existing intervals."

Attack vector

An attacker with the ability to add nftables rules using anonymous interval sets can craft two intervals with the same start value but different end values (e.g., A-B and A-C where C &lt; B). The existing overlap detection in `__nft_rbtree_insert` [patch_id=2661819] skips checks on start elements for anonymous sets, so the second interval is accepted despite partially overlapping the first. This can lead to incorrect packet classification or bypass of intended filtering rules.

Affected code

The vulnerability is in `__nft_rbtree_insert()` in `net/netfilter/nft_set_rbtree.c` [patch_id=2661819]. The overlap detection logic for start elements unconditionally skipped anonymous sets, allowing partial overlaps to go undetected.

What the fix does

The patch modifies `__nft_rbtree_insert` in `net/netfilter/nft_set_rbtree.c` [patch_id=2661819] to restore partial overlap detection for anonymous sets. Instead of skipping all anonymous set checks when two start elements are encountered, the new code checks whether the existing start element (`rbe_le`) has a preceding end element (`rbe_prev`). If `rbe_prev` exists and is an interval end, the new start element would sit inside an existing interval, so the insertion is rejected with `-ENOTEMPTY`. A new helper `nft_rbtree_prev_active` is added to safely walk to the previous active node in the rbtree.

Preconditions

  • authThe attacker must be able to add nftables rules using anonymous interval sets (e.g., via nft command or netlink).
  • configThe system must have the nftables subsystem enabled with the rbtree set backend.
  • inputThe attacker must supply two intervals with the same start value where one interval's end is less than the other's end (e.g., A-B and A-C with C < B).

Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

8

News mentions

0

No linked articles in our index yet.