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

authored by

Pablo Neira Ayuso and committed by
Florian Westphal
7f9203f4 1e13f27e

+18
+5
net/netfilter/nf_tables_api.c
··· 7636 7636 * and an existing one. 7637 7637 */ 7638 7638 err = -EEXIST; 7639 + } else if (err == -ECANCELED) { 7640 + /* ECANCELED reports an existing nul-element in 7641 + * interval sets. 7642 + */ 7643 + err = 0; 7639 7644 } 7640 7645 goto err_element_clash; 7641 7646 }
+13
net/netfilter/nft_set_rbtree.c
··· 57 57 return !nft_rbtree_interval_end(rbe); 58 58 } 59 59 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 + 60 67 static int nft_rbtree_cmp(const struct nft_set *set, 61 68 const struct nft_rbtree_elem *e1, 62 69 const struct nft_rbtree_elem *e2) ··· 380 373 */ 381 374 if (rbe_le && !nft_rbtree_cmp(set, new, rbe_le) && 382 375 nft_rbtree_interval_end(rbe_le) == nft_rbtree_interval_end(new)) { 376 + /* - ignore null interval, otherwise NLM_F_CREATE bogusly 377 + * reports EEXIST. 378 + */ 379 + if (nft_rbtree_interval_null(set, new)) 380 + return -ECANCELED; 381 + 383 382 *elem_priv = &rbe_le->priv; 384 383 return -EEXIST; 385 384 }