All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Borkmann <daniel@iogearbox.net>
To: kuba@kernel.org
Cc: pabeni@redhat.com, jhs@mojatatu.com, bigeasy@linutronix.de,
	andrii@kernel.org, memxor@gmail.com, bpf@vger.kernel.org,
	netdev@vger.kernel.org
Subject: [PATCH net 3/3] selftests/bpf: Add test for redirect from qdisc qevent block
Date: Tue, 30 Jun 2026 14:33:31 +0200	[thread overview]
Message-ID: <20260630123331.186840-4-daniel@iogearbox.net> (raw)
In-Reply-To: <20260630123331.186840-1-daniel@iogearbox.net>

Add a regression test for the NULL current->bpf_net_context deref hit
when a BPF classifier attached to a qdisc qevent block asks for a
redirect. The classifier runs from tcf_qevent_handle() on the qdisc
enqueue path, outside any bpf_net_context.

  # LDLIBS=-static PKG_CONFIG='pkg-config --static' ./vmtest.sh -- ./test_progs -t qevent
  [...]
  + /etc/rcS.d/S50-startup
  ./test_progs -t qevent
  #496/1   tc_qevent/redirect_verdict:OK
  #496/2   tc_qevent/redirect_helper:OK
  #496     tc_qevent:OK
  Summary: 1/2 PASSED, 0 SKIPPED, 0 FAILED

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
---
 tools/testing/selftests/bpf/config            |   1 +
 .../selftests/bpf/prog_tests/tc_qevent.c      | 113 ++++++++++++++++++
 .../selftests/bpf/progs/test_tc_qevent.c      |  23 ++++
 3 files changed, 137 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/tc_qevent.c
 create mode 100644 tools/testing/selftests/bpf/progs/test_tc_qevent.c

diff --git a/tools/testing/selftests/bpf/config b/tools/testing/selftests/bpf/config
index adb25146e88c..ea7044f30adc 100644
--- a/tools/testing/selftests/bpf/config
+++ b/tools/testing/selftests/bpf/config
@@ -82,6 +82,7 @@ CONFIG_NET_SCH_BPF=y
 CONFIG_NET_SCH_FQ=y
 CONFIG_NET_SCH_INGRESS=y
 CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_RED=y
 CONFIG_NET_SCHED=y
 CONFIG_NETDEVSIM=y
 CONFIG_NETFILTER=y
