10a80cf67SAndrii Nakryiko // SPDX-License-Identifier: GPL-2.0
20a80cf67SAndrii Nakryiko /* Copyright (c) 2021 Facebook */
30a80cf67SAndrii Nakryiko #define _GNU_SOURCE
40a80cf67SAndrii Nakryiko #include <pthread.h>
50a80cf67SAndrii Nakryiko #include <sched.h>
60a80cf67SAndrii Nakryiko #include <sys/syscall.h>
7ddc0027aSKui-Feng Lee #include <sys/mman.h>
80a80cf67SAndrii Nakryiko #include <unistd.h>
90a80cf67SAndrii Nakryiko #include <test_progs.h>
10ddc0027aSKui-Feng Lee #include <network_helpers.h>
11ddc0027aSKui-Feng Lee #include <bpf/btf.h>
120a80cf67SAndrii Nakryiko #include "test_bpf_cookie.skel.h"
132c6401c9SJiri Olsa #include "kprobe_multi.skel.h"
14*e7cf9a48SJiri Olsa #include "uprobe_multi.skel.h"
150a80cf67SAndrii Nakryiko
16ff943683SAndrii Nakryiko /* uprobe attach point */
trigger_func(void)17df78da27SAndrii Nakryiko static noinline void trigger_func(void)
18ff943683SAndrii Nakryiko {
19ff943683SAndrii Nakryiko asm volatile ("");
20ff943683SAndrii Nakryiko }
21ff943683SAndrii Nakryiko
kprobe_subtest(struct test_bpf_cookie * skel)220a80cf67SAndrii Nakryiko static void kprobe_subtest(struct test_bpf_cookie *skel)
230a80cf67SAndrii Nakryiko {
240a80cf67SAndrii Nakryiko DECLARE_LIBBPF_OPTS(bpf_kprobe_opts, opts);
250a80cf67SAndrii Nakryiko struct bpf_link *link1 = NULL, *link2 = NULL;
260a80cf67SAndrii Nakryiko struct bpf_link *retlink1 = NULL, *retlink2 = NULL;
270a80cf67SAndrii Nakryiko
280a80cf67SAndrii Nakryiko /* attach two kprobes */
290a80cf67SAndrii Nakryiko opts.bpf_cookie = 0x1;
300a80cf67SAndrii Nakryiko opts.retprobe = false;
310a80cf67SAndrii Nakryiko link1 = bpf_program__attach_kprobe_opts(skel->progs.handle_kprobe,
320a80cf67SAndrii Nakryiko SYS_NANOSLEEP_KPROBE_NAME, &opts);
330a80cf67SAndrii Nakryiko if (!ASSERT_OK_PTR(link1, "link1"))
340a80cf67SAndrii Nakryiko goto cleanup;
350a80cf67SAndrii Nakryiko
360a80cf67SAndrii Nakryiko opts.bpf_cookie = 0x2;
370a80cf67SAndrii Nakryiko opts.retprobe = false;
380a80cf67SAndrii Nakryiko link2 = bpf_program__attach_kprobe_opts(skel->progs.handle_kprobe,
390a80cf67SAndrii Nakryiko SYS_NANOSLEEP_KPROBE_NAME, &opts);
400a80cf67SAndrii Nakryiko if (!ASSERT_OK_PTR(link2, "link2"))
410a80cf67SAndrii Nakryiko goto cleanup;
420a80cf67SAndrii Nakryiko
430a80cf67SAndrii Nakryiko /* attach two kretprobes */
440a80cf67SAndrii Nakryiko opts.bpf_cookie = 0x10;
450a80cf67SAndrii Nakryiko opts.retprobe = true;
460a80cf67SAndrii Nakryiko retlink1 = bpf_program__attach_kprobe_opts(skel->progs.handle_kretprobe,
470a80cf67SAndrii Nakryiko SYS_NANOSLEEP_KPROBE_NAME, &opts);
480a80cf67SAndrii Nakryiko if (!ASSERT_OK_PTR(retlink1, "retlink1"))
490a80cf67SAndrii Nakryiko goto cleanup;
500a80cf67SAndrii Nakryiko
510a80cf67SAndrii Nakryiko opts.bpf_cookie = 0x20;
520a80cf67SAndrii Nakryiko opts.retprobe = true;
530a80cf67SAndrii Nakryiko retlink2 = bpf_program__attach_kprobe_opts(skel->progs.handle_kretprobe,
540a80cf67SAndrii Nakryiko SYS_NANOSLEEP_KPROBE_NAME, &opts);
550a80cf67SAndrii Nakryiko if (!ASSERT_OK_PTR(retlink2, "retlink2"))
560a80cf67SAndrii Nakryiko goto cleanup;
570a80cf67SAndrii Nakryiko
580a80cf67SAndrii Nakryiko /* trigger kprobe && kretprobe */
590a80cf67SAndrii Nakryiko usleep(1);
600a80cf67SAndrii Nakryiko
610a80cf67SAndrii Nakryiko ASSERT_EQ(skel->bss->kprobe_res, 0x1 | 0x2, "kprobe_res");
620a80cf67SAndrii Nakryiko ASSERT_EQ(skel->bss->kretprobe_res, 0x10 | 0x20, "kretprobe_res");
630a80cf67SAndrii Nakryiko
640a80cf67SAndrii Nakryiko cleanup:
650a80cf67SAndrii Nakryiko bpf_link__destroy(link1);
660a80cf67SAndrii Nakryiko bpf_link__destroy(link2);
670a80cf67SAndrii Nakryiko bpf_link__destroy(retlink1);
680a80cf67SAndrii Nakryiko bpf_link__destroy(retlink2);
690a80cf67SAndrii Nakryiko }
700a80cf67SAndrii Nakryiko
kprobe_multi_test_run(struct kprobe_multi * skel)712c6401c9SJiri Olsa static void kprobe_multi_test_run(struct kprobe_multi *skel)
722c6401c9SJiri Olsa {
732c6401c9SJiri Olsa LIBBPF_OPTS(bpf_test_run_opts, topts);
742c6401c9SJiri Olsa int err, prog_fd;
752c6401c9SJiri Olsa
762c6401c9SJiri Olsa prog_fd = bpf_program__fd(skel->progs.trigger);
772c6401c9SJiri Olsa err = bpf_prog_test_run_opts(prog_fd, &topts);
782c6401c9SJiri Olsa ASSERT_OK(err, "test_run");
792c6401c9SJiri Olsa ASSERT_EQ(topts.retval, 0, "test_run");
802c6401c9SJiri Olsa
812c6401c9SJiri Olsa ASSERT_EQ(skel->bss->kprobe_test1_result, 1, "kprobe_test1_result");
822c6401c9SJiri Olsa ASSERT_EQ(skel->bss->kprobe_test2_result, 1, "kprobe_test2_result");
832c6401c9SJiri Olsa ASSERT_EQ(skel->bss->kprobe_test3_result, 1, "kprobe_test3_result");
842c6401c9SJiri Olsa ASSERT_EQ(skel->bss->kprobe_test4_result, 1, "kprobe_test4_result");
852c6401c9SJiri Olsa ASSERT_EQ(skel->bss->kprobe_test5_result, 1, "kprobe_test5_result");
862c6401c9SJiri Olsa ASSERT_EQ(skel->bss->kprobe_test6_result, 1, "kprobe_test6_result");
872c6401c9SJiri Olsa ASSERT_EQ(skel->bss->kprobe_test7_result, 1, "kprobe_test7_result");
882c6401c9SJiri Olsa ASSERT_EQ(skel->bss->kprobe_test8_result, 1, "kprobe_test8_result");
892c6401c9SJiri Olsa
902c6401c9SJiri Olsa ASSERT_EQ(skel->bss->kretprobe_test1_result, 1, "kretprobe_test1_result");
912c6401c9SJiri Olsa ASSERT_EQ(skel->bss->kretprobe_test2_result, 1, "kretprobe_test2_result");
922c6401c9SJiri Olsa ASSERT_EQ(skel->bss->kretprobe_test3_result, 1, "kretprobe_test3_result");
932c6401c9SJiri Olsa ASSERT_EQ(skel->bss->kretprobe_test4_result, 1, "kretprobe_test4_result");
942c6401c9SJiri Olsa ASSERT_EQ(skel->bss->kretprobe_test5_result, 1, "kretprobe_test5_result");
952c6401c9SJiri Olsa ASSERT_EQ(skel->bss->kretprobe_test6_result, 1, "kretprobe_test6_result");
962c6401c9SJiri Olsa ASSERT_EQ(skel->bss->kretprobe_test7_result, 1, "kretprobe_test7_result");
972c6401c9SJiri Olsa ASSERT_EQ(skel->bss->kretprobe_test8_result, 1, "kretprobe_test8_result");
982c6401c9SJiri Olsa }
992c6401c9SJiri Olsa
kprobe_multi_link_api_subtest(void)1002c6401c9SJiri Olsa static void kprobe_multi_link_api_subtest(void)
1012c6401c9SJiri Olsa {
1022c6401c9SJiri Olsa int prog_fd, link1_fd = -1, link2_fd = -1;
1032c6401c9SJiri Olsa struct kprobe_multi *skel = NULL;
1042c6401c9SJiri Olsa LIBBPF_OPTS(bpf_link_create_opts, opts);
1052c6401c9SJiri Olsa unsigned long long addrs[8];
1062c6401c9SJiri Olsa __u64 cookies[8];
1072c6401c9SJiri Olsa
1082c6401c9SJiri Olsa if (!ASSERT_OK(load_kallsyms(), "load_kallsyms"))
1092c6401c9SJiri Olsa goto cleanup;
1102c6401c9SJiri Olsa
1112c6401c9SJiri Olsa skel = kprobe_multi__open_and_load();
1122c6401c9SJiri Olsa if (!ASSERT_OK_PTR(skel, "fentry_raw_skel_load"))
1132c6401c9SJiri Olsa goto cleanup;
1142c6401c9SJiri Olsa
1152c6401c9SJiri Olsa skel->bss->pid = getpid();
1162c6401c9SJiri Olsa skel->bss->test_cookie = true;
1172c6401c9SJiri Olsa
1182c6401c9SJiri Olsa #define GET_ADDR(__sym, __addr) ({ \
1192c6401c9SJiri Olsa __addr = ksym_get_addr(__sym); \
1202c6401c9SJiri Olsa if (!ASSERT_NEQ(__addr, 0, "ksym_get_addr " #__sym)) \
1212c6401c9SJiri Olsa goto cleanup; \
1222c6401c9SJiri Olsa })
1232c6401c9SJiri Olsa
1242c6401c9SJiri Olsa GET_ADDR("bpf_fentry_test1", addrs[0]);
125ad884853SJiri Olsa GET_ADDR("bpf_fentry_test3", addrs[1]);
126ad884853SJiri Olsa GET_ADDR("bpf_fentry_test4", addrs[2]);
127ad884853SJiri Olsa GET_ADDR("bpf_fentry_test5", addrs[3]);
128ad884853SJiri Olsa GET_ADDR("bpf_fentry_test6", addrs[4]);
129ad884853SJiri Olsa GET_ADDR("bpf_fentry_test7", addrs[5]);
130ad884853SJiri Olsa GET_ADDR("bpf_fentry_test2", addrs[6]);
1312c6401c9SJiri Olsa GET_ADDR("bpf_fentry_test8", addrs[7]);
1322c6401c9SJiri Olsa
1332c6401c9SJiri Olsa #undef GET_ADDR
1342c6401c9SJiri Olsa
135ad884853SJiri Olsa cookies[0] = 1; /* bpf_fentry_test1 */
136ad884853SJiri Olsa cookies[1] = 2; /* bpf_fentry_test3 */
137ad884853SJiri Olsa cookies[2] = 3; /* bpf_fentry_test4 */
138ad884853SJiri Olsa cookies[3] = 4; /* bpf_fentry_test5 */
139ad884853SJiri Olsa cookies[4] = 5; /* bpf_fentry_test6 */
140ad884853SJiri Olsa cookies[5] = 6; /* bpf_fentry_test7 */
141ad884853SJiri Olsa cookies[6] = 7; /* bpf_fentry_test2 */
142ad884853SJiri Olsa cookies[7] = 8; /* bpf_fentry_test8 */
1432c6401c9SJiri Olsa
1442c6401c9SJiri Olsa opts.kprobe_multi.addrs = (const unsigned long *) &addrs;
1452c6401c9SJiri Olsa opts.kprobe_multi.cnt = ARRAY_SIZE(addrs);
1462c6401c9SJiri Olsa opts.kprobe_multi.cookies = (const __u64 *) &cookies;
1472c6401c9SJiri Olsa prog_fd = bpf_program__fd(skel->progs.test_kprobe);
1482c6401c9SJiri Olsa
1492c6401c9SJiri Olsa link1_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_KPROBE_MULTI, &opts);
1502c6401c9SJiri Olsa if (!ASSERT_GE(link1_fd, 0, "link1_fd"))
1512c6401c9SJiri Olsa goto cleanup;
1522c6401c9SJiri Olsa
153ad884853SJiri Olsa cookies[0] = 8; /* bpf_fentry_test1 */
154ad884853SJiri Olsa cookies[1] = 7; /* bpf_fentry_test3 */
155ad884853SJiri Olsa cookies[2] = 6; /* bpf_fentry_test4 */
156ad884853SJiri Olsa cookies[3] = 5; /* bpf_fentry_test5 */
157ad884853SJiri Olsa cookies[4] = 4; /* bpf_fentry_test6 */
158ad884853SJiri Olsa cookies[5] = 3; /* bpf_fentry_test7 */
159ad884853SJiri Olsa cookies[6] = 2; /* bpf_fentry_test2 */
160ad884853SJiri Olsa cookies[7] = 1; /* bpf_fentry_test8 */
1612c6401c9SJiri Olsa
1622c6401c9SJiri Olsa opts.kprobe_multi.flags = BPF_F_KPROBE_MULTI_RETURN;
1632c6401c9SJiri Olsa prog_fd = bpf_program__fd(skel->progs.test_kretprobe);
1642c6401c9SJiri Olsa
1652c6401c9SJiri Olsa link2_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_KPROBE_MULTI, &opts);
1662c6401c9SJiri Olsa if (!ASSERT_GE(link2_fd, 0, "link2_fd"))
1672c6401c9SJiri Olsa goto cleanup;
1682c6401c9SJiri Olsa
1692c6401c9SJiri Olsa kprobe_multi_test_run(skel);
1702c6401c9SJiri Olsa
1712c6401c9SJiri Olsa cleanup:
1722c6401c9SJiri Olsa close(link1_fd);
1732c6401c9SJiri Olsa close(link2_fd);
1742c6401c9SJiri Olsa kprobe_multi__destroy(skel);
1752c6401c9SJiri Olsa }
1762c6401c9SJiri Olsa
kprobe_multi_attach_api_subtest(void)177318c812cSJiri Olsa static void kprobe_multi_attach_api_subtest(void)
178318c812cSJiri Olsa {
179318c812cSJiri Olsa struct bpf_link *link1 = NULL, *link2 = NULL;
180318c812cSJiri Olsa LIBBPF_OPTS(bpf_kprobe_multi_opts, opts);
181318c812cSJiri Olsa LIBBPF_OPTS(bpf_test_run_opts, topts);
182318c812cSJiri Olsa struct kprobe_multi *skel = NULL;
183318c812cSJiri Olsa const char *syms[8] = {
184318c812cSJiri Olsa "bpf_fentry_test1",
185318c812cSJiri Olsa "bpf_fentry_test3",
186318c812cSJiri Olsa "bpf_fentry_test4",
187318c812cSJiri Olsa "bpf_fentry_test5",
188318c812cSJiri Olsa "bpf_fentry_test6",
189318c812cSJiri Olsa "bpf_fentry_test7",
190ad884853SJiri Olsa "bpf_fentry_test2",
191318c812cSJiri Olsa "bpf_fentry_test8",
192318c812cSJiri Olsa };
193318c812cSJiri Olsa __u64 cookies[8];
194318c812cSJiri Olsa
195318c812cSJiri Olsa skel = kprobe_multi__open_and_load();
196318c812cSJiri Olsa if (!ASSERT_OK_PTR(skel, "fentry_raw_skel_load"))
197318c812cSJiri Olsa goto cleanup;
198318c812cSJiri Olsa
199318c812cSJiri Olsa skel->bss->pid = getpid();
200318c812cSJiri Olsa skel->bss->test_cookie = true;
201318c812cSJiri Olsa
202ad884853SJiri Olsa cookies[0] = 1; /* bpf_fentry_test1 */
203ad884853SJiri Olsa cookies[1] = 2; /* bpf_fentry_test3 */
204ad884853SJiri Olsa cookies[2] = 3; /* bpf_fentry_test4 */
205ad884853SJiri Olsa cookies[3] = 4; /* bpf_fentry_test5 */
206ad884853SJiri Olsa cookies[4] = 5; /* bpf_fentry_test6 */
207ad884853SJiri Olsa cookies[5] = 6; /* bpf_fentry_test7 */
208ad884853SJiri Olsa cookies[6] = 7; /* bpf_fentry_test2 */
209ad884853SJiri Olsa cookies[7] = 8; /* bpf_fentry_test8 */
210318c812cSJiri Olsa
211318c812cSJiri Olsa opts.syms = syms;
212318c812cSJiri Olsa opts.cnt = ARRAY_SIZE(syms);
213318c812cSJiri Olsa opts.cookies = cookies;
214318c812cSJiri Olsa
215318c812cSJiri Olsa link1 = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe,
216318c812cSJiri Olsa NULL, &opts);
217318c812cSJiri Olsa if (!ASSERT_OK_PTR(link1, "bpf_program__attach_kprobe_multi_opts"))
218318c812cSJiri Olsa goto cleanup;
219318c812cSJiri Olsa
220ad884853SJiri Olsa cookies[0] = 8; /* bpf_fentry_test1 */
221ad884853SJiri Olsa cookies[1] = 7; /* bpf_fentry_test3 */
222ad884853SJiri Olsa cookies[2] = 6; /* bpf_fentry_test4 */
223ad884853SJiri Olsa cookies[3] = 5; /* bpf_fentry_test5 */
224ad884853SJiri Olsa cookies[4] = 4; /* bpf_fentry_test6 */
225ad884853SJiri Olsa cookies[5] = 3; /* bpf_fentry_test7 */
226ad884853SJiri Olsa cookies[6] = 2; /* bpf_fentry_test2 */
227ad884853SJiri Olsa cookies[7] = 1; /* bpf_fentry_test8 */
228318c812cSJiri Olsa
229318c812cSJiri Olsa opts.retprobe = true;
230318c812cSJiri Olsa
231318c812cSJiri Olsa link2 = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kretprobe,
232318c812cSJiri Olsa NULL, &opts);
233318c812cSJiri Olsa if (!ASSERT_OK_PTR(link2, "bpf_program__attach_kprobe_multi_opts"))
234318c812cSJiri Olsa goto cleanup;
235318c812cSJiri Olsa
236318c812cSJiri Olsa kprobe_multi_test_run(skel);
237318c812cSJiri Olsa
238318c812cSJiri Olsa cleanup:
239318c812cSJiri Olsa bpf_link__destroy(link2);
240318c812cSJiri Olsa bpf_link__destroy(link1);
241318c812cSJiri Olsa kprobe_multi__destroy(skel);
242318c812cSJiri Olsa }
243*e7cf9a48SJiri Olsa
244*e7cf9a48SJiri Olsa /* defined in prog_tests/uprobe_multi_test.c */
245*e7cf9a48SJiri Olsa void uprobe_multi_func_1(void);
246*e7cf9a48SJiri Olsa void uprobe_multi_func_2(void);
247*e7cf9a48SJiri Olsa void uprobe_multi_func_3(void);
248*e7cf9a48SJiri Olsa
uprobe_multi_test_run(struct uprobe_multi * skel)249*e7cf9a48SJiri Olsa static void uprobe_multi_test_run(struct uprobe_multi *skel)
250*e7cf9a48SJiri Olsa {
251*e7cf9a48SJiri Olsa skel->bss->uprobe_multi_func_1_addr = (__u64) uprobe_multi_func_1;
252*e7cf9a48SJiri Olsa skel->bss->uprobe_multi_func_2_addr = (__u64) uprobe_multi_func_2;
253*e7cf9a48SJiri Olsa skel->bss->uprobe_multi_func_3_addr = (__u64) uprobe_multi_func_3;
254*e7cf9a48SJiri Olsa
255*e7cf9a48SJiri Olsa skel->bss->pid = getpid();
256*e7cf9a48SJiri Olsa skel->bss->test_cookie = true;
257*e7cf9a48SJiri Olsa
258*e7cf9a48SJiri Olsa uprobe_multi_func_1();
259*e7cf9a48SJiri Olsa uprobe_multi_func_2();
260*e7cf9a48SJiri Olsa uprobe_multi_func_3();
261*e7cf9a48SJiri Olsa
262*e7cf9a48SJiri Olsa ASSERT_EQ(skel->bss->uprobe_multi_func_1_result, 1, "uprobe_multi_func_1_result");
263*e7cf9a48SJiri Olsa ASSERT_EQ(skel->bss->uprobe_multi_func_2_result, 1, "uprobe_multi_func_2_result");
264*e7cf9a48SJiri Olsa ASSERT_EQ(skel->bss->uprobe_multi_func_3_result, 1, "uprobe_multi_func_3_result");
265*e7cf9a48SJiri Olsa
266*e7cf9a48SJiri Olsa ASSERT_EQ(skel->bss->uretprobe_multi_func_1_result, 1, "uretprobe_multi_func_1_result");
267*e7cf9a48SJiri Olsa ASSERT_EQ(skel->bss->uretprobe_multi_func_2_result, 1, "uretprobe_multi_func_2_result");
268*e7cf9a48SJiri Olsa ASSERT_EQ(skel->bss->uretprobe_multi_func_3_result, 1, "uretprobe_multi_func_3_result");
269*e7cf9a48SJiri Olsa }
270*e7cf9a48SJiri Olsa
uprobe_multi_attach_api_subtest(void)271*e7cf9a48SJiri Olsa static void uprobe_multi_attach_api_subtest(void)
272*e7cf9a48SJiri Olsa {
273*e7cf9a48SJiri Olsa struct bpf_link *link1 = NULL, *link2 = NULL;
274*e7cf9a48SJiri Olsa struct uprobe_multi *skel = NULL;
275*e7cf9a48SJiri Olsa LIBBPF_OPTS(bpf_uprobe_multi_opts, opts);
276*e7cf9a48SJiri Olsa const char *syms[3] = {
277*e7cf9a48SJiri Olsa "uprobe_multi_func_1",
278*e7cf9a48SJiri Olsa "uprobe_multi_func_2",
279*e7cf9a48SJiri Olsa "uprobe_multi_func_3",
280*e7cf9a48SJiri Olsa };
281*e7cf9a48SJiri Olsa __u64 cookies[3];
282*e7cf9a48SJiri Olsa
283*e7cf9a48SJiri Olsa cookies[0] = 3; /* uprobe_multi_func_1 */
284*e7cf9a48SJiri Olsa cookies[1] = 1; /* uprobe_multi_func_2 */
285*e7cf9a48SJiri Olsa cookies[2] = 2; /* uprobe_multi_func_3 */
286*e7cf9a48SJiri Olsa
287*e7cf9a48SJiri Olsa opts.syms = syms;
288*e7cf9a48SJiri Olsa opts.cnt = ARRAY_SIZE(syms);
289*e7cf9a48SJiri Olsa opts.cookies = &cookies[0];
290*e7cf9a48SJiri Olsa
291*e7cf9a48SJiri Olsa skel = uprobe_multi__open_and_load();
292*e7cf9a48SJiri Olsa if (!ASSERT_OK_PTR(skel, "uprobe_multi"))
293*e7cf9a48SJiri Olsa goto cleanup;
294*e7cf9a48SJiri Olsa
295*e7cf9a48SJiri Olsa link1 = bpf_program__attach_uprobe_multi(skel->progs.uprobe, -1,
296*e7cf9a48SJiri Olsa "/proc/self/exe", NULL, &opts);
297*e7cf9a48SJiri Olsa if (!ASSERT_OK_PTR(link1, "bpf_program__attach_uprobe_multi"))
298*e7cf9a48SJiri Olsa goto cleanup;
299*e7cf9a48SJiri Olsa
300*e7cf9a48SJiri Olsa cookies[0] = 2; /* uprobe_multi_func_1 */
301*e7cf9a48SJiri Olsa cookies[1] = 3; /* uprobe_multi_func_2 */
302*e7cf9a48SJiri Olsa cookies[2] = 1; /* uprobe_multi_func_3 */
303*e7cf9a48SJiri Olsa
304*e7cf9a48SJiri Olsa opts.retprobe = true;
305*e7cf9a48SJiri Olsa link2 = bpf_program__attach_uprobe_multi(skel->progs.uretprobe, -1,
306*e7cf9a48SJiri Olsa "/proc/self/exe", NULL, &opts);
307*e7cf9a48SJiri Olsa if (!ASSERT_OK_PTR(link2, "bpf_program__attach_uprobe_multi_retprobe"))
308*e7cf9a48SJiri Olsa goto cleanup;
309*e7cf9a48SJiri Olsa
310*e7cf9a48SJiri Olsa uprobe_multi_test_run(skel);
311*e7cf9a48SJiri Olsa
312*e7cf9a48SJiri Olsa cleanup:
313*e7cf9a48SJiri Olsa bpf_link__destroy(link2);
314*e7cf9a48SJiri Olsa bpf_link__destroy(link1);
315*e7cf9a48SJiri Olsa uprobe_multi__destroy(skel);
316*e7cf9a48SJiri Olsa }
317*e7cf9a48SJiri Olsa
uprobe_subtest(struct test_bpf_cookie * skel)3180a80cf67SAndrii Nakryiko static void uprobe_subtest(struct test_bpf_cookie *skel)
3190a80cf67SAndrii Nakryiko {
3200a80cf67SAndrii Nakryiko DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, opts);
3210a80cf67SAndrii Nakryiko struct bpf_link *link1 = NULL, *link2 = NULL;
3220a80cf67SAndrii Nakryiko struct bpf_link *retlink1 = NULL, *retlink2 = NULL;
323ff943683SAndrii Nakryiko ssize_t uprobe_offset;
3240a80cf67SAndrii Nakryiko
325ff943683SAndrii Nakryiko uprobe_offset = get_uprobe_offset(&trigger_func);
326ff943683SAndrii Nakryiko if (!ASSERT_GE(uprobe_offset, 0, "uprobe_offset"))
327ff943683SAndrii Nakryiko goto cleanup;
3280a80cf67SAndrii Nakryiko
3290a80cf67SAndrii Nakryiko /* attach two uprobes */
3300a80cf67SAndrii Nakryiko opts.bpf_cookie = 0x100;
3310a80cf67SAndrii Nakryiko opts.retprobe = false;
3320a80cf67SAndrii Nakryiko link1 = bpf_program__attach_uprobe_opts(skel->progs.handle_uprobe, 0 /* self pid */,
3330a80cf67SAndrii Nakryiko "/proc/self/exe", uprobe_offset, &opts);
3340a80cf67SAndrii Nakryiko if (!ASSERT_OK_PTR(link1, "link1"))
3350a80cf67SAndrii Nakryiko goto cleanup;
3360a80cf67SAndrii Nakryiko
3370a80cf67SAndrii Nakryiko opts.bpf_cookie = 0x200;
3380a80cf67SAndrii Nakryiko opts.retprobe = false;
3390a80cf67SAndrii Nakryiko link2 = bpf_program__attach_uprobe_opts(skel->progs.handle_uprobe, -1 /* any pid */,
3400a80cf67SAndrii Nakryiko "/proc/self/exe", uprobe_offset, &opts);
3410a80cf67SAndrii Nakryiko if (!ASSERT_OK_PTR(link2, "link2"))
3420a80cf67SAndrii Nakryiko goto cleanup;
3430a80cf67SAndrii Nakryiko
3440a80cf67SAndrii Nakryiko /* attach two uretprobes */
3450a80cf67SAndrii Nakryiko opts.bpf_cookie = 0x1000;
3460a80cf67SAndrii Nakryiko opts.retprobe = true;
3470a80cf67SAndrii Nakryiko retlink1 = bpf_program__attach_uprobe_opts(skel->progs.handle_uretprobe, -1 /* any pid */,
3480a80cf67SAndrii Nakryiko "/proc/self/exe", uprobe_offset, &opts);
3490a80cf67SAndrii Nakryiko if (!ASSERT_OK_PTR(retlink1, "retlink1"))
3500a80cf67SAndrii Nakryiko goto cleanup;
3510a80cf67SAndrii Nakryiko
3520a80cf67SAndrii Nakryiko opts.bpf_cookie = 0x2000;
3530a80cf67SAndrii Nakryiko opts.retprobe = true;
3540a80cf67SAndrii Nakryiko retlink2 = bpf_program__attach_uprobe_opts(skel->progs.handle_uretprobe, 0 /* self pid */,
3550a80cf67SAndrii Nakryiko "/proc/self/exe", uprobe_offset, &opts);
3560a80cf67SAndrii Nakryiko if (!ASSERT_OK_PTR(retlink2, "retlink2"))
3570a80cf67SAndrii Nakryiko goto cleanup;
3580a80cf67SAndrii Nakryiko
3590a80cf67SAndrii Nakryiko /* trigger uprobe && uretprobe */
360ff943683SAndrii Nakryiko trigger_func();
3610a80cf67SAndrii Nakryiko
3620a80cf67SAndrii Nakryiko ASSERT_EQ(skel->bss->uprobe_res, 0x100 | 0x200, "uprobe_res");
3630a80cf67SAndrii Nakryiko ASSERT_EQ(skel->bss->uretprobe_res, 0x1000 | 0x2000, "uretprobe_res");
3640a80cf67SAndrii Nakryiko
3650a80cf67SAndrii Nakryiko cleanup:
3660a80cf67SAndrii Nakryiko bpf_link__destroy(link1);
3670a80cf67SAndrii Nakryiko bpf_link__destroy(link2);
3680a80cf67SAndrii Nakryiko bpf_link__destroy(retlink1);
3690a80cf67SAndrii Nakryiko bpf_link__destroy(retlink2);
3700a80cf67SAndrii Nakryiko }
3710a80cf67SAndrii Nakryiko
tp_subtest(struct test_bpf_cookie * skel)3720a80cf67SAndrii Nakryiko static void tp_subtest(struct test_bpf_cookie *skel)
3730a80cf67SAndrii Nakryiko {
3740a80cf67SAndrii Nakryiko DECLARE_LIBBPF_OPTS(bpf_tracepoint_opts, opts);
3750a80cf67SAndrii Nakryiko struct bpf_link *link1 = NULL, *link2 = NULL, *link3 = NULL;
3760a80cf67SAndrii Nakryiko
3770a80cf67SAndrii Nakryiko /* attach first tp prog */
3780a80cf67SAndrii Nakryiko opts.bpf_cookie = 0x10000;
3790a80cf67SAndrii Nakryiko link1 = bpf_program__attach_tracepoint_opts(skel->progs.handle_tp1,
3800a80cf67SAndrii Nakryiko "syscalls", "sys_enter_nanosleep", &opts);
3810a80cf67SAndrii Nakryiko if (!ASSERT_OK_PTR(link1, "link1"))
3820a80cf67SAndrii Nakryiko goto cleanup;
3830a80cf67SAndrii Nakryiko
3840a80cf67SAndrii Nakryiko /* attach second tp prog */
3850a80cf67SAndrii Nakryiko opts.bpf_cookie = 0x20000;
3860a80cf67SAndrii Nakryiko link2 = bpf_program__attach_tracepoint_opts(skel->progs.handle_tp2,
3870a80cf67SAndrii Nakryiko "syscalls", "sys_enter_nanosleep", &opts);
3880a80cf67SAndrii Nakryiko if (!ASSERT_OK_PTR(link2, "link2"))
3890a80cf67SAndrii Nakryiko goto cleanup;
3900a80cf67SAndrii Nakryiko
3910a80cf67SAndrii Nakryiko /* trigger tracepoints */
3920a80cf67SAndrii Nakryiko usleep(1);
3930a80cf67SAndrii Nakryiko
3940a80cf67SAndrii Nakryiko ASSERT_EQ(skel->bss->tp_res, 0x10000 | 0x20000, "tp_res1");
3950a80cf67SAndrii Nakryiko
3960a80cf67SAndrii Nakryiko /* now we detach first prog and will attach third one, which causes
3970a80cf67SAndrii Nakryiko * two internal calls to bpf_prog_array_copy(), shuffling
3980a80cf67SAndrii Nakryiko * bpf_prog_array_items around. We test here that we don't lose track
3990a80cf67SAndrii Nakryiko * of associated bpf_cookies.
4000a80cf67SAndrii Nakryiko */
4010a80cf67SAndrii Nakryiko bpf_link__destroy(link1);
4020a80cf67SAndrii Nakryiko link1 = NULL;
4030a80cf67SAndrii Nakryiko kern_sync_rcu();
4040a80cf67SAndrii Nakryiko skel->bss->tp_res = 0;
4050a80cf67SAndrii Nakryiko
4060a80cf67SAndrii Nakryiko /* attach third tp prog */
4070a80cf67SAndrii Nakryiko opts.bpf_cookie = 0x40000;
4080a80cf67SAndrii Nakryiko link3 = bpf_program__attach_tracepoint_opts(skel->progs.handle_tp3,
4090a80cf67SAndrii Nakryiko "syscalls", "sys_enter_nanosleep", &opts);
4100a80cf67SAndrii Nakryiko if (!ASSERT_OK_PTR(link3, "link3"))
4110a80cf67SAndrii Nakryiko goto cleanup;
4120a80cf67SAndrii Nakryiko
4130a80cf67SAndrii Nakryiko /* trigger tracepoints */
4140a80cf67SAndrii Nakryiko usleep(1);
4150a80cf67SAndrii Nakryiko
4160a80cf67SAndrii Nakryiko ASSERT_EQ(skel->bss->tp_res, 0x20000 | 0x40000, "tp_res2");
4170a80cf67SAndrii Nakryiko
4180a80cf67SAndrii Nakryiko cleanup:
4190a80cf67SAndrii Nakryiko bpf_link__destroy(link1);
4200a80cf67SAndrii Nakryiko bpf_link__destroy(link2);
4210a80cf67SAndrii Nakryiko bpf_link__destroy(link3);
4220a80cf67SAndrii Nakryiko }
4230a80cf67SAndrii Nakryiko
burn_cpu(void)4240a80cf67SAndrii Nakryiko static void burn_cpu(void)
4250a80cf67SAndrii Nakryiko {
4260a80cf67SAndrii Nakryiko volatile int j = 0;
4270a80cf67SAndrii Nakryiko cpu_set_t cpu_set;
4280a80cf67SAndrii Nakryiko int i, err;
4290a80cf67SAndrii Nakryiko
4300a80cf67SAndrii Nakryiko /* generate some branches on cpu 0 */
4310a80cf67SAndrii Nakryiko CPU_ZERO(&cpu_set);
4320a80cf67SAndrii Nakryiko CPU_SET(0, &cpu_set);
4330a80cf67SAndrii Nakryiko err = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set), &cpu_set);
4340a80cf67SAndrii Nakryiko ASSERT_OK(err, "set_thread_affinity");
4350a80cf67SAndrii Nakryiko
4360a80cf67SAndrii Nakryiko /* spin the loop for a while (random high number) */
4370a80cf67SAndrii Nakryiko for (i = 0; i < 1000000; ++i)
4380a80cf67SAndrii Nakryiko ++j;
4390a80cf67SAndrii Nakryiko }
4400a80cf67SAndrii Nakryiko
pe_subtest(struct test_bpf_cookie * skel)4410a80cf67SAndrii Nakryiko static void pe_subtest(struct test_bpf_cookie *skel)
4420a80cf67SAndrii Nakryiko {
4430a80cf67SAndrii Nakryiko DECLARE_LIBBPF_OPTS(bpf_perf_event_opts, opts);
4440a80cf67SAndrii Nakryiko struct bpf_link *link = NULL;
4450a80cf67SAndrii Nakryiko struct perf_event_attr attr;
4460a80cf67SAndrii Nakryiko int pfd = -1;
4470a80cf67SAndrii Nakryiko
4480a80cf67SAndrii Nakryiko /* create perf event */
4490a80cf67SAndrii Nakryiko memset(&attr, 0, sizeof(attr));
4500a80cf67SAndrii Nakryiko attr.size = sizeof(attr);
4510a80cf67SAndrii Nakryiko attr.type = PERF_TYPE_SOFTWARE;
4520a80cf67SAndrii Nakryiko attr.config = PERF_COUNT_SW_CPU_CLOCK;
4530a80cf67SAndrii Nakryiko attr.freq = 1;
454d4b54054SMykola Lysenko attr.sample_freq = 1000;
4550a80cf67SAndrii Nakryiko pfd = syscall(__NR_perf_event_open, &attr, -1, 0, -1, PERF_FLAG_FD_CLOEXEC);
4560a80cf67SAndrii Nakryiko if (!ASSERT_GE(pfd, 0, "perf_fd"))
4570a80cf67SAndrii Nakryiko goto cleanup;
4580a80cf67SAndrii Nakryiko
4590a80cf67SAndrii Nakryiko opts.bpf_cookie = 0x100000;
4600a80cf67SAndrii Nakryiko link = bpf_program__attach_perf_event_opts(skel->progs.handle_pe, pfd, &opts);
4610a80cf67SAndrii Nakryiko if (!ASSERT_OK_PTR(link, "link1"))
4620a80cf67SAndrii Nakryiko goto cleanup;
4630a80cf67SAndrii Nakryiko
4640a80cf67SAndrii Nakryiko burn_cpu(); /* trigger BPF prog */
4650a80cf67SAndrii Nakryiko
4660a80cf67SAndrii Nakryiko ASSERT_EQ(skel->bss->pe_res, 0x100000, "pe_res1");
4670a80cf67SAndrii Nakryiko
4680a80cf67SAndrii Nakryiko /* prevent bpf_link__destroy() closing pfd itself */
4690a80cf67SAndrii Nakryiko bpf_link__disconnect(link);
4700a80cf67SAndrii Nakryiko /* close BPF link's FD explicitly */
4710a80cf67SAndrii Nakryiko close(bpf_link__fd(link));
4720a80cf67SAndrii Nakryiko /* free up memory used by struct bpf_link */
4730a80cf67SAndrii Nakryiko bpf_link__destroy(link);
4740a80cf67SAndrii Nakryiko link = NULL;
4750a80cf67SAndrii Nakryiko kern_sync_rcu();
4760a80cf67SAndrii Nakryiko skel->bss->pe_res = 0;
4770a80cf67SAndrii Nakryiko
4780a80cf67SAndrii Nakryiko opts.bpf_cookie = 0x200000;
4790a80cf67SAndrii Nakryiko link = bpf_program__attach_perf_event_opts(skel->progs.handle_pe, pfd, &opts);
4800a80cf67SAndrii Nakryiko if (!ASSERT_OK_PTR(link, "link2"))
4810a80cf67SAndrii Nakryiko goto cleanup;
4820a80cf67SAndrii Nakryiko
4830a80cf67SAndrii Nakryiko burn_cpu(); /* trigger BPF prog */
4840a80cf67SAndrii Nakryiko
4850a80cf67SAndrii Nakryiko ASSERT_EQ(skel->bss->pe_res, 0x200000, "pe_res2");
4860a80cf67SAndrii Nakryiko
4870a80cf67SAndrii Nakryiko cleanup:
4880a80cf67SAndrii Nakryiko close(pfd);
4890a80cf67SAndrii Nakryiko bpf_link__destroy(link);
4900a80cf67SAndrii Nakryiko }
4910a80cf67SAndrii Nakryiko
tracing_subtest(struct test_bpf_cookie * skel)492ddc0027aSKui-Feng Lee static void tracing_subtest(struct test_bpf_cookie *skel)
493ddc0027aSKui-Feng Lee {
494ddc0027aSKui-Feng Lee __u64 cookie;
495ddc0027aSKui-Feng Lee int prog_fd;
496ddc0027aSKui-Feng Lee int fentry_fd = -1, fexit_fd = -1, fmod_ret_fd = -1;
497ddc0027aSKui-Feng Lee LIBBPF_OPTS(bpf_test_run_opts, opts);
498ddc0027aSKui-Feng Lee LIBBPF_OPTS(bpf_link_create_opts, link_opts);
499ddc0027aSKui-Feng Lee
500ddc0027aSKui-Feng Lee skel->bss->fentry_res = 0;
501ddc0027aSKui-Feng Lee skel->bss->fexit_res = 0;
502ddc0027aSKui-Feng Lee
503ddc0027aSKui-Feng Lee cookie = 0x10000000000000L;
504ddc0027aSKui-Feng Lee prog_fd = bpf_program__fd(skel->progs.fentry_test1);
505ddc0027aSKui-Feng Lee link_opts.tracing.cookie = cookie;
506ddc0027aSKui-Feng Lee fentry_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_FENTRY, &link_opts);
507ddc0027aSKui-Feng Lee if (!ASSERT_GE(fentry_fd, 0, "fentry.link_create"))
508ddc0027aSKui-Feng Lee goto cleanup;
509ddc0027aSKui-Feng Lee
510ddc0027aSKui-Feng Lee cookie = 0x20000000000000L;
511ddc0027aSKui-Feng Lee prog_fd = bpf_program__fd(skel->progs.fexit_test1);
512ddc0027aSKui-Feng Lee link_opts.tracing.cookie = cookie;
513ddc0027aSKui-Feng Lee fexit_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_FEXIT, &link_opts);
514ddc0027aSKui-Feng Lee if (!ASSERT_GE(fexit_fd, 0, "fexit.link_create"))
515ddc0027aSKui-Feng Lee goto cleanup;
516ddc0027aSKui-Feng Lee
517ddc0027aSKui-Feng Lee cookie = 0x30000000000000L;
518ddc0027aSKui-Feng Lee prog_fd = bpf_program__fd(skel->progs.fmod_ret_test);
519ddc0027aSKui-Feng Lee link_opts.tracing.cookie = cookie;
520ddc0027aSKui-Feng Lee fmod_ret_fd = bpf_link_create(prog_fd, 0, BPF_MODIFY_RETURN, &link_opts);
521ddc0027aSKui-Feng Lee if (!ASSERT_GE(fmod_ret_fd, 0, "fmod_ret.link_create"))
522ddc0027aSKui-Feng Lee goto cleanup;
523ddc0027aSKui-Feng Lee
524ddc0027aSKui-Feng Lee prog_fd = bpf_program__fd(skel->progs.fentry_test1);
525ddc0027aSKui-Feng Lee bpf_prog_test_run_opts(prog_fd, &opts);
526ddc0027aSKui-Feng Lee
527ddc0027aSKui-Feng Lee prog_fd = bpf_program__fd(skel->progs.fmod_ret_test);
528ddc0027aSKui-Feng Lee bpf_prog_test_run_opts(prog_fd, &opts);
529ddc0027aSKui-Feng Lee
530ddc0027aSKui-Feng Lee ASSERT_EQ(skel->bss->fentry_res, 0x10000000000000L, "fentry_res");
531ddc0027aSKui-Feng Lee ASSERT_EQ(skel->bss->fexit_res, 0x20000000000000L, "fexit_res");
532ddc0027aSKui-Feng Lee ASSERT_EQ(skel->bss->fmod_ret_res, 0x30000000000000L, "fmod_ret_res");
533ddc0027aSKui-Feng Lee
534ddc0027aSKui-Feng Lee cleanup:
535ddc0027aSKui-Feng Lee if (fentry_fd >= 0)
536ddc0027aSKui-Feng Lee close(fentry_fd);
537ddc0027aSKui-Feng Lee if (fexit_fd >= 0)
538ddc0027aSKui-Feng Lee close(fexit_fd);
539ddc0027aSKui-Feng Lee if (fmod_ret_fd >= 0)
540ddc0027aSKui-Feng Lee close(fmod_ret_fd);
541ddc0027aSKui-Feng Lee }
542ddc0027aSKui-Feng Lee
543ddc0027aSKui-Feng Lee int stack_mprotect(void);
544ddc0027aSKui-Feng Lee
lsm_subtest(struct test_bpf_cookie * skel)545ddc0027aSKui-Feng Lee static void lsm_subtest(struct test_bpf_cookie *skel)
546ddc0027aSKui-Feng Lee {
547ddc0027aSKui-Feng Lee __u64 cookie;
548ddc0027aSKui-Feng Lee int prog_fd;
549ddc0027aSKui-Feng Lee int lsm_fd = -1;
550ddc0027aSKui-Feng Lee LIBBPF_OPTS(bpf_link_create_opts, link_opts);
5512934565fSIlya Leoshkevich int err;
552ddc0027aSKui-Feng Lee
553ddc0027aSKui-Feng Lee skel->bss->lsm_res = 0;
554ddc0027aSKui-Feng Lee
555ddc0027aSKui-Feng Lee cookie = 0x90000000000090L;
556ddc0027aSKui-Feng Lee prog_fd = bpf_program__fd(skel->progs.test_int_hook);
557ddc0027aSKui-Feng Lee link_opts.tracing.cookie = cookie;
558ddc0027aSKui-Feng Lee lsm_fd = bpf_link_create(prog_fd, 0, BPF_LSM_MAC, &link_opts);
559ddc0027aSKui-Feng Lee if (!ASSERT_GE(lsm_fd, 0, "lsm.link_create"))
560ddc0027aSKui-Feng Lee goto cleanup;
561ddc0027aSKui-Feng Lee
5622934565fSIlya Leoshkevich err = stack_mprotect();
5632934565fSIlya Leoshkevich if (!ASSERT_EQ(err, -1, "stack_mprotect") ||
5642934565fSIlya Leoshkevich !ASSERT_EQ(errno, EPERM, "stack_mprotect"))
565ddc0027aSKui-Feng Lee goto cleanup;
566ddc0027aSKui-Feng Lee
567ddc0027aSKui-Feng Lee usleep(1);
568ddc0027aSKui-Feng Lee
569ddc0027aSKui-Feng Lee ASSERT_EQ(skel->bss->lsm_res, 0x90000000000090L, "fentry_res");
570ddc0027aSKui-Feng Lee
571ddc0027aSKui-Feng Lee cleanup:
572ddc0027aSKui-Feng Lee if (lsm_fd >= 0)
573ddc0027aSKui-Feng Lee close(lsm_fd);
574ddc0027aSKui-Feng Lee }
575ddc0027aSKui-Feng Lee
test_bpf_cookie(void)5760a80cf67SAndrii Nakryiko void test_bpf_cookie(void)
5770a80cf67SAndrii Nakryiko {
5780a80cf67SAndrii Nakryiko struct test_bpf_cookie *skel;
5790a80cf67SAndrii Nakryiko
5800a80cf67SAndrii Nakryiko skel = test_bpf_cookie__open_and_load();
5810a80cf67SAndrii Nakryiko if (!ASSERT_OK_PTR(skel, "skel_open"))
5820a80cf67SAndrii Nakryiko return;
5830a80cf67SAndrii Nakryiko
5840a80cf67SAndrii Nakryiko skel->bss->my_tid = syscall(SYS_gettid);
5850a80cf67SAndrii Nakryiko
5860a80cf67SAndrii Nakryiko if (test__start_subtest("kprobe"))
5870a80cf67SAndrii Nakryiko kprobe_subtest(skel);
5882c6401c9SJiri Olsa if (test__start_subtest("multi_kprobe_link_api"))
5892c6401c9SJiri Olsa kprobe_multi_link_api_subtest();
590318c812cSJiri Olsa if (test__start_subtest("multi_kprobe_attach_api"))
591318c812cSJiri Olsa kprobe_multi_attach_api_subtest();
5920a80cf67SAndrii Nakryiko if (test__start_subtest("uprobe"))
5930a80cf67SAndrii Nakryiko uprobe_subtest(skel);
594*e7cf9a48SJiri Olsa if (test__start_subtest("multi_uprobe_attach_api"))
595*e7cf9a48SJiri Olsa uprobe_multi_attach_api_subtest();
5960a80cf67SAndrii Nakryiko if (test__start_subtest("tracepoint"))
5970a80cf67SAndrii Nakryiko tp_subtest(skel);
5980a80cf67SAndrii Nakryiko if (test__start_subtest("perf_event"))
5990a80cf67SAndrii Nakryiko pe_subtest(skel);
600ddc0027aSKui-Feng Lee if (test__start_subtest("trampoline"))
601ddc0027aSKui-Feng Lee tracing_subtest(skel);
602ddc0027aSKui-Feng Lee if (test__start_subtest("lsm"))
603ddc0027aSKui-Feng Lee lsm_subtest(skel);
6040a80cf67SAndrii Nakryiko
6050a80cf67SAndrii Nakryiko test_bpf_cookie__destroy(skel);
6060a80cf67SAndrii Nakryiko }
607