Skip to content

Commit 39c4be3

Browse files
committed
netfilter: nft_set_pipapo_avx2: fix skip of expired entries
JIRA: https://issues.redhat.com/browse/RHEL-113001 Upstream Status: commit 5823699 commit 5823699 Author: Florian Westphal <fw@strlen.de> Date: Tue Sep 9 14:11:48 2025 +0200 netfilter: nft_set_pipapo_avx2: fix skip of expired entries KASAN reports following splat: BUG: KASAN: slab-out-of-bounds in pipapo_get_avx2+0x941/0x25d0 Read of size 1 at addr ffff88814c561be0 by task nft/3944 Call Trace: pipapo_get_avx2+0x941/0x25d0 nft_pipapo_insert+0x440/0x11b0 nf_tables_newsetelem+0x220a/0x3a00 .. This bisects to commit 84c1da7 ("netfilter: nft_set_pipapo: use AVX2 algorithm for insertions too"). However, that change merely uncovers this bug. When we find a match but that match has expired or timed out, the AVX2 implementation restarts the full match loop. At that point, the pointer to the key data has already been changed and points to the keys last field. This will then result in out-of-bounds read once its incremented again for the next field. The restart logic in AVX2 is different compared to the plain C implementation, but both should follow the same logic. The C implementation just calls pipapo_refill() again do check the next entry. Do the same in the AVX2 implementation. Note that with this change, due to implementation differences of pipapo_refill vs. nft_pipapo_avx2_refill, the refill call will return the same element again. Then, on the next call, it will move to the next entry as expected. This is because avx2_refill doesn't clear the bitmap in the 'last' conditional. This is harmless. Expired/timed out elements are also not expected to be frequent. selftest is added in a followup commit. Fixes: 7400b06 ("nft_set_pipapo: Introduce AVX2-based lookup implementation") Reviewed-by: Stefano Brivio <sbrivio@redhat.com> Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Florian Westphal <fwestpha@redhat.com>
1 parent afdc40f commit 39c4be3

File tree

1 file changed

+5
-2
lines changed

1 file changed

+5
-2
lines changed

net/netfilter/nft_set_pipapo_avx2.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,7 +1192,6 @@ nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
11921192

11931193
nft_pipapo_avx2_prepare();
11941194

1195-
next_match:
11961195
nft_pipapo_for_each_field(f, i, m) {
11971196
bool last = i == m->field_count - 1, first = !i;
11981197
int ret = 0;
@@ -1239,14 +1238,18 @@ nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
12391238

12401239
#undef NFT_SET_PIPAPO_AVX2_LOOKUP
12411240

1241+
next_match:
12421242
if (ret < 0)
12431243
goto out;
12441244

12451245
if (last) {
12461246
const struct nft_set_ext *e = &f->mt[ret].e->ext;
12471247

1248-
if (unlikely(nft_set_elem_expired(e)))
1248+
if (unlikely(nft_set_elem_expired(e))) {
1249+
ret = pipapo_refill(res, f->bsize, f->rules,
1250+
fill, f->mt, last);
12491251
goto next_match;
1252+
}
12501253

12511254
ext = e;
12521255
goto out;

0 commit comments

Comments
 (0)