public inbox for linux-kselftest@vger.kernel.org
 help / color / mirror / Atom feed
From: Vastargazing <vebohr@gmail.com>
To: pablo@netfilter.org, fw@strlen.de
Cc: netfilter-devel@vger.kernel.org, linux-kselftest@vger.kernel.org,
	shuah@kernel.org, linux-kernel@vger.kernel.org,
	Vastargazing <vebohr@gmail.com>
Subject: [PATCH 1/1] selftests: netfilter: add nft_ct timeout destroy race test
Date: Wed, 22 Apr 2026 16:18:18 +0300	[thread overview]
Message-ID: <20260422131818.106417-2-vebohr@gmail.com> (raw)
In-Reply-To: <20260422131818.106417-1-vebohr@gmail.com>

Add a netfilter kselftest for the nft_ct timeout object destroy race
fixed by commit f8dca15a1b19 ("netfilter: nft_ct: fix use-after-free in
timeout object destroy").

Keep creating new TCP connections from one namespace while repeatedly
flushing and recreating the table that owns a ct timeout object. This
exercises concurrent packet processing against the timeout object
teardown path without requiring external traffic tools beyond bash,
nft and ip.

On a KASAN kernel, a regression in the RCU lifetime handling should
show up as a slab-use-after-free report in nf_conntrack_tcp_packet().

Assisted-by: GitHub Copilot:claude-sonnet-4-6
Signed-off-by: Vastargazing <vebohr@gmail.com>
---
 .../testing/selftests/net/netfilter/Makefile  |   1 +
 .../netfilter/nft_ct_timeout_concurrency.sh   | 116 ++++++++++++++++++
 2 files changed, 117 insertions(+)
 create mode 100644 tools/testing/selftests/net/netfilter/nft_ct_timeout_concurrency.sh

diff --git a/tools/testing/selftests/net/netfilter/Makefile b/tools/testing/selftests/net/netfilter/Makefile
index ee2d1a5254f8..bcf53a1ef7ec 100644
--- a/tools/testing/selftests/net/netfilter/Makefile
+++ b/tools/testing/selftests/net/netfilter/Makefile
@@ -25,6 +25,7 @@ TEST_PROGS := \
 	nft_audit.sh \
 	nft_concat_range.sh \
 	nft_conntrack_helper.sh \
+	nft_ct_timeout_concurrency.sh \
 	nft_fib.sh \
 	nft_flowtable.sh \
 	nft_interface_stress.sh \
diff --git a/tools/testing/selftests/net/netfilter/nft_ct_timeout_concurrency.sh b/tools/testing/selftests/net/netfilter/nft_ct_timeout_concurrency.sh
new file mode 100644
index 000000000000..79876cdfb2df
--- /dev/null
+++ b/tools/testing/selftests/net/netfilter/nft_ct_timeout_concurrency.sh
@@ -0,0 +1,116 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Stress nftables ct timeout object destruction while new TCP flows keep
+# attaching the object.
+
+net_netfilter_dir=$(dirname "$(readlink -e "${BASH_SOURCE[0]}")")
+source "$net_netfilter_dir/lib.sh"
+
+checktool "nft --version" "run test without nft tool"
+
+read kernel_tainted < /proc/sys/kernel/tainted
+
+# Default to 80% of the global timeout but keep this stress test short.
+TEST_RUNTIME=$((${kselftest_timeout:-30} * 8 / 10))
+[[ $TEST_RUNTIME -gt 20 ]] && TEST_RUNTIME=20
+
+PORT=12345
+
+cleanup()
+{
+	cleanup_all_ns
+}
+
+load_ruleset()
+{
+	ip netns exec "$ns1" nft -f - <<EOF
+table ip ct_test {
+	ct timeout tcptime {
+		protocol tcp
+		policy = { established: 5s }
+	}
+
+	chain output {
+		type filter hook output priority filter; policy accept;
+		ct state new ip daddr 10.0.1.2 tcp dport $PORT counter ct timeout set "tcptime"
+	}
+}
+EOF
+}
+
+flush_table()
+{
+	ip netns exec "$ns1" nft flush table ip ct_test 2>/dev/null || true
+	ip netns exec "$ns1" nft delete table ip ct_test 2>/dev/null || true
+}
+
+rule_packets()
+{
+	local packets
+
+	packets=$(ip netns exec "$ns1" nft list chain ip ct_test output 2>/dev/null |
+		sed -n 's/.*counter packets \([0-9][0-9]*\) bytes.*/\1/p' |
+		head -n1)
+
+	if [ -n "$packets" ]; then
+		echo "$packets"
+	else
+		echo 0
+	fi
+}
+
+trap cleanup EXIT
+
+setup_ns ns1 ns2 || exit $ksft_skip
+
+if ! ip link add veth0 netns "$ns1" type veth peer name veth0 netns "$ns2" > /dev/null 2>&1; then
+	echo "SKIP: No virtual ethernet pair device support in kernel"
+	exit $ksft_skip
+fi
+
+ip -net "$ns1" link set veth0 up
+ip -net "$ns2" link set veth0 up
+
+ip -net "$ns1" addr add 10.0.1.1/24 dev veth0
+ip -net "$ns2" addr add 10.0.1.2/24 dev veth0
+
+if ! load_ruleset; then
+	echo "SKIP: Could not load ct timeout ruleset"
+	exit $ksft_skip
+fi
+
+ip netns exec "$ns1" bash -c '
+	while :; do
+		exec 3<>/dev/tcp/10.0.1.2/'"$PORT"' 2>/dev/null || true
+		exec 3<&- 3>&-
+	done
+' > /dev/null 2>&1 &
+traffic_pid=$!
+
+if ! busywait_for_counter "$BUSYWAIT_TIMEOUT" 1 rule_packets > /dev/null; then
+	echo "FAIL: Did not observe TCP traffic hitting ct timeout rule"
+	exit $ksft_fail
+fi
+
+end_time=$((SECONDS + TEST_RUNTIME))
+while [ "$SECONDS" -lt "$end_time" ]; do
+	flush_table
+
+	if ! load_ruleset; then
+		echo "FAIL: Could not recreate ct timeout ruleset"
+		exit $ksft_fail
+	fi
+done
+
+flush_table
+
+kill "$traffic_pid" 2>/dev/null
+wait "$traffic_pid" 2>/dev/null
+
+if [[ $kernel_tainted -eq 0 && $(</proc/sys/kernel/tainted) -ne 0 ]]; then
+	echo "FAIL: Kernel is tainted"
+	exit $ksft_fail
+fi
+
+exit $ksft_pass
-- 
2.51.0


  reply	other threads:[~2026-04-22 13:18 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-22 13:18 [PATCH 0/1] selftests: netfilter: add regression test for nft_ct timeout UAF Vastargazing
2026-04-22 13:18 ` Vastargazing [this message]
2026-04-22 13:51   ` [PATCH 1/1] selftests: netfilter: add nft_ct timeout destroy race test Florian Westphal

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260422131818.106417-2-vebohr@gmail.com \
    --to=vebohr@gmail.com \
    --cc=fw@strlen.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=netfilter-devel@vger.kernel.org \
    --cc=pablo@netfilter.org \
    --cc=shuah@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox