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_pipapo_avx2: don't return non-matching entry on expiry

New test case fails unexpectedly when avx2 matching functions are used.

The test first loads a ranomly generated pipapo set
with 'ipv4 . port' key, i.e. nft -f foo.

This works. Then, it reloads the set after a flush:
(echo flush set t s; cat foo) | nft -f -

This is expected to work, because its the same set after all and it was
already loaded once.

But with avx2, this fails: nft reports a clashing element.

The reported clash is of following form:

We successfully re-inserted
a . b
c . d

Then we try to insert a . d

avx2 finds the already existing a . d, which (due to 'flush set') is marked
as invalid in the new generation. It skips the element and moves to next.

Due to incorrect masking, the skip-step finds the next matching
element *only considering the first field*,

i.e. we return the already reinserted "a . b", even though the
last field is different and the entry should not have been matched.

No such error is reported for the generic c implementation (no avx2) or when
the last field has to use the 'nft_pipapo_avx2_lookup_slow' fallback.

Bisection points to
7711f4bb4b36 ("netfilter: nft_set_pipapo: fix range overlap detection")
but that fix merely uncovers this bug.

Before this commit, the wrong element is returned, but erronously
reported as a full, identical duplicate.

The root-cause is too early return in the avx2 match functions.
When we process the last field, we should continue to process data
until the entire input size has been consumed to make sure no stale
bits remain in the map.

Link: https://lore.kernel.org/netfilter-devel/20260321152506.037f68c0@elisabeth/
Signed-off-by: Florian Westphal <fw@strlen.de>
Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Florian Westphal and committed by
Pablo Neira Ayuso
d3c0037f c4ea7d89

+10 -10
+10 -10
net/netfilter/nft_set_pipapo_avx2.c
··· 242 242 243 243 b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last); 244 244 if (last) 245 - return b; 245 + ret = b; 246 246 247 247 if (unlikely(ret == -1)) 248 248 ret = b / XSAVE_YMM_SIZE; ··· 319 319 320 320 b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last); 321 321 if (last) 322 - return b; 322 + ret = b; 323 323 324 324 if (unlikely(ret == -1)) 325 325 ret = b / XSAVE_YMM_SIZE; ··· 414 414 415 415 b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last); 416 416 if (last) 417 - return b; 417 + ret = b; 418 418 419 419 if (unlikely(ret == -1)) 420 420 ret = b / XSAVE_YMM_SIZE; ··· 505 505 506 506 b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last); 507 507 if (last) 508 - return b; 508 + ret = b; 509 509 510 510 if (unlikely(ret == -1)) 511 511 ret = b / XSAVE_YMM_SIZE; ··· 641 641 642 642 b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last); 643 643 if (last) 644 - return b; 644 + ret = b; 645 645 646 646 if (unlikely(ret == -1)) 647 647 ret = b / XSAVE_YMM_SIZE; ··· 699 699 700 700 b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last); 701 701 if (last) 702 - return b; 702 + ret = b; 703 703 704 704 if (unlikely(ret == -1)) 705 705 ret = b / XSAVE_YMM_SIZE; ··· 764 764 765 765 b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last); 766 766 if (last) 767 - return b; 767 + ret = b; 768 768 769 769 if (unlikely(ret == -1)) 770 770 ret = b / XSAVE_YMM_SIZE; ··· 839 839 840 840 b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last); 841 841 if (last) 842 - return b; 842 + ret = b; 843 843 844 844 if (unlikely(ret == -1)) 845 845 ret = b / XSAVE_YMM_SIZE; ··· 925 925 926 926 b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last); 927 927 if (last) 928 - return b; 928 + ret = b; 929 929 930 930 if (unlikely(ret == -1)) 931 931 ret = b / XSAVE_YMM_SIZE; ··· 1019 1019 1020 1020 b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last); 1021 1021 if (last) 1022 - return b; 1022 + ret = b; 1023 1023 1024 1024 if (unlikely(ret == -1)) 1025 1025 ret = b / XSAVE_YMM_SIZE;