Add two new subtests to kprobe_multi_test to validate the
kprobe.session exact function name optimization:

test_session_syms: Attaches a kprobe.session program to an exact
function name (bpf_fentry_test1) to verify the fast syms[] path
works correctly.  Validates that both entry and return probes fire.

test_session_errors: Verifies error code consistency between the
wildcard pattern path (slow, parses kallsyms) and the exact function
name path (fast, uses syms[] array).  Both paths must return -ENOENT
for non-existent functions, protecting against future changes that
could break API consistency.

Signed-off-by: Andrey Grodzovsky <[email protected]>
---
 .../bpf/prog_tests/kprobe_multi_test.c        | 76 +++++++++++++++++++
 .../bpf/progs/kprobe_multi_session_errors.c   | 27 +++++++
 .../bpf/progs/kprobe_multi_session_syms.c     | 45 +++++++++++
 3 files changed, 148 insertions(+)
 create mode 100644 
tools/testing/selftests/bpf/progs/kprobe_multi_session_errors.c
 create mode 100644 
tools/testing/selftests/bpf/progs/kprobe_multi_session_syms.c

diff --git a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c 
b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
index 9caef222e528..62f7959858a9 100644
--- a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
+++ b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
@@ -8,6 +8,8 @@
 #include "kprobe_multi_override.skel.h"
 #include "kprobe_multi_session.skel.h"
 #include "kprobe_multi_session_cookie.skel.h"
+#include "kprobe_multi_session_syms.skel.h"
+#include "kprobe_multi_session_errors.skel.h"
 #include "kprobe_multi_verifier.skel.h"
 #include "kprobe_write_ctx.skel.h"
 #include "bpf/libbpf_internal.h"
@@ -400,6 +402,76 @@ static void test_session_cookie_skel_api(void)
        kprobe_multi_session_cookie__destroy(skel);
 }
 
