Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: Add uprobe session test

Adding uprobe session test and testing that the entry program
return value controls execution of the return probe program.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20241108134544.480660-7-jolsa@kernel.org

authored by

Jiri Olsa and committed by
Andrii Nakryiko
4856ecb1 022367ec

+118
+47
tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c
··· 8 8 #include "uprobe_multi_usdt.skel.h" 9 9 #include "uprobe_multi_consumers.skel.h" 10 10 #include "uprobe_multi_pid_filter.skel.h" 11 + #include "uprobe_multi_session.skel.h" 11 12 #include "bpf/libbpf_internal.h" 12 13 #include "testing_helpers.h" 13 14 #include "../sdt.h" ··· 1018 1017 uprobe_multi_pid_filter__destroy(skel); 1019 1018 } 1020 1019 1020 + static void test_session_skel_api(void) 1021 + { 1022 + struct uprobe_multi_session *skel = NULL; 1023 + LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); 1024 + struct bpf_link *link = NULL; 1025 + int err; 1026 + 1027 + skel = uprobe_multi_session__open_and_load(); 1028 + if (!ASSERT_OK_PTR(skel, "uprobe_multi_session__open_and_load")) 1029 + goto cleanup; 1030 + 1031 + skel->bss->pid = getpid(); 1032 + skel->bss->user_ptr = test_data; 1033 + 1034 + err = uprobe_multi_session__attach(skel); 1035 + if (!ASSERT_OK(err, "uprobe_multi_session__attach")) 1036 + goto cleanup; 1037 + 1038 + /* trigger all probes */ 1039 + skel->bss->uprobe_multi_func_1_addr = (__u64) uprobe_multi_func_1; 1040 + skel->bss->uprobe_multi_func_2_addr = (__u64) uprobe_multi_func_2; 1041 + skel->bss->uprobe_multi_func_3_addr = (__u64) uprobe_multi_func_3; 1042 + 1043 + uprobe_multi_func_1(); 1044 + uprobe_multi_func_2(); 1045 + uprobe_multi_func_3(); 1046 + 1047 + /* 1048 + * We expect 2 for uprobe_multi_func_2 because it runs both entry/return probe, 1049 + * uprobe_multi_func_[13] run just the entry probe. All expected numbers are 1050 + * doubled, because we run extra test for sleepable session. 1051 + */ 1052 + ASSERT_EQ(skel->bss->uprobe_session_result[0], 2, "uprobe_multi_func_1_result"); 1053 + ASSERT_EQ(skel->bss->uprobe_session_result[1], 4, "uprobe_multi_func_2_result"); 1054 + ASSERT_EQ(skel->bss->uprobe_session_result[2], 2, "uprobe_multi_func_3_result"); 1055 + 1056 + /* We expect increase in 3 entry and 1 return session calls -> 4 */ 1057 + ASSERT_EQ(skel->bss->uprobe_multi_sleep_result, 4, "uprobe_multi_sleep_result"); 1058 + 1059 + cleanup: 1060 + bpf_link__destroy(link); 1061 + uprobe_multi_session__destroy(skel); 1062 + } 1063 + 1021 1064 static void test_bench_attach_uprobe(void) 1022 1065 { 1023 1066 long attach_start_ns = 0, attach_end_ns = 0; ··· 1158 1113 test_pid_filter_process(false); 1159 1114 if (test__start_subtest("filter_clone_vm")) 1160 1115 test_pid_filter_process(true); 1116 + if (test__start_subtest("session")) 1117 + test_session_skel_api(); 1161 1118 }
+71
tools/testing/selftests/bpf/progs/uprobe_multi_session.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <linux/bpf.h> 3 + #include <bpf/bpf_helpers.h> 4 + #include <bpf/bpf_tracing.h> 5 + #include <stdbool.h> 6 + #include "bpf_kfuncs.h" 7 + #include "bpf_misc.h" 8 + 9 + char _license[] SEC("license") = "GPL"; 10 + 11 + __u64 uprobe_multi_func_1_addr = 0; 12 + __u64 uprobe_multi_func_2_addr = 0; 13 + __u64 uprobe_multi_func_3_addr = 0; 14 + 15 + __u64 uprobe_session_result[3] = {}; 16 + __u64 uprobe_multi_sleep_result = 0; 17 + 18 + void *user_ptr = 0; 19 + int pid = 0; 20 + 21 + static int uprobe_multi_check(void *ctx, bool is_return) 22 + { 23 + const __u64 funcs[] = { 24 + uprobe_multi_func_1_addr, 25 + uprobe_multi_func_2_addr, 26 + uprobe_multi_func_3_addr, 27 + }; 28 + unsigned int i; 29 + __u64 addr; 30 + 31 + if (bpf_get_current_pid_tgid() >> 32 != pid) 32 + return 1; 33 + 34 + addr = bpf_get_func_ip(ctx); 35 + 36 + for (i = 0; i < ARRAY_SIZE(funcs); i++) { 37 + if (funcs[i] == addr) { 38 + uprobe_session_result[i]++; 39 + break; 40 + } 41 + } 42 + 43 + /* only uprobe_multi_func_2 executes return probe */ 44 + if ((addr == uprobe_multi_func_1_addr) || 45 + (addr == uprobe_multi_func_3_addr)) 46 + return 1; 47 + 48 + return 0; 49 + } 50 + 51 + SEC("uprobe.session//proc/self/exe:uprobe_multi_func_*") 52 + int uprobe(struct pt_regs *ctx) 53 + { 54 + return uprobe_multi_check(ctx, bpf_session_is_return()); 55 + } 56 + 57 + static __always_inline bool verify_sleepable_user_copy(void) 58 + { 59 + char data[9]; 60 + 61 + bpf_copy_from_user(data, sizeof(data), user_ptr); 62 + return bpf_strncmp(data, sizeof(data), "test_data") == 0; 63 + } 64 + 65 + SEC("uprobe.session.s//proc/self/exe:uprobe_multi_func_*") 66 + int uprobe_sleepable(struct pt_regs *ctx) 67 + { 68 + if (verify_sleepable_user_copy()) 69 + uprobe_multi_sleep_result++; 70 + return uprobe_multi_check(ctx, bpf_session_is_return()); 71 + }