Skip to content

Commit 33d0779

Browse files
sbrivio-rhummakynes
authored andcommitted
netfilter: nft_set_rbtree: Don't account for expired elements on insertion
While checking the validity of insertion in __nft_rbtree_insert(), we currently ignore conflicting elements and intervals only if they are not active within the next generation. However, if we consider expired elements and intervals as potentially conflicting and overlapping, we'll return error for entries that should be added instead. This is particularly visible with garbage collection intervals that are comparable with the element timeout itself, as reported by Mike Dillinger. Other than the simple issue of denying insertion of valid entries, this might also result in insertion of a single element (opening or closing) out of a given interval. With single entries (that are inserted as intervals of size 1), this leads in turn to the creation of new intervals. For example: # nft add element t s { 192.0.2.1 } # nft list ruleset [...] elements = { 192.0.2.1-255.255.255.255 } Always ignore expired elements active in the next generation, while checking for conflicts. It might be more convenient to introduce a new macro that covers both inactive and expired items, as this type of check also appears quite frequently in other set back-ends. This is however beyond the scope of this fix and can be deferred to a separate patch. Other than the overlap detection cases introduced by commit 7c84d41 ("netfilter: nft_set_rbtree: Detect partial overlaps on insertion"), we also have to cover the original conflict check dealing with conflicts between two intervals of size 1, which was introduced before support for timeout was introduced. This won't return an error to the user as -EEXIST is masked by nft if NLM_F_EXCL is not given, but would result in a silent failure adding the entry. Reported-by: Mike Dillinger <miked@softtalker.com> Cc: <stable@vger.kernel.org> # 5.6.x Fixes: 8d8540c ("netfilter: nft_set_rbtree: add timeout support") Fixes: 7c84d41 ("netfilter: nft_set_rbtree: Detect partial overlaps on insertion") Signed-off-by: Stefano Brivio <sbrivio@redhat.com> Acked-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
1 parent af7b480 commit 33d0779

File tree

1 file changed

+14
-7
lines changed

1 file changed

+14
-7
lines changed

net/netfilter/nft_set_rbtree.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -271,38 +271,45 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
271271

272272
if (nft_rbtree_interval_start(new)) {
273273
if (nft_rbtree_interval_end(rbe) &&
274-
nft_set_elem_active(&rbe->ext, genmask))
274+
nft_set_elem_active(&rbe->ext, genmask) &&
275+
!nft_set_elem_expired(&rbe->ext))
275276
overlap = false;
276277
} else {
277278
overlap = nft_rbtree_interval_end(rbe) &&
278279
nft_set_elem_active(&rbe->ext,
279-
genmask);
280+
genmask) &&
281+
!nft_set_elem_expired(&rbe->ext);
280282
}
281283
} else if (d > 0) {
282284
p = &parent->rb_right;
283285

284286
if (nft_rbtree_interval_end(new)) {
285287
overlap = nft_rbtree_interval_end(rbe) &&
286288
nft_set_elem_active(&rbe->ext,
287-
genmask);
289+
genmask) &&
290+
!nft_set_elem_expired(&rbe->ext);
288291
} else if (nft_rbtree_interval_end(rbe) &&
289-
nft_set_elem_active(&rbe->ext, genmask)) {
292+
nft_set_elem_active(&rbe->ext, genmask) &&
293+
!nft_set_elem_expired(&rbe->ext)) {
290294
overlap = true;
291295
}
292296
} else {
293297
if (nft_rbtree_interval_end(rbe) &&
294298
nft_rbtree_interval_start(new)) {
295299
p = &parent->rb_left;
296300

297-
if (nft_set_elem_active(&rbe->ext, genmask))
301+
if (nft_set_elem_active(&rbe->ext, genmask) &&
302+
!nft_set_elem_expired(&rbe->ext))
298303
overlap = false;
299304
} else if (nft_rbtree_interval_start(rbe) &&
300305
nft_rbtree_interval_end(new)) {
301306
p = &parent->rb_right;
302307

303-
if (nft_set_elem_active(&rbe->ext, genmask))
308+
if (nft_set_elem_active(&rbe->ext, genmask) &&
309+
!nft_set_elem_expired(&rbe->ext))
304310
overlap = false;
305-
} else if (nft_set_elem_active(&rbe->ext, genmask)) {
311+
} else if (nft_set_elem_active(&rbe->ext, genmask) &&
312+
!nft_set_elem_expired(&rbe->ext)) {
306313
*ext = &rbe->ext;
307314
return -EEXIST;
308315
} else {

0 commit comments

Comments
 (0)