+static void test_session_syms_skel_api(void)
+{
+       struct kprobe_multi_session_syms *skel = NULL;
+
+       LIBBPF_OPTS(bpf_test_run_opts, topts);
+       int err, prog_fd;
+
+       skel = kprobe_multi_session_syms__open_and_load();
+       if (!ASSERT_OK_PTR(skel, "kprobe_multi_session_syms__open_and_load"))
+               return;
+
+       skel->bss->pid = getpid();
+
+       err = kprobe_multi_session_syms__attach(skel);
+       if (!ASSERT_OK(err, "kprobe_multi_session_syms__attach"))
+               goto cleanup;
+
+       prog_fd = bpf_program__fd(skel->progs.trigger);
+       err = bpf_prog_test_run_opts(prog_fd, &topts);
+       ASSERT_OK(err, "test_run");
+       ASSERT_EQ(topts.retval, 0, "test_run");
+
+       /* Test 1: Both entry and return should fire */
+       ASSERT_EQ(skel->bss->test1_count, 2, "test1_count");
+       ASSERT_TRUE(skel->bss->test1_return, "test1_return");
+
+cleanup:
+       kprobe_multi_session_syms__destroy(skel);
+}
+
+static void test_session_errors(void)
+{
+       struct kprobe_multi_session_errors *skel = NULL;
+       struct bpf_link *link_wildcard = NULL;
+       struct bpf_link *link_exact = NULL;
+       int err_wildcard, err_exact;
+
+       skel = kprobe_multi_session_errors__open_and_load();
+       if (!ASSERT_OK_PTR(skel, "kprobe_multi_session_errors__open_and_load"))
+               return;
+
+       /*
+        * Test error code consistency: both wildcard (slow path) and exact name
+        * (fast path) should return the same error code (ENOENT) for 
non-existent
+        * functions. This protects against future kernel changes that might 
alter
+        * error return values.
+        */
+
+       /* Try to attach with non-existent wildcard pattern (slow path) */
+       link_wildcard = 
bpf_program__attach(skel->progs.test_nonexistent_wildcard);
+       err_wildcard = -errno;
+       ASSERT_ERR_PTR(link_wildcard, "attach_nonexistent_wildcard");
+       ASSERT_EQ(err_wildcard, -ENOENT, "wildcard_error_enoent");
+
+       /* Try to attach with non-existent exact name (fast path) */
+       link_exact = bpf_program__attach(skel->progs.test_nonexistent_exact);
+       err_exact = -errno;
+       ASSERT_ERR_PTR(link_exact, "attach_nonexistent_exact");
+       ASSERT_EQ(err_exact, -ENOENT, "exact_error_enoent");
+
+       /*
+        * Verify both paths return identical error codes - this is critical for
+        * API consistency and prevents user code from breaking when switching
+        * between wildcard patterns and exact function names.
+        */
+       ASSERT_EQ(err_wildcard, err_exact, "error_consistency");
+
+       kprobe_multi_session_errors__destroy(skel);
+}
+
 static void test_unique_match(void)
 {
        LIBBPF_OPTS(bpf_kprobe_multi_opts, opts);
@@ -645,6 +717,10 @@ void test_kprobe_multi_test(void)
                test_session_skel_api();
        if (test__start_subtest("session_cookie"))
                test_session_cookie_skel_api();
+       if (test__start_subtest("session_syms"))
+               test_session_syms_skel_api();
+       if (test__start_subtest("session_errors"))
+               test_session_errors();
        if (test__start_subtest("unique_match"))
                test_unique_match();
        if (test__start_subtest("attach_write_ctx"))
diff --git a/tools/testing/selftests/bpf/progs/kprobe_multi_session_errors.c 
b/tools/testing/selftests/bpf/progs/kprobe_multi_session_errors.c
new file mode 100644
index 000000000000..749d43b35bc2
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/kprobe_multi_session_errors.c
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Test error code consistency between fast and slow paths for non-existent 
functions */
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+
+char _license[] SEC("license") = "GPL";
+
+/*
+ * Test 1: Non-existent wildcard pattern (slow path)
+ * This uses pattern matching with kallsyms parsing and should fail with ENOENT
+ */
+SEC("kprobe.session/__impossible_test_func_xyz_wildcard_*")
+int test_nonexistent_wildcard(struct pt_regs *ctx)
+{
+       return 0;
+}
+
+/*
+ * Test 2: Non-existent exact function name (fast path)
+ * This uses syms[] array and should fail with ENOENT (normalized from ESRCH)
+ */
+SEC("kprobe.session/__impossible_test_func_xyz_exact_123")
+int test_nonexistent_exact(struct pt_regs *ctx)
+{
+       return 0;
+}
diff --git a/tools/testing/selftests/bpf/progs/kprobe_multi_session_syms.c 
b/tools/testing/selftests/bpf/progs/kprobe_multi_session_syms.c
new file mode 100644
index 000000000000..6a4bd57af1fc
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/kprobe_multi_session_syms.c
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Test kprobe.session with exact function names to verify syms[] optimization 
*/
+#include <vmlinux.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include <stdbool.h>
+
+char _license[] SEC("license") = "GPL";
+
+int pid = 0;
+
+/* Results for each function: incremented on entry and return */
+__u64 test1_count = 0;
+
+/* Track entry vs return */
+bool test1_return = false;
+
+/*
+ * No tests in here, just to trigger 'bpf_fentry_test*'
+ * through tracing test_run
+ */
+SEC("fentry/bpf_modify_return_test")
+int BPF_PROG(trigger)
+{
+       return 0;
+}
+
+/*
+ * Test 1: Exact function name (no wildcards) - uses fast syms[] path
+ * This should attach via opts.syms array, bypassing kallsyms parsing
+ */
+SEC("kprobe.session/bpf_fentry_test1")
+int test_kprobe_syms_1(struct pt_regs *ctx)
+{
+       if (bpf_get_current_pid_tgid() >> 32 != pid)
+               return 0;
+
+       test1_count++;
+
+       /* Check if this is return probe */
+       if (bpf_session_is_return(ctx))
+               test1_return = true;
+
+       return 0;  /* Always execute return probe */
+}
-- 
2.34.1


Reply via email to