From: Daniel Borkmann <daniel@iogearbox.net>
To: bpf@vger.kernel.org
Cc: ast@kernel.org, andrii@kernel.org, jolsa@kernel.org,
Menglong Dong <dongml2@chinatelecom.cn>,
Steven Rostedt <rostedt@goodmis.org>
Subject: [PATCH bpf 2/2] selftests/bpf: Test kprobe and fentry programs on one function
Date: Sat, 24 Oct 2026 09:37:12 +0200 [thread overview]
Message-ID: <20261024073712.1074591-2-daniel@iogearbox.net> (raw)
In-Reply-To: <20261024073712.1074591-1-daniel@iogearbox.net>
A kprobe next to a BPF trampoline makes the ftrace site of the function
call ftrace_regs_caller and from there the list of ftrace callbacks,
the path that crashed while ftrace_ops_list_func() started at an odd
address. No test covers a function traced by both. Thus, attach an
fentry program and a kprobe to bpf_fentry_test1(), then a second fentry
program, which modifies the trampoline of the shared site, then detach
the kprobe. After each step, check that every attached program ran once
for the call and saw its argument.
Without the previous fix the test crashes the kernel, but only where
ftrace_ops_list_func() is at an odd address (in my test with gcc +
CONFIG_CC_OPTIMIZE_FOR_SIZE=y). With the fix it passes:
# LDLIBS=-static PKG_CONFIG='pkg-config --static' ./vmtest.sh -- ./test_progs -t fentry_kprobe_shared
[...]
#147 fentry_kprobe_shared:OK
Summary: 1/0 PASSED, 0 SKIPPED, 0/0 FAILED
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Cc: Menglong Dong <dongml2@chinatelecom.cn>
Cc: Steven Rostedt <rostedt@goodmis.org>
---
.../bpf/prog_tests/fentry_kprobe_shared.c | 54 +++++++++++++++++++
.../bpf/progs/fentry_kprobe_shared.c | 40 ++++++++++++++
2 files changed, 94 insertions(+)
create mode 100644 tools/testing/selftests/bpf/prog_tests/fentry_kprobe_shared.c
create mode 100644 tools/testing/selftests/bpf/progs/fentry_kprobe_shared.c
diff --git a/tools/testing/selftests/bpf/prog_tests/fentry_kprobe_shared.c b/tools/testing/selftests/bpf/prog_tests/fentry_kprobe_shared.c
new file mode 100644
index 000000000000..b53ddb983f6f
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/fentry_kprobe_shared.c
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <test_progs.h>
+#include "fentry_kprobe_shared.skel.h"
+
+static void trigger(struct fentry_kprobe_shared *skel)
+{
+ LIBBPF_OPTS(bpf_test_run_opts, topts);
+ int err;
+
+ err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.fentry1), &topts);
+ ASSERT_OK(err, "test_run");
+}
+
+/*
+ * With a kprobe next to the trampoline, the ftrace site of the function
+ * reaches the trampoline through the list of ftrace callbacks, and so does
+ * the site of a trampoline that is modified to add or remove a program.
+ */
+void test_fentry_kprobe_shared(void)
+{
+ struct fentry_kprobe_shared *skel;
+
+ skel = fentry_kprobe_shared__open_and_load();
+ if (!ASSERT_OK_PTR(skel, "open_and_load"))
+ return;
+ skel->bss->pid = getpid();
+
+ skel->links.fentry1 = bpf_program__attach(skel->progs.fentry1);
+ if (!ASSERT_OK_PTR(skel->links.fentry1, "attach_fentry1"))
+ goto out;
+ skel->links.kprobe1 = bpf_program__attach(skel->progs.kprobe1);
+ if (!ASSERT_OK_PTR(skel->links.kprobe1, "attach_kprobe1"))
+ goto out;
+ trigger(skel);
+ ASSERT_EQ(skel->bss->fentry1_hits, 1, "fentry1_hits");
+ ASSERT_EQ(skel->bss->kprobe_hits, 1, "kprobe_hits");
+
+ skel->links.fentry2 = bpf_program__attach(skel->progs.fentry2);
+ if (!ASSERT_OK_PTR(skel->links.fentry2, "attach_fentry2"))
+ goto out;
+ trigger(skel);
+ ASSERT_EQ(skel->bss->fentry1_hits, 2, "fentry1_hits");
+ ASSERT_EQ(skel->bss->fentry2_hits, 1, "fentry2_hits");
+ ASSERT_EQ(skel->bss->kprobe_hits, 2, "kprobe_hits");
+
+ bpf_link__destroy(skel->links.kprobe1);
+ skel->links.kprobe1 = NULL;
+ trigger(skel);
+ ASSERT_EQ(skel->bss->fentry1_hits, 3, "fentry1_hits");
+ ASSERT_EQ(skel->bss->fentry2_hits, 2, "fentry2_hits");
+ ASSERT_EQ(skel->bss->kprobe_hits, 2, "kprobe_hits");
+out:
+ fentry_kprobe_shared__destroy(skel);
+}
diff --git a/tools/testing/selftests/bpf/progs/fentry_kprobe_shared.c b/tools/testing/selftests/bpf/progs/fentry_kprobe_shared.c
new file mode 100644
index 000000000000..aae8d9d29d37
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/fentry_kprobe_shared.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+
+char _license[] SEC("license") = "GPL";
+
+int pid;
+int fentry1_hits;
+int fentry2_hits;
+int kprobe_hits;
+
+static bool from_test(int a)
+{
+ return (bpf_get_current_pid_tgid() >> 32) == pid && a == 1;
+}
+
+SEC("fentry/bpf_fentry_test1")
+int BPF_PROG(fentry1, int a)
+{
+ if (from_test(a))
+ fentry1_hits++;
+ return 0;
+}
+
+SEC("fentry/bpf_fentry_test1")
+int BPF_PROG(fentry2, int a)
+{
+ if (from_test(a))
+ fentry2_hits++;
+ return 0;
+}
+
+SEC("kprobe/bpf_fentry_test1")
+int BPF_KPROBE(kprobe1, int a)
+{
+ if (from_test(a))
+ kprobe_hits++;
+ return 0;
+}
--
2.43.0
next prev parent reply other threads:[~2026-10-24 7:37 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-24 7:37 [PATCH bpf 1/2] x86/ftrace: Use jmp mode only where functions are aligned Daniel Borkmann
2026-10-24 7:37 ` Daniel Borkmann [this message]
2026-10-24 19:10 ` Alexei Starovoitov
2026-10-25 13:18 ` Jiri Olsa
2026-10-25 15:27 ` Daniel Borkmann
2026-10-25 17:38 ` Alexei Starovoitov
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=20261024073712.1074591-2-daniel@iogearbox.net \
--to=daniel@iogearbox.net \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=dongml2@chinatelecom.cn \
--cc=jolsa@kernel.org \
--cc=rostedt@goodmis.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