Skip to content

Commit 7f9203f

Browse files
ummakynesFlorian Westphal
authored andcommitted
netfilter: nft_set_rbtree: fix bogus EEXIST with NLM_F_CREATE with null interval
Userspace adds a non-matching null element to the kernel for historical reasons. This null element is added when the set is populated with elements. Inclusion of this element is conditional, therefore, userspace needs to dump the set content to check for its presence. If the NLM_F_CREATE flag is turned on, this becomes an issue because kernel bogusly reports EEXIST. Add special case to ignore NLM_F_CREATE in this case, therefore, re-adding the nul-element never fails. Fixes: c016c7e ("netfilter: nf_tables: honor NLM_F_EXCL flag in set element insertion") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Florian Westphal <fw@strlen.de>
1 parent 1e13f27 commit 7f9203f

2 files changed

Lines changed: 18 additions & 0 deletions

File tree

net/netfilter/nf_tables_api.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7636,6 +7636,11 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
76367636
* and an existing one.
76377637
*/
76387638
err = -EEXIST;
7639+
} else if (err == -ECANCELED) {
7640+
/* ECANCELED reports an existing nul-element in
7641+
* interval sets.
7642+
*/
7643+
err = 0;
76397644
}
76407645
goto err_element_clash;
76417646
}

net/netfilter/nft_set_rbtree.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ static bool nft_rbtree_interval_start(const struct nft_rbtree_elem *rbe)
5757
return !nft_rbtree_interval_end(rbe);
5858
}
5959

60+
static bool nft_rbtree_interval_null(const struct nft_set *set,
61+
const struct nft_rbtree_elem *rbe)
62+
{
63+
return (!memchr_inv(nft_set_ext_key(&rbe->ext), 0, set->klen) &&
64+
nft_rbtree_interval_end(rbe));
65+
}
66+
6067
static int nft_rbtree_cmp(const struct nft_set *set,
6168
const struct nft_rbtree_elem *e1,
6269
const struct nft_rbtree_elem *e2)
@@ -373,6 +380,12 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
373380
*/
374381
if (rbe_le && !nft_rbtree_cmp(set, new, rbe_le) &&
375382
nft_rbtree_interval_end(rbe_le) == nft_rbtree_interval_end(new)) {
383+
/* - ignore null interval, otherwise NLM_F_CREATE bogusly
384+
* reports EEXIST.
385+
*/
386+
if (nft_rbtree_interval_null(set, new))
387+
return -ECANCELED;
388+
376389
*elem_priv = &rbe_le->priv;
377390
return -EEXIST;
378391
}

0 commit comments

Comments
 (0)