* [PATCH nft] tests: shell: add test case for interval set with timeout and aborted transaction
@ 2026-01-29 16:33 Florian Westphal
2026-01-29 16:39 ` Florian Westphal
0 siblings, 1 reply; 2+ messages in thread
From: Florian Westphal @ 2026-01-29 16:33 UTC (permalink / raw)
To: netfilter-devel; +Cc: Florian Westphal
Add a regression test for rbtree+bsearch getting out-of-sync in
nf-next kernel.
This covers the syzkaller reproducer from
https://syzkaller.appspot.com/bug?extid=d417922a3e7935517ef6
which triggers abort with earlier gc at insert time and
additional corner cases where transaction passes without
recording a relevant change in the set (and thus no call to
either abort or commit).
Signed-off-by: Florian Westphal <fw@strlen.de>
---
.../dumps/rbtree_timeout_no_commit.json-nft | 34 ++++++++++
.../sets/dumps/rbtree_timeout_no_commit.nft | 7 +++
.../testcases/sets/rbtree_timeout_no_commit | 63 +++++++++++++++++++
3 files changed, 104 insertions(+)
create mode 100644 tests/shell/testcases/sets/dumps/rbtree_timeout_no_commit.json-nft
create mode 100644 tests/shell/testcases/sets/dumps/rbtree_timeout_no_commit.nft
create mode 100755 tests/shell/testcases/sets/rbtree_timeout_no_commit
diff --git a/tests/shell/testcases/sets/dumps/rbtree_timeout_no_commit.json-nft b/tests/shell/testcases/sets/dumps/rbtree_timeout_no_commit.json-nft
new file mode 100644
index 000000000000..3cf22678e179
--- /dev/null
+++ b/tests/shell/testcases/sets/dumps/rbtree_timeout_no_commit.json-nft
@@ -0,0 +1,34 @@
+{
+ "nftables": [
+ {
+ "metainfo": {
+ "version": "VERSION",
+ "release_name": "RELEASE_NAME",
+ "json_schema_version": 1
+ }
+ },
+ {
+ "table": {
+ "family": "ip",
+ "name": "t",
+ "handle": 0
+ }
+ },
+ {
+ "set": {
+ "family": "ip",
+ "name": "s",
+ "table": "t",
+ "type": "ipv4_addr",
+ "handle": 0,
+ "flags": [
+ "interval",
+ "timeout"
+ ],
+ "elem": [
+ "10.0.0.1"
+ ]
+ }
+ }
+ ]
+}
diff --git a/tests/shell/testcases/sets/dumps/rbtree_timeout_no_commit.nft b/tests/shell/testcases/sets/dumps/rbtree_timeout_no_commit.nft
new file mode 100644
index 000000000000..df0be9af386b
--- /dev/null
+++ b/tests/shell/testcases/sets/dumps/rbtree_timeout_no_commit.nft
@@ -0,0 +1,7 @@
+table ip t {
+ set s {
+ type ipv4_addr
+ flags interval,timeout
+ elements = { 10.0.0.1 }
+ }
+}
diff --git a/tests/shell/testcases/sets/rbtree_timeout_no_commit b/tests/shell/testcases/sets/rbtree_timeout_no_commit
new file mode 100755
index 000000000000..6101fff35e74
--- /dev/null
+++ b/tests/shell/testcases/sets/rbtree_timeout_no_commit
@@ -0,0 +1,63 @@
+#!/bin/bash
+
+# Test for bug added with kernel commit
+# 7e43e0a1141d ("netfilter: nft_set_rbtree: translate rbtree to array for binary search")
+# The binary search blob gets out-of-sync with the rbtree, holding pointers to elements
+# that have been free'd by garbage collection (element timed out).
+#
+# Prerequisite: set has a timed-out entry and 'add/create element' caused
+# that element to be free'd.
+
+# 1. add new element, transaction is later aborted.
+# Commit hook isn't called, so make sure ->abort refreshes the blob too.
+#
+# 2. re-add an existing element, transaction passes.
+# In this case, the commit hook isn't called because we don't have
+# any changes to the set from transaction point of view.
+# Transaction log can even be empty in this case.
+#
+# 3. create (F_EXCL) an existing element.
+# Also triggers abort, but ->abort callback isn't invoked
+# as no element was added.
+
+$NFT -f - <<EOF
+table t {
+ set s {
+ type ipv4_addr
+ flags interval, timeout
+ elements = { 10.0.0.1, 10.0.1.2-10.1.2.4 timeout 1s }
+ }
+}
+EOF
+
+sleep 2
+
+$NFT add element ip t s { 10.0.0.1 } || exit 1
+
+# The above insert triggered GC on the existing element,
+# and the 'add' suceeded (transaction successful).
+# 'get element' must fail and not encounter the removed
+# element.
+$NFT get element ip t s '{ 10.0.1.2 }' && exit 1
+echo "PASS: Did not find expired element after re-adding existing element"
+
+# Re-add an expiring element
+$NFT add element ip t s '{ 10.0.1.2 timeout 1s }' || exit 1
+sleep 2
+
+$NFT -f - <<EOF
+add element ip t s { 10.0.0.3, 10.0.1.5-10.0.1.42 }
+add element inet t s { 10.0.0.3 }
+EOF
+[ $? -eq 0 ] && exit 1
+
+$NFT get element ip t s '{ 10.0.1.2 }' && exit 1
+echo "PASS: Did not find expired element after transaction abort"
+
+# This create must fail, the transaction is aborted.
+# But the failed insertion also triggered GC on the
+# existing element.
+$NFT create element ip t s { 10.0.0.1 } && exit 1
+
+$NFT get element ip t s '{ 10.0.1.2 }' && exit 1
+echo "PASS: Did not find expired element after create failure"
--
2.52.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH nft] tests: shell: add test case for interval set with timeout and aborted transaction
2026-01-29 16:33 [PATCH nft] tests: shell: add test case for interval set with timeout and aborted transaction Florian Westphal
@ 2026-01-29 16:39 ` Florian Westphal
0 siblings, 0 replies; 2+ messages in thread
From: Florian Westphal @ 2026-01-29 16:39 UTC (permalink / raw)
To: netfilter-devel
Florian Westphal <fw@strlen.de> wrote:
> + elements = { 10.0.0.1, 10.0.1.2-10.1.2.4 timeout 1s }
> + }
> +}
> +EOF
> +
> +sleep 2
Argh, I keep forgetting I can use sub-ms timeout :-)
I'll push an amended test that completes a bit faster.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-01-29 16:39 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-29 16:33 [PATCH nft] tests: shell: add test case for interval set with timeout and aborted transaction Florian Westphal
2026-01-29 16:39 ` Florian Westphal
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.