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 | |
7 | char _license[] SEC("license" ) = "GPL" ; |
8 | |
9 | __u64 uprobe_multi_func_1_addr = 0; |
10 | __u64 uprobe_multi_func_2_addr = 0; |
11 | __u64 uprobe_multi_func_3_addr = 0; |
12 | |
13 | __u64 uprobe_multi_func_1_result = 0; |
14 | __u64 uprobe_multi_func_2_result = 0; |
15 | __u64 uprobe_multi_func_3_result = 0; |
16 | |
17 | __u64 uretprobe_multi_func_1_result = 0; |
18 | __u64 uretprobe_multi_func_2_result = 0; |
19 | __u64 uretprobe_multi_func_3_result = 0; |
20 | |
21 | __u64 uprobe_multi_sleep_result = 0; |
22 | |
23 | int pid = 0; |
24 | int child_pid = 0; |
25 | |
26 | bool test_cookie = false; |
27 | void *user_ptr = 0; |
28 | |
29 | static __always_inline bool verify_sleepable_user_copy(void) |
30 | { |
31 | char data[9]; |
32 | |
33 | bpf_copy_from_user(data, sizeof(data), user_ptr); |
34 | return bpf_strncmp(data, sizeof(data), "test_data" ) == 0; |
35 | } |
36 | |
37 | static void uprobe_multi_check(void *ctx, bool is_return, bool is_sleep) |
38 | { |
39 | child_pid = bpf_get_current_pid_tgid() >> 32; |
40 | |
41 | if (pid && child_pid != pid) |
42 | return; |
43 | |
44 | __u64 cookie = test_cookie ? bpf_get_attach_cookie(ctx) : 0; |
45 | __u64 addr = bpf_get_func_ip(ctx); |
46 | |
47 | #define SET(__var, __addr, __cookie) ({ \ |
48 | if (addr == __addr && \ |
49 | (!test_cookie || (cookie == __cookie))) \ |
50 | __var += 1; \ |
51 | }) |
52 | |
53 | if (is_return) { |
54 | SET(uretprobe_multi_func_1_result, uprobe_multi_func_1_addr, 2); |
55 | SET(uretprobe_multi_func_2_result, uprobe_multi_func_2_addr, 3); |
56 | SET(uretprobe_multi_func_3_result, uprobe_multi_func_3_addr, 1); |
57 | } else { |
58 | SET(uprobe_multi_func_1_result, uprobe_multi_func_1_addr, 3); |
59 | SET(uprobe_multi_func_2_result, uprobe_multi_func_2_addr, 1); |
60 | SET(uprobe_multi_func_3_result, uprobe_multi_func_3_addr, 2); |
61 | } |
62 | |
63 | #undef SET |
64 | |
65 | if (is_sleep && verify_sleepable_user_copy()) |
66 | uprobe_multi_sleep_result += 1; |
67 | } |
68 | |
69 | SEC("uprobe.multi//proc/self/exe:uprobe_multi_func_*" ) |
70 | int uprobe(struct pt_regs *ctx) |
71 | { |
72 | uprobe_multi_check(ctx, is_return: false, is_sleep: false); |
73 | return 0; |
74 | } |
75 | |
76 | SEC("uretprobe.multi//proc/self/exe:uprobe_multi_func_*" ) |
77 | int uretprobe(struct pt_regs *ctx) |
78 | { |
79 | uprobe_multi_check(ctx, is_return: true, is_sleep: false); |
80 | return 0; |
81 | } |
82 | |
83 | SEC("uprobe.multi.s//proc/self/exe:uprobe_multi_func_*" ) |
84 | int uprobe_sleep(struct pt_regs *ctx) |
85 | { |
86 | uprobe_multi_check(ctx, is_return: false, is_sleep: true); |
87 | return 0; |
88 | } |
89 | |
90 | SEC("uretprobe.multi.s//proc/self/exe:uprobe_multi_func_*" ) |
91 | int uretprobe_sleep(struct pt_regs *ctx) |
92 | { |
93 | uprobe_multi_check(ctx, is_return: true, is_sleep: true); |
94 | return 0; |
95 | } |
96 | |
97 | SEC("uprobe.multi//proc/self/exe:uprobe_multi_func_*" ) |
98 | int (struct pt_regs *ctx) |
99 | { |
100 | return 0; |
101 | } |
102 | |