0001
0002
0003 #define _GNU_SOURCE
0004 #include <pthread.h>
0005 #include <sched.h>
0006 #include <sys/syscall.h>
0007 #include <sys/mman.h>
0008 #include <unistd.h>
0009 #include <test_progs.h>
0010 #include <network_helpers.h>
0011 #include <bpf/btf.h>
0012 #include "test_bpf_cookie.skel.h"
0013 #include "kprobe_multi.skel.h"
0014
0015
0016 static void trigger_func(void)
0017 {
0018 asm volatile ("");
0019 }
0020
0021 static void kprobe_subtest(struct test_bpf_cookie *skel)
0022 {
0023 DECLARE_LIBBPF_OPTS(bpf_kprobe_opts, opts);
0024 struct bpf_link *link1 = NULL, *link2 = NULL;
0025 struct bpf_link *retlink1 = NULL, *retlink2 = NULL;
0026
0027
0028 opts.bpf_cookie = 0x1;
0029 opts.retprobe = false;
0030 link1 = bpf_program__attach_kprobe_opts(skel->progs.handle_kprobe,
0031 SYS_NANOSLEEP_KPROBE_NAME, &opts);
0032 if (!ASSERT_OK_PTR(link1, "link1"))
0033 goto cleanup;
0034
0035 opts.bpf_cookie = 0x2;
0036 opts.retprobe = false;
0037 link2 = bpf_program__attach_kprobe_opts(skel->progs.handle_kprobe,
0038 SYS_NANOSLEEP_KPROBE_NAME, &opts);
0039 if (!ASSERT_OK_PTR(link2, "link2"))
0040 goto cleanup;
0041
0042
0043 opts.bpf_cookie = 0x10;
0044 opts.retprobe = true;
0045 retlink1 = bpf_program__attach_kprobe_opts(skel->progs.handle_kretprobe,
0046 SYS_NANOSLEEP_KPROBE_NAME, &opts);
0047 if (!ASSERT_OK_PTR(retlink1, "retlink1"))
0048 goto cleanup;
0049
0050 opts.bpf_cookie = 0x20;
0051 opts.retprobe = true;
0052 retlink2 = bpf_program__attach_kprobe_opts(skel->progs.handle_kretprobe,
0053 SYS_NANOSLEEP_KPROBE_NAME, &opts);
0054 if (!ASSERT_OK_PTR(retlink2, "retlink2"))
0055 goto cleanup;
0056
0057
0058 usleep(1);
0059
0060 ASSERT_EQ(skel->bss->kprobe_res, 0x1 | 0x2, "kprobe_res");
0061 ASSERT_EQ(skel->bss->kretprobe_res, 0x10 | 0x20, "kretprobe_res");
0062
0063 cleanup:
0064 bpf_link__destroy(link1);
0065 bpf_link__destroy(link2);
0066 bpf_link__destroy(retlink1);
0067 bpf_link__destroy(retlink2);
0068 }
0069
0070 static void kprobe_multi_test_run(struct kprobe_multi *skel)
0071 {
0072 LIBBPF_OPTS(bpf_test_run_opts, topts);
0073 int err, prog_fd;
0074
0075 prog_fd = bpf_program__fd(skel->progs.trigger);
0076 err = bpf_prog_test_run_opts(prog_fd, &topts);
0077 ASSERT_OK(err, "test_run");
0078 ASSERT_EQ(topts.retval, 0, "test_run");
0079
0080 ASSERT_EQ(skel->bss->kprobe_test1_result, 1, "kprobe_test1_result");
0081 ASSERT_EQ(skel->bss->kprobe_test2_result, 1, "kprobe_test2_result");
0082 ASSERT_EQ(skel->bss->kprobe_test3_result, 1, "kprobe_test3_result");
0083 ASSERT_EQ(skel->bss->kprobe_test4_result, 1, "kprobe_test4_result");
0084 ASSERT_EQ(skel->bss->kprobe_test5_result, 1, "kprobe_test5_result");
0085 ASSERT_EQ(skel->bss->kprobe_test6_result, 1, "kprobe_test6_result");
0086 ASSERT_EQ(skel->bss->kprobe_test7_result, 1, "kprobe_test7_result");
0087 ASSERT_EQ(skel->bss->kprobe_test8_result, 1, "kprobe_test8_result");
0088
0089 ASSERT_EQ(skel->bss->kretprobe_test1_result, 1, "kretprobe_test1_result");
0090 ASSERT_EQ(skel->bss->kretprobe_test2_result, 1, "kretprobe_test2_result");
0091 ASSERT_EQ(skel->bss->kretprobe_test3_result, 1, "kretprobe_test3_result");
0092 ASSERT_EQ(skel->bss->kretprobe_test4_result, 1, "kretprobe_test4_result");
0093 ASSERT_EQ(skel->bss->kretprobe_test5_result, 1, "kretprobe_test5_result");
0094 ASSERT_EQ(skel->bss->kretprobe_test6_result, 1, "kretprobe_test6_result");
0095 ASSERT_EQ(skel->bss->kretprobe_test7_result, 1, "kretprobe_test7_result");
0096 ASSERT_EQ(skel->bss->kretprobe_test8_result, 1, "kretprobe_test8_result");
0097 }
0098
0099 static void kprobe_multi_link_api_subtest(void)
0100 {
0101 int prog_fd, link1_fd = -1, link2_fd = -1;
0102 struct kprobe_multi *skel = NULL;
0103 LIBBPF_OPTS(bpf_link_create_opts, opts);
0104 unsigned long long addrs[8];
0105 __u64 cookies[8];
0106
0107 if (!ASSERT_OK(load_kallsyms(), "load_kallsyms"))
0108 goto cleanup;
0109
0110 skel = kprobe_multi__open_and_load();
0111 if (!ASSERT_OK_PTR(skel, "fentry_raw_skel_load"))
0112 goto cleanup;
0113
0114 skel->bss->pid = getpid();
0115 skel->bss->test_cookie = true;
0116
0117 #define GET_ADDR(__sym, __addr) ({ \
0118 __addr = ksym_get_addr(__sym); \
0119 if (!ASSERT_NEQ(__addr, 0, "ksym_get_addr " #__sym)) \
0120 goto cleanup; \
0121 })
0122
0123 GET_ADDR("bpf_fentry_test1", addrs[0]);
0124 GET_ADDR("bpf_fentry_test3", addrs[1]);
0125 GET_ADDR("bpf_fentry_test4", addrs[2]);
0126 GET_ADDR("bpf_fentry_test5", addrs[3]);
0127 GET_ADDR("bpf_fentry_test6", addrs[4]);
0128 GET_ADDR("bpf_fentry_test7", addrs[5]);
0129 GET_ADDR("bpf_fentry_test2", addrs[6]);
0130 GET_ADDR("bpf_fentry_test8", addrs[7]);
0131
0132 #undef GET_ADDR
0133
0134 cookies[0] = 1;
0135 cookies[1] = 2;
0136 cookies[2] = 3;
0137 cookies[3] = 4;
0138 cookies[4] = 5;
0139 cookies[5] = 6;
0140 cookies[6] = 7;
0141 cookies[7] = 8;
0142
0143 opts.kprobe_multi.addrs = (const unsigned long *) &addrs;
0144 opts.kprobe_multi.cnt = ARRAY_SIZE(addrs);
0145 opts.kprobe_multi.cookies = (const __u64 *) &cookies;
0146 prog_fd = bpf_program__fd(skel->progs.test_kprobe);
0147
0148 link1_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_KPROBE_MULTI, &opts);
0149 if (!ASSERT_GE(link1_fd, 0, "link1_fd"))
0150 goto cleanup;
0151
0152 cookies[0] = 8;
0153 cookies[1] = 7;
0154 cookies[2] = 6;
0155 cookies[3] = 5;
0156 cookies[4] = 4;
0157 cookies[5] = 3;
0158 cookies[6] = 2;
0159 cookies[7] = 1;
0160
0161 opts.kprobe_multi.flags = BPF_F_KPROBE_MULTI_RETURN;
0162 prog_fd = bpf_program__fd(skel->progs.test_kretprobe);
0163
0164 link2_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_KPROBE_MULTI, &opts);
0165 if (!ASSERT_GE(link2_fd, 0, "link2_fd"))
0166 goto cleanup;
0167
0168 kprobe_multi_test_run(skel);
0169
0170 cleanup:
0171 close(link1_fd);
0172 close(link2_fd);
0173 kprobe_multi__destroy(skel);
0174 }
0175
0176 static void kprobe_multi_attach_api_subtest(void)
0177 {
0178 struct bpf_link *link1 = NULL, *link2 = NULL;
0179 LIBBPF_OPTS(bpf_kprobe_multi_opts, opts);
0180 LIBBPF_OPTS(bpf_test_run_opts, topts);
0181 struct kprobe_multi *skel = NULL;
0182 const char *syms[8] = {
0183 "bpf_fentry_test1",
0184 "bpf_fentry_test3",
0185 "bpf_fentry_test4",
0186 "bpf_fentry_test5",
0187 "bpf_fentry_test6",
0188 "bpf_fentry_test7",
0189 "bpf_fentry_test2",
0190 "bpf_fentry_test8",
0191 };
0192 __u64 cookies[8];
0193
0194 skel = kprobe_multi__open_and_load();
0195 if (!ASSERT_OK_PTR(skel, "fentry_raw_skel_load"))
0196 goto cleanup;
0197
0198 skel->bss->pid = getpid();
0199 skel->bss->test_cookie = true;
0200
0201 cookies[0] = 1;
0202 cookies[1] = 2;
0203 cookies[2] = 3;
0204 cookies[3] = 4;
0205 cookies[4] = 5;
0206 cookies[5] = 6;
0207 cookies[6] = 7;
0208 cookies[7] = 8;
0209
0210 opts.syms = syms;
0211 opts.cnt = ARRAY_SIZE(syms);
0212 opts.cookies = cookies;
0213
0214 link1 = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe,
0215 NULL, &opts);
0216 if (!ASSERT_OK_PTR(link1, "bpf_program__attach_kprobe_multi_opts"))
0217 goto cleanup;
0218
0219 cookies[0] = 8;
0220 cookies[1] = 7;
0221 cookies[2] = 6;
0222 cookies[3] = 5;
0223 cookies[4] = 4;
0224 cookies[5] = 3;
0225 cookies[6] = 2;
0226 cookies[7] = 1;
0227
0228 opts.retprobe = true;
0229
0230 link2 = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kretprobe,
0231 NULL, &opts);
0232 if (!ASSERT_OK_PTR(link2, "bpf_program__attach_kprobe_multi_opts"))
0233 goto cleanup;
0234
0235 kprobe_multi_test_run(skel);
0236
0237 cleanup:
0238 bpf_link__destroy(link2);
0239 bpf_link__destroy(link1);
0240 kprobe_multi__destroy(skel);
0241 }
0242 static void uprobe_subtest(struct test_bpf_cookie *skel)
0243 {
0244 DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, opts);
0245 struct bpf_link *link1 = NULL, *link2 = NULL;
0246 struct bpf_link *retlink1 = NULL, *retlink2 = NULL;
0247 ssize_t uprobe_offset;
0248
0249 uprobe_offset = get_uprobe_offset(&trigger_func);
0250 if (!ASSERT_GE(uprobe_offset, 0, "uprobe_offset"))
0251 goto cleanup;
0252
0253
0254 opts.bpf_cookie = 0x100;
0255 opts.retprobe = false;
0256 link1 = bpf_program__attach_uprobe_opts(skel->progs.handle_uprobe, 0 ,
0257 "/proc/self/exe", uprobe_offset, &opts);
0258 if (!ASSERT_OK_PTR(link1, "link1"))
0259 goto cleanup;
0260
0261 opts.bpf_cookie = 0x200;
0262 opts.retprobe = false;
0263 link2 = bpf_program__attach_uprobe_opts(skel->progs.handle_uprobe, -1 ,
0264 "/proc/self/exe", uprobe_offset, &opts);
0265 if (!ASSERT_OK_PTR(link2, "link2"))
0266 goto cleanup;
0267
0268
0269 opts.bpf_cookie = 0x1000;
0270 opts.retprobe = true;
0271 retlink1 = bpf_program__attach_uprobe_opts(skel->progs.handle_uretprobe, -1 ,
0272 "/proc/self/exe", uprobe_offset, &opts);
0273 if (!ASSERT_OK_PTR(retlink1, "retlink1"))
0274 goto cleanup;
0275
0276 opts.bpf_cookie = 0x2000;
0277 opts.retprobe = true;
0278 retlink2 = bpf_program__attach_uprobe_opts(skel->progs.handle_uretprobe, 0 ,
0279 "/proc/self/exe", uprobe_offset, &opts);
0280 if (!ASSERT_OK_PTR(retlink2, "retlink2"))
0281 goto cleanup;
0282
0283
0284 trigger_func();
0285
0286 ASSERT_EQ(skel->bss->uprobe_res, 0x100 | 0x200, "uprobe_res");
0287 ASSERT_EQ(skel->bss->uretprobe_res, 0x1000 | 0x2000, "uretprobe_res");
0288
0289 cleanup:
0290 bpf_link__destroy(link1);
0291 bpf_link__destroy(link2);
0292 bpf_link__destroy(retlink1);
0293 bpf_link__destroy(retlink2);
0294 }
0295
0296 static void tp_subtest(struct test_bpf_cookie *skel)
0297 {
0298 DECLARE_LIBBPF_OPTS(bpf_tracepoint_opts, opts);
0299 struct bpf_link *link1 = NULL, *link2 = NULL, *link3 = NULL;
0300
0301
0302 opts.bpf_cookie = 0x10000;
0303 link1 = bpf_program__attach_tracepoint_opts(skel->progs.handle_tp1,
0304 "syscalls", "sys_enter_nanosleep", &opts);
0305 if (!ASSERT_OK_PTR(link1, "link1"))
0306 goto cleanup;
0307
0308
0309 opts.bpf_cookie = 0x20000;
0310 link2 = bpf_program__attach_tracepoint_opts(skel->progs.handle_tp2,
0311 "syscalls", "sys_enter_nanosleep", &opts);
0312 if (!ASSERT_OK_PTR(link2, "link2"))
0313 goto cleanup;
0314
0315
0316 usleep(1);
0317
0318 ASSERT_EQ(skel->bss->tp_res, 0x10000 | 0x20000, "tp_res1");
0319
0320
0321
0322
0323
0324
0325 bpf_link__destroy(link1);
0326 link1 = NULL;
0327 kern_sync_rcu();
0328 skel->bss->tp_res = 0;
0329
0330
0331 opts.bpf_cookie = 0x40000;
0332 link3 = bpf_program__attach_tracepoint_opts(skel->progs.handle_tp3,
0333 "syscalls", "sys_enter_nanosleep", &opts);
0334 if (!ASSERT_OK_PTR(link3, "link3"))
0335 goto cleanup;
0336
0337
0338 usleep(1);
0339
0340 ASSERT_EQ(skel->bss->tp_res, 0x20000 | 0x40000, "tp_res2");
0341
0342 cleanup:
0343 bpf_link__destroy(link1);
0344 bpf_link__destroy(link2);
0345 bpf_link__destroy(link3);
0346 }
0347
0348 static void burn_cpu(void)
0349 {
0350 volatile int j = 0;
0351 cpu_set_t cpu_set;
0352 int i, err;
0353
0354
0355 CPU_ZERO(&cpu_set);
0356 CPU_SET(0, &cpu_set);
0357 err = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set), &cpu_set);
0358 ASSERT_OK(err, "set_thread_affinity");
0359
0360
0361 for (i = 0; i < 1000000; ++i)
0362 ++j;
0363 }
0364
0365 static void pe_subtest(struct test_bpf_cookie *skel)
0366 {
0367 DECLARE_LIBBPF_OPTS(bpf_perf_event_opts, opts);
0368 struct bpf_link *link = NULL;
0369 struct perf_event_attr attr;
0370 int pfd = -1;
0371
0372
0373 memset(&attr, 0, sizeof(attr));
0374 attr.size = sizeof(attr);
0375 attr.type = PERF_TYPE_SOFTWARE;
0376 attr.config = PERF_COUNT_SW_CPU_CLOCK;
0377 attr.freq = 1;
0378 attr.sample_freq = 1000;
0379 pfd = syscall(__NR_perf_event_open, &attr, -1, 0, -1, PERF_FLAG_FD_CLOEXEC);
0380 if (!ASSERT_GE(pfd, 0, "perf_fd"))
0381 goto cleanup;
0382
0383 opts.bpf_cookie = 0x100000;
0384 link = bpf_program__attach_perf_event_opts(skel->progs.handle_pe, pfd, &opts);
0385 if (!ASSERT_OK_PTR(link, "link1"))
0386 goto cleanup;
0387
0388 burn_cpu();
0389
0390 ASSERT_EQ(skel->bss->pe_res, 0x100000, "pe_res1");
0391
0392
0393 bpf_link__disconnect(link);
0394
0395 close(bpf_link__fd(link));
0396
0397 bpf_link__destroy(link);
0398 link = NULL;
0399 kern_sync_rcu();
0400 skel->bss->pe_res = 0;
0401
0402 opts.bpf_cookie = 0x200000;
0403 link = bpf_program__attach_perf_event_opts(skel->progs.handle_pe, pfd, &opts);
0404 if (!ASSERT_OK_PTR(link, "link2"))
0405 goto cleanup;
0406
0407 burn_cpu();
0408
0409 ASSERT_EQ(skel->bss->pe_res, 0x200000, "pe_res2");
0410
0411 cleanup:
0412 close(pfd);
0413 bpf_link__destroy(link);
0414 }
0415
0416 static void tracing_subtest(struct test_bpf_cookie *skel)
0417 {
0418 __u64 cookie;
0419 int prog_fd;
0420 int fentry_fd = -1, fexit_fd = -1, fmod_ret_fd = -1;
0421 LIBBPF_OPTS(bpf_test_run_opts, opts);
0422 LIBBPF_OPTS(bpf_link_create_opts, link_opts);
0423
0424 skel->bss->fentry_res = 0;
0425 skel->bss->fexit_res = 0;
0426
0427 cookie = 0x10000000000000L;
0428 prog_fd = bpf_program__fd(skel->progs.fentry_test1);
0429 link_opts.tracing.cookie = cookie;
0430 fentry_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_FENTRY, &link_opts);
0431 if (!ASSERT_GE(fentry_fd, 0, "fentry.link_create"))
0432 goto cleanup;
0433
0434 cookie = 0x20000000000000L;
0435 prog_fd = bpf_program__fd(skel->progs.fexit_test1);
0436 link_opts.tracing.cookie = cookie;
0437 fexit_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_FEXIT, &link_opts);
0438 if (!ASSERT_GE(fexit_fd, 0, "fexit.link_create"))
0439 goto cleanup;
0440
0441 cookie = 0x30000000000000L;
0442 prog_fd = bpf_program__fd(skel->progs.fmod_ret_test);
0443 link_opts.tracing.cookie = cookie;
0444 fmod_ret_fd = bpf_link_create(prog_fd, 0, BPF_MODIFY_RETURN, &link_opts);
0445 if (!ASSERT_GE(fmod_ret_fd, 0, "fmod_ret.link_create"))
0446 goto cleanup;
0447
0448 prog_fd = bpf_program__fd(skel->progs.fentry_test1);
0449 bpf_prog_test_run_opts(prog_fd, &opts);
0450
0451 prog_fd = bpf_program__fd(skel->progs.fmod_ret_test);
0452 bpf_prog_test_run_opts(prog_fd, &opts);
0453
0454 ASSERT_EQ(skel->bss->fentry_res, 0x10000000000000L, "fentry_res");
0455 ASSERT_EQ(skel->bss->fexit_res, 0x20000000000000L, "fexit_res");
0456 ASSERT_EQ(skel->bss->fmod_ret_res, 0x30000000000000L, "fmod_ret_res");
0457
0458 cleanup:
0459 if (fentry_fd >= 0)
0460 close(fentry_fd);
0461 if (fexit_fd >= 0)
0462 close(fexit_fd);
0463 if (fmod_ret_fd >= 0)
0464 close(fmod_ret_fd);
0465 }
0466
0467 int stack_mprotect(void);
0468
0469 static void lsm_subtest(struct test_bpf_cookie *skel)
0470 {
0471 __u64 cookie;
0472 int prog_fd;
0473 int lsm_fd = -1;
0474 LIBBPF_OPTS(bpf_link_create_opts, link_opts);
0475
0476 skel->bss->lsm_res = 0;
0477
0478 cookie = 0x90000000000090L;
0479 prog_fd = bpf_program__fd(skel->progs.test_int_hook);
0480 link_opts.tracing.cookie = cookie;
0481 lsm_fd = bpf_link_create(prog_fd, 0, BPF_LSM_MAC, &link_opts);
0482 if (!ASSERT_GE(lsm_fd, 0, "lsm.link_create"))
0483 goto cleanup;
0484
0485 stack_mprotect();
0486 if (!ASSERT_EQ(errno, EPERM, "stack_mprotect"))
0487 goto cleanup;
0488
0489 usleep(1);
0490
0491 ASSERT_EQ(skel->bss->lsm_res, 0x90000000000090L, "fentry_res");
0492
0493 cleanup:
0494 if (lsm_fd >= 0)
0495 close(lsm_fd);
0496 }
0497
0498 void test_bpf_cookie(void)
0499 {
0500 struct test_bpf_cookie *skel;
0501
0502 skel = test_bpf_cookie__open_and_load();
0503 if (!ASSERT_OK_PTR(skel, "skel_open"))
0504 return;
0505
0506 skel->bss->my_tid = syscall(SYS_gettid);
0507
0508 if (test__start_subtest("kprobe"))
0509 kprobe_subtest(skel);
0510 if (test__start_subtest("multi_kprobe_link_api"))
0511 kprobe_multi_link_api_subtest();
0512 if (test__start_subtest("multi_kprobe_attach_api"))
0513 kprobe_multi_attach_api_subtest();
0514 if (test__start_subtest("uprobe"))
0515 uprobe_subtest(skel);
0516 if (test__start_subtest("tracepoint"))
0517 tp_subtest(skel);
0518 if (test__start_subtest("perf_event"))
0519 pe_subtest(skel);
0520 if (test__start_subtest("trampoline"))
0521 tracing_subtest(skel);
0522 if (test__start_subtest("lsm"))
0523 lsm_subtest(skel);
0524
0525 test_bpf_cookie__destroy(skel);
0526 }