1
2
3#define _GNU_SOURCE
4#include <pthread.h>
5#include <sched.h>
6#include <sys/syscall.h>
7#include <unistd.h>
8#include <test_progs.h>
9#include "test_bpf_cookie.skel.h"
10
11static void kprobe_subtest(struct test_bpf_cookie *skel)
12{
13 DECLARE_LIBBPF_OPTS(bpf_kprobe_opts, opts);
14 struct bpf_link *link1 = NULL, *link2 = NULL;
15 struct bpf_link *retlink1 = NULL, *retlink2 = NULL;
16
17
18 opts.bpf_cookie = 0x1;
19 opts.retprobe = false;
20 link1 = bpf_program__attach_kprobe_opts(skel->progs.handle_kprobe,
21 SYS_NANOSLEEP_KPROBE_NAME, &opts);
22 if (!ASSERT_OK_PTR(link1, "link1"))
23 goto cleanup;
24
25 opts.bpf_cookie = 0x2;
26 opts.retprobe = false;
27 link2 = bpf_program__attach_kprobe_opts(skel->progs.handle_kprobe,
28 SYS_NANOSLEEP_KPROBE_NAME, &opts);
29 if (!ASSERT_OK_PTR(link2, "link2"))
30 goto cleanup;
31
32
33 opts.bpf_cookie = 0x10;
34 opts.retprobe = true;
35 retlink1 = bpf_program__attach_kprobe_opts(skel->progs.handle_kretprobe,
36 SYS_NANOSLEEP_KPROBE_NAME, &opts);
37 if (!ASSERT_OK_PTR(retlink1, "retlink1"))
38 goto cleanup;
39
40 opts.bpf_cookie = 0x20;
41 opts.retprobe = true;
42 retlink2 = bpf_program__attach_kprobe_opts(skel->progs.handle_kretprobe,
43 SYS_NANOSLEEP_KPROBE_NAME, &opts);
44 if (!ASSERT_OK_PTR(retlink2, "retlink2"))
45 goto cleanup;
46
47
48 usleep(1);
49
50 ASSERT_EQ(skel->bss->kprobe_res, 0x1 | 0x2, "kprobe_res");
51 ASSERT_EQ(skel->bss->kretprobe_res, 0x10 | 0x20, "kretprobe_res");
52
53cleanup:
54 bpf_link__destroy(link1);
55 bpf_link__destroy(link2);
56 bpf_link__destroy(retlink1);
57 bpf_link__destroy(retlink2);
58}
59
60static void uprobe_subtest(struct test_bpf_cookie *skel)
61{
62 DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, opts);
63 struct bpf_link *link1 = NULL, *link2 = NULL;
64 struct bpf_link *retlink1 = NULL, *retlink2 = NULL;
65 size_t uprobe_offset;
66 ssize_t base_addr;
67
68 base_addr = get_base_addr();
69 uprobe_offset = get_uprobe_offset(&get_base_addr, base_addr);
70
71
72 opts.bpf_cookie = 0x100;
73 opts.retprobe = false;
74 link1 = bpf_program__attach_uprobe_opts(skel->progs.handle_uprobe, 0 ,
75 "/proc/self/exe", uprobe_offset, &opts);
76 if (!ASSERT_OK_PTR(link1, "link1"))
77 goto cleanup;
78
79 opts.bpf_cookie = 0x200;
80 opts.retprobe = false;
81 link2 = bpf_program__attach_uprobe_opts(skel->progs.handle_uprobe, -1 ,
82 "/proc/self/exe", uprobe_offset, &opts);
83 if (!ASSERT_OK_PTR(link2, "link2"))
84 goto cleanup;
85
86
87 opts.bpf_cookie = 0x1000;
88 opts.retprobe = true;
89 retlink1 = bpf_program__attach_uprobe_opts(skel->progs.handle_uretprobe, -1 ,
90 "/proc/self/exe", uprobe_offset, &opts);
91 if (!ASSERT_OK_PTR(retlink1, "retlink1"))
92 goto cleanup;
93
94 opts.bpf_cookie = 0x2000;
95 opts.retprobe = true;
96 retlink2 = bpf_program__attach_uprobe_opts(skel->progs.handle_uretprobe, 0 ,
97 "/proc/self/exe", uprobe_offset, &opts);
98 if (!ASSERT_OK_PTR(retlink2, "retlink2"))
99 goto cleanup;
100
101
102 get_base_addr();
103
104 ASSERT_EQ(skel->bss->uprobe_res, 0x100 | 0x200, "uprobe_res");
105 ASSERT_EQ(skel->bss->uretprobe_res, 0x1000 | 0x2000, "uretprobe_res");
106
107cleanup:
108 bpf_link__destroy(link1);
109 bpf_link__destroy(link2);
110 bpf_link__destroy(retlink1);
111 bpf_link__destroy(retlink2);
112}
113
114static void tp_subtest(struct test_bpf_cookie *skel)
115{
116 DECLARE_LIBBPF_OPTS(bpf_tracepoint_opts, opts);
117 struct bpf_link *link1 = NULL, *link2 = NULL, *link3 = NULL;
118
119
120 opts.bpf_cookie = 0x10000;
121 link1 = bpf_program__attach_tracepoint_opts(skel->progs.handle_tp1,
122 "syscalls", "sys_enter_nanosleep", &opts);
123 if (!ASSERT_OK_PTR(link1, "link1"))
124 goto cleanup;
125
126
127 opts.bpf_cookie = 0x20000;
128 link2 = bpf_program__attach_tracepoint_opts(skel->progs.handle_tp2,
129 "syscalls", "sys_enter_nanosleep", &opts);
130 if (!ASSERT_OK_PTR(link2, "link2"))
131 goto cleanup;
132
133
134 usleep(1);
135
136 ASSERT_EQ(skel->bss->tp_res, 0x10000 | 0x20000, "tp_res1");
137
138
139
140
141
142
143 bpf_link__destroy(link1);
144 link1 = NULL;
145 kern_sync_rcu();
146 skel->bss->tp_res = 0;
147
148
149 opts.bpf_cookie = 0x40000;
150 link3 = bpf_program__attach_tracepoint_opts(skel->progs.handle_tp3,
151 "syscalls", "sys_enter_nanosleep", &opts);
152 if (!ASSERT_OK_PTR(link3, "link3"))
153 goto cleanup;
154
155
156 usleep(1);
157
158 ASSERT_EQ(skel->bss->tp_res, 0x20000 | 0x40000, "tp_res2");
159
160cleanup:
161 bpf_link__destroy(link1);
162 bpf_link__destroy(link2);
163 bpf_link__destroy(link3);
164}
165
166static void burn_cpu(void)
167{
168 volatile int j = 0;
169 cpu_set_t cpu_set;
170 int i, err;
171
172
173 CPU_ZERO(&cpu_set);
174 CPU_SET(0, &cpu_set);
175 err = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set), &cpu_set);
176 ASSERT_OK(err, "set_thread_affinity");
177
178
179 for (i = 0; i < 1000000; ++i)
180 ++j;
181}
182
183static void pe_subtest(struct test_bpf_cookie *skel)
184{
185 DECLARE_LIBBPF_OPTS(bpf_perf_event_opts, opts);
186 struct bpf_link *link = NULL;
187 struct perf_event_attr attr;
188 int pfd = -1;
189
190
191 memset(&attr, 0, sizeof(attr));
192 attr.size = sizeof(attr);
193 attr.type = PERF_TYPE_SOFTWARE;
194 attr.config = PERF_COUNT_SW_CPU_CLOCK;
195 attr.freq = 1;
196 attr.sample_freq = 4000;
197 pfd = syscall(__NR_perf_event_open, &attr, -1, 0, -1, PERF_FLAG_FD_CLOEXEC);
198 if (!ASSERT_GE(pfd, 0, "perf_fd"))
199 goto cleanup;
200
201 opts.bpf_cookie = 0x100000;
202 link = bpf_program__attach_perf_event_opts(skel->progs.handle_pe, pfd, &opts);
203 if (!ASSERT_OK_PTR(link, "link1"))
204 goto cleanup;
205
206 burn_cpu();
207
208 ASSERT_EQ(skel->bss->pe_res, 0x100000, "pe_res1");
209
210
211 bpf_link__disconnect(link);
212
213 close(bpf_link__fd(link));
214
215 bpf_link__destroy(link);
216 link = NULL;
217 kern_sync_rcu();
218 skel->bss->pe_res = 0;
219
220 opts.bpf_cookie = 0x200000;
221 link = bpf_program__attach_perf_event_opts(skel->progs.handle_pe, pfd, &opts);
222 if (!ASSERT_OK_PTR(link, "link2"))
223 goto cleanup;
224
225 burn_cpu();
226
227 ASSERT_EQ(skel->bss->pe_res, 0x200000, "pe_res2");
228
229cleanup:
230 close(pfd);
231 bpf_link__destroy(link);
232}
233
234void test_bpf_cookie(void)
235{
236 struct test_bpf_cookie *skel;
237
238 skel = test_bpf_cookie__open_and_load();
239 if (!ASSERT_OK_PTR(skel, "skel_open"))
240 return;
241
242 skel->bss->my_tid = syscall(SYS_gettid);
243
244 if (test__start_subtest("kprobe"))
245 kprobe_subtest(skel);
246 if (test__start_subtest("uprobe"))
247 uprobe_subtest(skel);
248 if (test__start_subtest("tracepoint"))
249 tp_subtest(skel);
250 if (test__start_subtest("perf_event"))
251 pe_subtest(skel);
252
253 test_bpf_cookie__destroy(skel);
254}
255