* [PATCH v6.1 0/3] Fix CVE-2026-23272
@ 2026-06-19 9:28 Shivani Agarwal
2026-06-19 9:28 ` [PATCH v6.1 1/3] netfilter: nf_tables: always increment set element count Shivani Agarwal
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Shivani Agarwal @ 2026-06-19 9:28 UTC (permalink / raw)
To: stable, gregkh
Cc: pablo, fw, phil, davem, edumazet, kuba, pabeni, horms,
netfilter-devel, coreteam, netdev, linux-kernel, ajay.kaher,
alexey.makhalov, vamsi-krishna.brahmajosyula, yin.ding,
tapas.kundu, Shivani Agarwal
To fix CVE-2026-23272, commit def602e498a4 is required; however,
it depends on commit d4b7f29eb85c and 8d738c1869f6. Therefore,
both patches have been backported to v6.1.
Florian Westphal (1):
netfilter: nf_tables: always increment set element count
Pablo Neira Ayuso (2):
netfilter: nf_tables: fix set size with rbtree backend
netfilter: nf_tables: unconditionally bump set->nelems before
insertion
include/net/netfilter/nf_tables.h | 6 +++
net/netfilter/nf_tables_api.c | 72 ++++++++++++++++++++++++++-----
net/netfilter/nft_set_rbtree.c | 43 ++++++++++++++++++
3 files changed, 110 insertions(+), 11 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v6.1 1/3] netfilter: nf_tables: always increment set element count
2026-06-19 9:28 [PATCH v6.1 0/3] Fix CVE-2026-23272 Shivani Agarwal
@ 2026-06-19 9:28 ` Shivani Agarwal
2026-06-19 9:28 ` [PATCH v6.1 2/3] netfilter: nf_tables: fix set size with rbtree backend Shivani Agarwal
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Shivani Agarwal @ 2026-06-19 9:28 UTC (permalink / raw)
To: stable, gregkh
Cc: pablo, fw, phil, davem, edumazet, kuba, pabeni, horms,
netfilter-devel, coreteam, netdev, linux-kernel, ajay.kaher,
alexey.makhalov, vamsi-krishna.brahmajosyula, yin.ding,
tapas.kundu, Shivani Agarwal
From: Florian Westphal <fw@strlen.de>
[ Upstream commit d4b7f29eb85c93893bc27388b37709efbc3c9a0e ]
At this time, set->nelems counter only increments when the set has
a maximum size.
All set elements decrement the counter unconditionally, this is
confusing.
Increment the counter unconditionally to make this symmetrical.
This would also allow changing the set maximum size after set creation
in a later patch.
Signed-off-by: Florian Westphal <fw@strlen.de>
[ Shivani: Modified to apply on 6.1.y ]
Signed-off-by: Shivani Agarwal <shivani.agarwal@broadcom.com>
---
net/netfilter/nf_tables_api.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 0c4224282..ec4bfe53b 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -6670,10 +6670,13 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
goto err_element_clash;
}
- if (!(flags & NFT_SET_ELEM_CATCHALL) && set->size &&
- !atomic_add_unless(&set->nelems, 1, set->size + set->ndeact)) {
- err = -ENFILE;
- goto err_set_full;
+ if (!(flags & NFT_SET_ELEM_CATCHALL)) {
+ unsigned int max = set->size ? set->size + set->ndeact : UINT_MAX;
+
+ if (!atomic_add_unless(&set->nelems, 1, max)) {
+ err = -ENFILE;
+ goto err_set_full;
+ }
}
nft_trans_elem(trans) = elem;
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v6.1 2/3] netfilter: nf_tables: fix set size with rbtree backend
2026-06-19 9:28 [PATCH v6.1 0/3] Fix CVE-2026-23272 Shivani Agarwal
2026-06-19 9:28 ` [PATCH v6.1 1/3] netfilter: nf_tables: always increment set element count Shivani Agarwal
@ 2026-06-19 9:28 ` Shivani Agarwal
2026-06-19 9:28 ` [PATCH v6.1 3/3] netfilter: nf_tables: unconditionally bump set->nelems before insertion Shivani Agarwal
2026-06-20 11:54 ` [PATCH v6.1 0/3] Fix CVE-2026-23272 Sasha Levin
3 siblings, 0 replies; 5+ messages in thread
From: Shivani Agarwal @ 2026-06-19 9:28 UTC (permalink / raw)
To: stable, gregkh
Cc: pablo, fw, phil, davem, edumazet, kuba, pabeni, horms,
netfilter-devel, coreteam, netdev, linux-kernel, ajay.kaher,
alexey.makhalov, vamsi-krishna.brahmajosyula, yin.ding,
tapas.kundu, Sasha Levin, Shivani Agarwal
From: Pablo Neira Ayuso <pablo@netfilter.org>
[ Upstream commit 8d738c1869f611955d91d8d0fd0012d9ef207201 ]
The existing rbtree implementation uses singleton elements to represent
ranges, however, userspace provides a set size according to the number
of ranges in the set.
Adjust provided userspace set size to the number of singleton elements
in the kernel by multiplying the range by two.
Check if the no-match all-zero element is already in the set, in such
case release one slot in the set size.
Fixes: 0ed6389c483d ("netfilter: nf_tables: rename set implementations")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
[ Shivani: Modified to apply on 6.1.y ]
Signed-off-by: Shivani Agarwal <shivani.agarwal@broadcom.com>
---
include/net/netfilter/nf_tables.h | 6 ++++
net/netfilter/nf_tables_api.c | 49 +++++++++++++++++++++++++++++--
net/netfilter/nft_set_rbtree.c | 43 +++++++++++++++++++++++++++
3 files changed, 96 insertions(+), 2 deletions(-)
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index dafa0a32e..3329c2eae 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -422,6 +422,9 @@ struct nft_set_ext;
* @remove: remove element from set
* @walk: iterate over all set elements
* @get: get set elements
+ * @ksize: kernel set size
+ * @usize: userspace set size
+ * @adjust_maxsize: delta to adjust maximum set size
* @privsize: function to return size of set private data
* @init: initialize private data of new set instance
* @destroy: destroy private data of set instance
@@ -470,6 +473,9 @@ struct nft_set_ops {
const struct nft_set *set,
const struct nft_set_elem *elem,
unsigned int flags);
+ u32 (*ksize)(u32 size);
+ u32 (*usize)(u32 size);
+ u32 (*adjust_maxsize)(const struct nft_set *set);
void (*commit)(struct nft_set *set);
void (*abort)(const struct nft_set *set);
u64 (*privsize)(const struct nlattr * const nla[],
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index ec4bfe53b..15bfdf07c 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -4264,6 +4264,14 @@ static int nf_tables_fill_set_concat(struct sk_buff *skb,
return 0;
}
+static u32 nft_set_userspace_size(const struct nft_set_ops *ops, u32 size)
+{
+ if (ops->usize)
+ return ops->usize(size);
+
+ return size;
+}
+
static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
const struct nft_set *set, u16 event, u16 flags)
{
@@ -4328,7 +4336,8 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
if (!nest)
goto nla_put_failure;
if (set->size &&
- nla_put_be32(skb, NFTA_SET_DESC_SIZE, htonl(set->size)))
+ nla_put_be32(skb, NFTA_SET_DESC_SIZE,
+ htonl(nft_set_userspace_size(set->ops, set->size))))
goto nla_put_failure;
if (set->field_count > 1 &&
@@ -4698,6 +4707,15 @@ static bool nft_set_is_same(const struct nft_set *set,
return true;
}
+static u32 nft_set_kernel_size(const struct nft_set_ops *ops,
+ const struct nft_set_desc *desc)
+{
+ if (ops->ksize)
+ return ops->ksize(desc->size);
+
+ return desc->size;
+}
+
static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
const struct nlattr * const nla[])
{
@@ -4880,6 +4898,9 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
if (err < 0)
return err;
+ if (desc.size)
+ desc.size = nft_set_kernel_size(set->ops, &desc);
+
err = 0;
if (!nft_set_is_same(set, &desc, exprs, num_exprs, flags)) {
NL_SET_BAD_ATTR(extack, nla[NFTA_SET_NAME]);
@@ -4902,6 +4923,9 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
if (IS_ERR(ops))
return PTR_ERR(ops);
+ if (desc.size)
+ desc.size = nft_set_kernel_size(ops, &desc);
+
udlen = 0;
if (nla[NFTA_SET_USERDATA])
udlen = nla_len(nla[NFTA_SET_USERDATA]);
@@ -6327,6 +6351,27 @@ static bool nft_setelem_valid_key_end(const struct nft_set *set,
return true;
}
+static u32 nft_set_maxsize(const struct nft_set *set)
+{
+ u32 maxsize, delta;
+
+ if (!set->size)
+ return UINT_MAX;
+
+ if (set->ops->adjust_maxsize)
+ delta = set->ops->adjust_maxsize(set);
+ else
+ delta = 0;
+
+ if (check_add_overflow(set->size, set->ndeact, &maxsize))
+ return UINT_MAX;
+
+ if (check_add_overflow(maxsize, delta, &maxsize))
+ return UINT_MAX;
+
+ return maxsize;
+}
+
static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
const struct nlattr *attr, u32 nlmsg_flags)
{
@@ -6671,7 +6716,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
}
if (!(flags & NFT_SET_ELEM_CATCHALL)) {
- unsigned int max = set->size ? set->size + set->ndeact : UINT_MAX;
+ unsigned int max = nft_set_maxsize(set);
if (!atomic_add_unless(&set->nelems, 1, max)) {
err = -ENFILE;
diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
index 426becaad..26e1d994f 100644
--- a/net/netfilter/nft_set_rbtree.c
+++ b/net/netfilter/nft_set_rbtree.c
@@ -775,6 +775,46 @@ static bool nft_rbtree_estimate(const struct nft_set_desc *desc, u32 features,
return true;
}
+/* rbtree stores ranges as singleton elements, each range is composed of two
+ * elements ...
+ */
+static u32 nft_rbtree_ksize(u32 size)
+{
+ return size * 2;
+}
+
+/* ... hide this detail to userspace. */
+static u32 nft_rbtree_usize(u32 size)
+{
+ if (!size)
+ return 0;
+
+ return size / 2;
+}
+
+static u32 nft_rbtree_adjust_maxsize(const struct nft_set *set)
+{
+ struct nft_rbtree *priv = nft_set_priv(set);
+ struct nft_rbtree_elem *rbe;
+ struct rb_node *node;
+ const void *key;
+
+ node = rb_last(&priv->root);
+ if (!node)
+ return 0;
+
+ rbe = rb_entry(node, struct nft_rbtree_elem, node);
+ if (!nft_rbtree_interval_end(rbe))
+ return 0;
+
+ key = nft_set_ext_key(&rbe->ext);
+ if (memchr(key, 1, set->klen))
+ return 0;
+
+ /* this is the all-zero no-match element. */
+ return 1;
+}
+
const struct nft_set_type nft_set_rbtree_type = {
.features = NFT_SET_INTERVAL | NFT_SET_MAP | NFT_SET_OBJECT | NFT_SET_TIMEOUT,
.ops = {
@@ -791,5 +831,8 @@ const struct nft_set_type nft_set_rbtree_type = {
.lookup = nft_rbtree_lookup,
.walk = nft_rbtree_walk,
.get = nft_rbtree_get,
+ .ksize = nft_rbtree_ksize,
+ .usize = nft_rbtree_usize,
+ .adjust_maxsize = nft_rbtree_adjust_maxsize,
},
};
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v6.1 3/3] netfilter: nf_tables: unconditionally bump set->nelems before insertion
2026-06-19 9:28 [PATCH v6.1 0/3] Fix CVE-2026-23272 Shivani Agarwal
2026-06-19 9:28 ` [PATCH v6.1 1/3] netfilter: nf_tables: always increment set element count Shivani Agarwal
2026-06-19 9:28 ` [PATCH v6.1 2/3] netfilter: nf_tables: fix set size with rbtree backend Shivani Agarwal
@ 2026-06-19 9:28 ` Shivani Agarwal
2026-06-20 11:54 ` [PATCH v6.1 0/3] Fix CVE-2026-23272 Sasha Levin
3 siblings, 0 replies; 5+ messages in thread
From: Shivani Agarwal @ 2026-06-19 9:28 UTC (permalink / raw)
To: stable, gregkh
Cc: pablo, fw, phil, davem, edumazet, kuba, pabeni, horms,
netfilter-devel, coreteam, netdev, linux-kernel, ajay.kaher,
alexey.makhalov, vamsi-krishna.brahmajosyula, yin.ding,
tapas.kundu, Inseo An, Li hongliang, Sasha Levin, Shivani Agarwal
From: Pablo Neira Ayuso <pablo@netfilter.org>
[ Upstream commit def602e498a4f951da95c95b1b8ce8ae68aa733a ]
In case that the set is full, a new element gets published then removed
without waiting for the RCU grace period, while RCU reader can be
walking over it already.
To address this issue, add the element transaction even if set is full,
but toggle the set_full flag to report -ENFILE so the abort path safely
unwinds the set to its previous state.
As for element updates, decrement set->nelems to restore it.
A simpler fix is to call synchronize_rcu() in the error path.
However, with a large batch adding elements to already maxed-out set,
this could cause noticeable slowdown of such batches.
Fixes: 35d0ac9070ef ("netfilter: nf_tables: fix set->nelems counting with no NLM_F_EXCL")
Reported-by: Inseo An <y0un9sa@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Florian Westphal <fw@strlen.de>
[ Minor conflict resolved. ]
Signed-off-by: Li hongliang <1468888505@139.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
[ Shivani: Modified to apply on 6.1.y ]
Signed-off-by: Shivani Agarwal <shivani.agarwal@broadcom.com>
---
net/netfilter/nf_tables_api.c | 28 +++++++++++++++-------------
1 file changed, 15 insertions(+), 13 deletions(-)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 15bfdf07c..196ac4e76 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -6388,6 +6388,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
struct nft_data_desc desc;
enum nft_registers dreg;
struct nft_trans *trans;
+ bool set_full = false;
u64 timeout;
u64 expiration;
int err, i;
@@ -6680,10 +6681,18 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
if (err < 0)
goto err_elem_free;
+ if (!(flags & NFT_SET_ELEM_CATCHALL)) {
+ unsigned int max = nft_set_maxsize(set), nelems;
+
+ nelems = atomic_inc_return(&set->nelems);
+ if (nelems > max)
+ set_full = true;
+ }
+
trans = nft_trans_elem_alloc(ctx, NFT_MSG_NEWSETELEM, set);
if (trans == NULL) {
err = -ENOMEM;
- goto err_elem_free;
+ goto err_set_size;
}
ext->genmask = nft_genmask_cur(ctx->net);
@@ -6715,23 +6724,16 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
goto err_element_clash;
}
- if (!(flags & NFT_SET_ELEM_CATCHALL)) {
- unsigned int max = nft_set_maxsize(set);
-
- if (!atomic_add_unless(&set->nelems, 1, max)) {
- err = -ENFILE;
- goto err_set_full;
- }
- }
-
nft_trans_elem(trans) = elem;
nft_trans_commit_list_add_tail(ctx->net, trans);
- return 0;
-err_set_full:
- nft_setelem_remove(ctx->net, set, &elem);
+ return set_full ? -ENFILE : 0;
+
err_element_clash:
kfree(trans);
+err_set_size:
+ if (!(flags & NFT_SET_ELEM_CATCHALL))
+ atomic_dec(&set->nelems);
err_elem_free:
nf_tables_set_elem_destroy(ctx, set, elem.priv);
err_parse_data:
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v6.1 0/3] Fix CVE-2026-23272
2026-06-19 9:28 [PATCH v6.1 0/3] Fix CVE-2026-23272 Shivani Agarwal
` (2 preceding siblings ...)
2026-06-19 9:28 ` [PATCH v6.1 3/3] netfilter: nf_tables: unconditionally bump set->nelems before insertion Shivani Agarwal
@ 2026-06-20 11:54 ` Sasha Levin
3 siblings, 0 replies; 5+ messages in thread
From: Sasha Levin @ 2026-06-20 11:54 UTC (permalink / raw)
To: stable, gregkh
Cc: Sasha Levin, pablo, fw, phil, davem, edumazet, kuba, pabeni,
horms, netfilter-devel, coreteam, netdev, linux-kernel,
ajay.kaher, alexey.makhalov, vamsi-krishna.brahmajosyula,
yin.ding, tapas.kundu, Shivani Agarwal
> [PATCH v6.1 0/3] Fix CVE-2026-23272
Queued the series for 6.1, thanks.
--
Thanks,
Sasha
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-06-20 11:55 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-19 9:28 [PATCH v6.1 0/3] Fix CVE-2026-23272 Shivani Agarwal
2026-06-19 9:28 ` [PATCH v6.1 1/3] netfilter: nf_tables: always increment set element count Shivani Agarwal
2026-06-19 9:28 ` [PATCH v6.1 2/3] netfilter: nf_tables: fix set size with rbtree backend Shivani Agarwal
2026-06-19 9:28 ` [PATCH v6.1 3/3] netfilter: nf_tables: unconditionally bump set->nelems before insertion Shivani Agarwal
2026-06-20 11:54 ` [PATCH v6.1 0/3] Fix CVE-2026-23272 Sasha Levin
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.