diff --git a/tools/testing/selftests/bpf/prog_tests/tc_qevent.c b/tools/testing/selftests/bpf/prog_tests/tc_qevent.c
new file mode 100644
index 000000000000..67e1d17567ab
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/tc_qevent.c
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <test_progs.h>
+#include <network_helpers.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "test_tc_qevent.skel.h"
+
+#define NS_TX		"tc_qevent_tx"
+#define NS_RX		"tc_qevent_rx"
+#define IP_TX		"10.255.0.1"
+#define IP_RX		"10.255.0.2"
+#define PIN_PATH	"/sys/fs/bpf/tc_qevent_redirect"
+
+static void blast_udp(void)
+{
+	struct sockaddr_in dst = {};
+	char buf[1400] = {};
+	int fd, i;
+
+	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (!ASSERT_GE(fd, 0, "udp socket"))
+		return;
+
+	dst.sin_family = AF_INET;
+	dst.sin_port = htons(12345);
+	inet_pton(AF_INET, IP_RX, &dst.sin_addr);
+
+	/*
+	 * Push far more than the RED queue can hold. Once qavg crosses qth_min
+	 * every further packet hits the congestion_drop / early_drop qevent.
+	 */
+	for (i = 0; i < 50000; i++)
+		sendto(fd, buf, sizeof(buf), MSG_DONTWAIT,
+		       (struct sockaddr *)&dst, sizeof(dst));
+
+	close(fd);
+}
+
+static void run_qevent_redirect(struct bpf_program *prog, __u64 *counter)
+{
+	struct nstoken *tok = NULL;
+	int err;
+
+	SYS_NOFAIL("ip netns del %s", NS_TX);
+	SYS_NOFAIL("ip netns del %s", NS_RX);
+	unlink(PIN_PATH);
+
+	err = bpf_program__pin(prog, PIN_PATH);
+	if (!ASSERT_OK(err, "pin prog"))
+		return;
+
+	SYS(unpin,  "ip netns add %s", NS_TX);
+	SYS(del_tx, "ip netns add %s", NS_RX);
+	SYS(del_rx, "ip -n %s link add veth0 type veth peer name veth1 netns %s", NS_TX, NS_RX);
+	SYS(del_rx, "ip -n %s addr add %s/24 dev veth0", NS_TX, IP_TX);
+	SYS(del_rx, "ip -n %s link set veth0 up", NS_TX);
+	SYS(del_rx, "ip -n %s addr add %s/24 dev veth1", NS_RX, IP_RX);
+	SYS(del_rx, "ip -n %s link set veth1 up", NS_RX);
+
+	tok = open_netns(NS_TX);
+	if (!ASSERT_OK_PTR(tok, "open_netns"))
+		goto del_rx;
+
+	SYS(close_ns, "tc qdisc add dev veth0 root handle 1: htb default 1");
+	SYS(close_ns, "tc class add dev veth0 parent 1: classid 1:1 htb rate 1mbit ceil 1mbit");
+
+	if (system("tc qdisc add dev veth0 parent 1:1 handle 11: red "
+		   "limit 500000 avpkt 1000 probability 1 min 5000 max 6000 "
+		   "burst 6 qevent early_drop block 10 2>/dev/null")) {
+		test__skip();
+		goto close_ns;
+	}
+
+	if (system("tc filter add block 10 bpf da object-pinned "
+		   PIN_PATH " 2>/dev/null")) {
+		test__skip();
+		goto close_ns;
+	}
+
+	blast_udp();
+	ASSERT_GT(*counter, 0, "qevent classifier ran");
+close_ns:
+	close_netns(tok);
+del_rx:
+	SYS_NOFAIL("ip netns del %s", NS_RX);
+del_tx:
+	SYS_NOFAIL("ip netns del %s", NS_TX);
+unpin:
+	bpf_program__unpin(prog, PIN_PATH);
+}
+
+void test_tc_qevent(void)
+{
+	struct test_tc_qevent *skel;
+
+	skel = test_tc_qevent__open_and_load();
+	if (!ASSERT_OK_PTR(skel, "open_and_load"))
+		return;
+
+	if (test__start_subtest("redirect_verdict"))
+		run_qevent_redirect(skel->progs.qevent_redirect_verdict,
+				    &skel->bss->verdict_calls);
+	if (test__start_subtest("redirect_helper"))
+		run_qevent_redirect(skel->progs.qevent_redirect_helper,
+				    &skel->bss->helper_calls);
+
+	test_tc_qevent__destroy(skel);
+}
diff --git a/tools/testing/selftests/bpf/progs/test_tc_qevent.c b/tools/testing/selftests/bpf/progs/test_tc_qevent.c
new file mode 100644
index 000000000000..1529c111f4aa
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_tc_qevent.c
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+
+int redirect_ifindex = 1;
+__u64 verdict_calls = 0;
+__u64 helper_calls = 0;
+
+SEC("tc")
+int qevent_redirect_verdict(struct __sk_buff *skb)
+{
+	__sync_fetch_and_add(&verdict_calls, 1);
+	return TCX_REDIRECT;
+}
+
+SEC("tc")
+int qevent_redirect_helper(struct __sk_buff *skb)
+{
+	__sync_fetch_and_add(&helper_calls, 1);
+	return bpf_redirect(redirect_ifindex, 0);
+}
+
+char _license[] SEC("license") = "GPL";
-- 
2.43.0


  parent reply	other threads:[~2026-06-30 12:33 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-30 12:33 [PATCH net 0/3] Fix broken TC_ACT_REDIRECT from qdiscs Daniel Borkmann
2026-06-30 12:33 ` [PATCH net 1/3] bpf: Reject redirect helpers without a bpf_net_context Daniel Borkmann
2026-06-30 12:33 ` [PATCH net 2/3] net/sched: Handle TC_ACT_REDIRECT from qdisc filter chains Daniel Borkmann
2026-06-30 15:16   ` Jamal Hadi Salim
2026-06-30 15:23     ` Daniel Borkmann
2026-07-01 15:35       ` Jamal Hadi Salim
2026-07-05  7:26         ` Paolo Abeni
2026-07-05 14:03           ` Jamal Hadi Salim
2026-07-01 12:33   ` sashiko-bot
2026-07-01 13:07     ` Daniel Borkmann
2026-07-06  9:01   ` Paolo Abeni
2026-06-30 12:33 ` Daniel Borkmann [this message]
2026-07-01 12:33   ` [PATCH net 3/3] selftests/bpf: Add test for redirect from qdisc qevent block sashiko-bot
2026-07-01 13:20     ` Daniel Borkmann
2026-06-30 14:37 ` [PATCH net 0/3] Fix broken TC_ACT_REDIRECT from qdiscs Sebastian Andrzej Siewior
2026-06-30 15:09   ` Daniel Borkmann

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=20260630123331.186840-4-daniel@iogearbox.net \
    --to=daniel@iogearbox.net \
    --cc=andrii@kernel.org \
    --cc=bigeasy@linutronix.de \
    --cc=bpf@vger.kernel.org \
    --cc=jhs@mojatatu.com \
    --cc=kuba@kernel.org \
    --cc=memxor@gmail.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    /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 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.