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

Configure Feed

Select the types of activity you want to include in your feed.

at master 753 lines 22 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2#include <errno.h> 3#include <sys/prctl.h> 4#include <test_progs.h> 5#include "kprobe_multi.skel.h" 6#include "trace_helpers.h" 7#include "kprobe_multi_empty.skel.h" 8#include "kprobe_multi_override.skel.h" 9#include "kprobe_multi_session.skel.h" 10#include "kprobe_multi_session_cookie.skel.h" 11#include "kprobe_multi_verifier.skel.h" 12#include "kprobe_write_ctx.skel.h" 13#include "kprobe_multi_sleepable.skel.h" 14#include "bpf/libbpf_internal.h" 15#include "bpf/hashmap.h" 16 17static void kprobe_multi_test_run(struct kprobe_multi *skel, bool test_return) 18{ 19 LIBBPF_OPTS(bpf_test_run_opts, topts); 20 int err, prog_fd; 21 22 prog_fd = bpf_program__fd(skel->progs.trigger); 23 err = bpf_prog_test_run_opts(prog_fd, &topts); 24 ASSERT_OK(err, "test_run"); 25 ASSERT_EQ(topts.retval, 0, "test_run"); 26 27 ASSERT_EQ(skel->bss->kprobe_test1_result, 1, "kprobe_test1_result"); 28 ASSERT_EQ(skel->bss->kprobe_test2_result, 1, "kprobe_test2_result"); 29 ASSERT_EQ(skel->bss->kprobe_test3_result, 1, "kprobe_test3_result"); 30 ASSERT_EQ(skel->bss->kprobe_test4_result, 1, "kprobe_test4_result"); 31 ASSERT_EQ(skel->bss->kprobe_test5_result, 1, "kprobe_test5_result"); 32 ASSERT_EQ(skel->bss->kprobe_test6_result, 1, "kprobe_test6_result"); 33 ASSERT_EQ(skel->bss->kprobe_test7_result, 1, "kprobe_test7_result"); 34 ASSERT_EQ(skel->bss->kprobe_test8_result, 1, "kprobe_test8_result"); 35 36 if (test_return) { 37 ASSERT_EQ(skel->bss->kretprobe_test1_result, 1, "kretprobe_test1_result"); 38 ASSERT_EQ(skel->bss->kretprobe_test2_result, 1, "kretprobe_test2_result"); 39 ASSERT_EQ(skel->bss->kretprobe_test3_result, 1, "kretprobe_test3_result"); 40 ASSERT_EQ(skel->bss->kretprobe_test4_result, 1, "kretprobe_test4_result"); 41 ASSERT_EQ(skel->bss->kretprobe_test5_result, 1, "kretprobe_test5_result"); 42 ASSERT_EQ(skel->bss->kretprobe_test6_result, 1, "kretprobe_test6_result"); 43 ASSERT_EQ(skel->bss->kretprobe_test7_result, 1, "kretprobe_test7_result"); 44 ASSERT_EQ(skel->bss->kretprobe_test8_result, 1, "kretprobe_test8_result"); 45 } 46} 47 48static void test_skel_api(void) 49{ 50 struct kprobe_multi *skel = NULL; 51 int err; 52 53 skel = kprobe_multi__open_and_load(); 54 if (!ASSERT_OK_PTR(skel, "kprobe_multi__open_and_load")) 55 goto cleanup; 56 57 skel->bss->pid = getpid(); 58 err = kprobe_multi__attach(skel); 59 if (!ASSERT_OK(err, "kprobe_multi__attach")) 60 goto cleanup; 61 62 kprobe_multi_test_run(skel, true); 63 64cleanup: 65 kprobe_multi__destroy(skel); 66} 67 68static void test_link_api(struct bpf_link_create_opts *opts) 69{ 70 int prog_fd, link1_fd = -1, link2_fd = -1; 71 struct kprobe_multi *skel = NULL; 72 73 skel = kprobe_multi__open_and_load(); 74 if (!ASSERT_OK_PTR(skel, "fentry_raw_skel_load")) 75 goto cleanup; 76 77 skel->bss->pid = getpid(); 78 prog_fd = bpf_program__fd(skel->progs.test_kprobe); 79 link1_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_KPROBE_MULTI, opts); 80 if (!ASSERT_GE(link1_fd, 0, "link_fd")) 81 goto cleanup; 82 83 opts->kprobe_multi.flags = BPF_F_KPROBE_MULTI_RETURN; 84 prog_fd = bpf_program__fd(skel->progs.test_kretprobe); 85 link2_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_KPROBE_MULTI, opts); 86 if (!ASSERT_GE(link2_fd, 0, "link_fd")) 87 goto cleanup; 88 89 kprobe_multi_test_run(skel, true); 90 91cleanup: 92 if (link1_fd != -1) 93 close(link1_fd); 94 if (link2_fd != -1) 95 close(link2_fd); 96 kprobe_multi__destroy(skel); 97} 98 99#define GET_ADDR(__sym, __addr) ({ \ 100 __addr = ksym_get_addr(__sym); \ 101 if (!ASSERT_NEQ(__addr, 0, "kallsyms load failed for " #__sym)) \ 102 return; \ 103}) 104 105static void test_link_api_addrs(void) 106{ 107 LIBBPF_OPTS(bpf_link_create_opts, opts); 108 unsigned long long addrs[8]; 109 110 GET_ADDR("bpf_fentry_test1", addrs[0]); 111 GET_ADDR("bpf_fentry_test2", addrs[1]); 112 GET_ADDR("bpf_fentry_test3", addrs[2]); 113 GET_ADDR("bpf_fentry_test4", addrs[3]); 114 GET_ADDR("bpf_fentry_test5", addrs[4]); 115 GET_ADDR("bpf_fentry_test6", addrs[5]); 116 GET_ADDR("bpf_fentry_test7", addrs[6]); 117 GET_ADDR("bpf_fentry_test8", addrs[7]); 118 119 opts.kprobe_multi.addrs = (const unsigned long*) addrs; 120 opts.kprobe_multi.cnt = ARRAY_SIZE(addrs); 121 test_link_api(&opts); 122} 123 124static void test_link_api_syms(void) 125{ 126 LIBBPF_OPTS(bpf_link_create_opts, opts); 127 const char *syms[8] = { 128 "bpf_fentry_test1", 129 "bpf_fentry_test2", 130 "bpf_fentry_test3", 131 "bpf_fentry_test4", 132 "bpf_fentry_test5", 133 "bpf_fentry_test6", 134 "bpf_fentry_test7", 135 "bpf_fentry_test8", 136 }; 137 138 opts.kprobe_multi.syms = syms; 139 opts.kprobe_multi.cnt = ARRAY_SIZE(syms); 140 test_link_api(&opts); 141} 142 143static void 144test_attach_api(const char *pattern, struct bpf_kprobe_multi_opts *opts) 145{ 146 struct bpf_link *link1 = NULL, *link2 = NULL; 147 struct kprobe_multi *skel = NULL; 148 149 skel = kprobe_multi__open_and_load(); 150 if (!ASSERT_OK_PTR(skel, "fentry_raw_skel_load")) 151 goto cleanup; 152 153 skel->bss->pid = getpid(); 154 link1 = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual, 155 pattern, opts); 156 if (!ASSERT_OK_PTR(link1, "bpf_program__attach_kprobe_multi_opts")) 157 goto cleanup; 158 159 if (opts) { 160 opts->retprobe = true; 161 link2 = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kretprobe_manual, 162 pattern, opts); 163 if (!ASSERT_OK_PTR(link2, "bpf_program__attach_kprobe_multi_opts")) 164 goto cleanup; 165 } 166 167 kprobe_multi_test_run(skel, !!opts); 168 169cleanup: 170 bpf_link__destroy(link2); 171 bpf_link__destroy(link1); 172 kprobe_multi__destroy(skel); 173} 174 175static void test_attach_api_pattern(void) 176{ 177 LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); 178 179 test_attach_api("bpf_fentry_test*", &opts); 180 test_attach_api("bpf_fentry_test?", NULL); 181} 182 183static void test_attach_api_addrs(void) 184{ 185 LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); 186 unsigned long long addrs[8]; 187 188 GET_ADDR("bpf_fentry_test1", addrs[0]); 189 GET_ADDR("bpf_fentry_test2", addrs[1]); 190 GET_ADDR("bpf_fentry_test3", addrs[2]); 191 GET_ADDR("bpf_fentry_test4", addrs[3]); 192 GET_ADDR("bpf_fentry_test5", addrs[4]); 193 GET_ADDR("bpf_fentry_test6", addrs[5]); 194 GET_ADDR("bpf_fentry_test7", addrs[6]); 195 GET_ADDR("bpf_fentry_test8", addrs[7]); 196 197 opts.addrs = (const unsigned long *) addrs; 198 opts.cnt = ARRAY_SIZE(addrs); 199 test_attach_api(NULL, &opts); 200} 201 202static void test_attach_api_syms(void) 203{ 204 LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); 205 const char *syms[8] = { 206 "bpf_fentry_test1", 207 "bpf_fentry_test2", 208 "bpf_fentry_test3", 209 "bpf_fentry_test4", 210 "bpf_fentry_test5", 211 "bpf_fentry_test6", 212 "bpf_fentry_test7", 213 "bpf_fentry_test8", 214 }; 215 216 opts.syms = syms; 217 opts.cnt = ARRAY_SIZE(syms); 218 test_attach_api(NULL, &opts); 219} 220 221static void test_attach_api_fails(void) 222{ 223 LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); 224 LIBBPF_OPTS(bpf_test_run_opts, topts); 225 struct kprobe_multi *skel = NULL; 226 struct kprobe_multi_sleepable *sl_skel = NULL; 227 struct bpf_link *link = NULL; 228 unsigned long long addrs[2]; 229 const char *syms[2] = { 230 "bpf_fentry_test1", 231 "bpf_fentry_test2", 232 }; 233 __u64 cookies[2]; 234 int saved_error, err; 235 236 addrs[0] = ksym_get_addr("bpf_fentry_test1"); 237 addrs[1] = ksym_get_addr("bpf_fentry_test2"); 238 239 if (!ASSERT_FALSE(!addrs[0] || !addrs[1], "ksym_get_addr")) 240 goto cleanup; 241 242 skel = kprobe_multi__open_and_load(); 243 if (!ASSERT_OK_PTR(skel, "fentry_raw_skel_load")) 244 goto cleanup; 245 246 skel->bss->pid = getpid(); 247 248 /* fail_1 - pattern and opts NULL */ 249 link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual, 250 NULL, NULL); 251 saved_error = -errno; 252 if (!ASSERT_ERR_PTR(link, "fail_1")) 253 goto cleanup; 254 255 if (!ASSERT_EQ(saved_error, -EINVAL, "fail_1_error")) 256 goto cleanup; 257 258 /* fail_2 - both addrs and syms set */ 259 opts.addrs = (const unsigned long *) addrs; 260 opts.syms = syms; 261 opts.cnt = ARRAY_SIZE(syms); 262 opts.cookies = NULL; 263 264 link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual, 265 NULL, &opts); 266 saved_error = -errno; 267 if (!ASSERT_ERR_PTR(link, "fail_2")) 268 goto cleanup; 269 270 if (!ASSERT_EQ(saved_error, -EINVAL, "fail_2_error")) 271 goto cleanup; 272 273 /* fail_3 - pattern and addrs set */ 274 opts.addrs = (const unsigned long *) addrs; 275 opts.syms = NULL; 276 opts.cnt = ARRAY_SIZE(syms); 277 opts.cookies = NULL; 278 279 link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual, 280 "ksys_*", &opts); 281 saved_error = -errno; 282 if (!ASSERT_ERR_PTR(link, "fail_3")) 283 goto cleanup; 284 285 if (!ASSERT_EQ(saved_error, -EINVAL, "fail_3_error")) 286 goto cleanup; 287 288 /* fail_4 - pattern and cnt set */ 289 opts.addrs = NULL; 290 opts.syms = NULL; 291 opts.cnt = ARRAY_SIZE(syms); 292 opts.cookies = NULL; 293 294 link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual, 295 "ksys_*", &opts); 296 saved_error = -errno; 297 if (!ASSERT_ERR_PTR(link, "fail_4")) 298 goto cleanup; 299 300 if (!ASSERT_EQ(saved_error, -EINVAL, "fail_4_error")) 301 goto cleanup; 302 303 /* fail_5 - pattern and cookies */ 304 opts.addrs = NULL; 305 opts.syms = NULL; 306 opts.cnt = 0; 307 opts.cookies = cookies; 308 309 link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual, 310 "ksys_*", &opts); 311 saved_error = -errno; 312 if (!ASSERT_ERR_PTR(link, "fail_5")) 313 goto cleanup; 314 315 if (!ASSERT_EQ(saved_error, -EINVAL, "fail_5_error")) 316 goto cleanup; 317 318 /* fail_6 - abnormal cnt */ 319 opts.addrs = (const unsigned long *) addrs; 320 opts.syms = NULL; 321 opts.cnt = INT_MAX; 322 opts.cookies = NULL; 323 324 link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual, 325 NULL, &opts); 326 saved_error = -errno; 327 if (!ASSERT_ERR_PTR(link, "fail_6")) 328 goto cleanup; 329 330 if (!ASSERT_EQ(saved_error, -E2BIG, "fail_6_error")) 331 goto cleanup; 332 333 /* fail_7 - non-existent wildcard pattern (slow path) */ 334 LIBBPF_OPTS_RESET(opts); 335 336 link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual, 337 "__nonexistent_func_xyz_*", 338 &opts); 339 saved_error = -errno; 340 if (!ASSERT_ERR_PTR(link, "fail_7")) 341 goto cleanup; 342 343 if (!ASSERT_EQ(saved_error, -ENOENT, "fail_7_error")) 344 goto cleanup; 345 346 /* fail_8 - non-existent exact name (fast path), same error as wildcard */ 347 link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual, 348 "__nonexistent_func_xyz_123", 349 &opts); 350 saved_error = -errno; 351 if (!ASSERT_ERR_PTR(link, "fail_8")) 352 goto cleanup; 353 354 if (!ASSERT_EQ(saved_error, -ENOENT, "fail_8_error")) 355 goto cleanup; 356 357 /* fail_9 - sleepable kprobe multi should not attach */ 358 sl_skel = kprobe_multi_sleepable__open(); 359 if (!ASSERT_OK_PTR(sl_skel, "sleep_skel_open")) 360 goto cleanup; 361 362 sl_skel->bss->user_ptr = sl_skel; 363 364 err = bpf_program__set_flags(sl_skel->progs.handle_kprobe_multi_sleepable, 365 BPF_F_SLEEPABLE); 366 if (!ASSERT_OK(err, "sleep_skel_set_flags")) 367 goto cleanup; 368 369 err = kprobe_multi_sleepable__load(sl_skel); 370 if (!ASSERT_OK(err, "sleep_skel_load")) 371 goto cleanup; 372 373 link = bpf_program__attach_kprobe_multi_opts(sl_skel->progs.handle_kprobe_multi_sleepable, 374 "bpf_fentry_test1", NULL); 375 saved_error = -errno; 376 377 if (!ASSERT_ERR_PTR(link, "fail_9")) 378 goto cleanup; 379 380 if (!ASSERT_EQ(saved_error, -EINVAL, "fail_9_error")) 381 goto cleanup; 382 383 err = bpf_prog_test_run_opts(bpf_program__fd(sl_skel->progs.fentry), &topts); 384 ASSERT_OK(err, "bpf_prog_test_run_opts"); 385 386cleanup: 387 bpf_link__destroy(link); 388 kprobe_multi__destroy(skel); 389 kprobe_multi_sleepable__destroy(sl_skel); 390} 391 392static void test_session_skel_api(void) 393{ 394 struct kprobe_multi_session *skel = NULL; 395 LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); 396 LIBBPF_OPTS(bpf_test_run_opts, topts); 397 struct bpf_link *link = NULL; 398 int i, err, prog_fd; 399 400 skel = kprobe_multi_session__open_and_load(); 401 if (!ASSERT_OK_PTR(skel, "kprobe_multi_session__open_and_load")) 402 return; 403 404 skel->bss->pid = getpid(); 405 406 err = kprobe_multi_session__attach(skel); 407 if (!ASSERT_OK(err, " kprobe_multi_session__attach")) 408 goto cleanup; 409 410 prog_fd = bpf_program__fd(skel->progs.trigger); 411 err = bpf_prog_test_run_opts(prog_fd, &topts); 412 ASSERT_OK(err, "test_run"); 413 ASSERT_EQ(topts.retval, 0, "test_run"); 414 415 /* 416 * bpf_fentry_test1 is hit by both the wildcard probe and the exact 417 * name probe (test_kprobe_syms), so entry + return fires twice: 4. 418 * bpf_fentry_test2-4 are hit only by the wildcard probe: 2. 419 */ 420 ASSERT_EQ(skel->bss->kprobe_session_result[0], 4, "kprobe_session_result"); 421 for (i = 1; i < 4; i++) 422 ASSERT_EQ(skel->bss->kprobe_session_result[i], 2, "kprobe_session_result"); 423 424 /* bpf_fentry_test5-8 trigger only entry probe, result is 1 */ 425 for (i = 4; i < 8; i++) 426 ASSERT_EQ(skel->bss->kprobe_session_result[i], 1, "kprobe_session_result"); 427 428cleanup: 429 bpf_link__destroy(link); 430 kprobe_multi_session__destroy(skel); 431} 432 433static void test_session_cookie_skel_api(void) 434{ 435 struct kprobe_multi_session_cookie *skel = NULL; 436 LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); 437 LIBBPF_OPTS(bpf_test_run_opts, topts); 438 struct bpf_link *link = NULL; 439 int err, prog_fd; 440 441 skel = kprobe_multi_session_cookie__open_and_load(); 442 if (!ASSERT_OK_PTR(skel, "fentry_raw_skel_load")) 443 return; 444 445 skel->bss->pid = getpid(); 446 447 err = kprobe_multi_session_cookie__attach(skel); 448 if (!ASSERT_OK(err, " kprobe_multi_wrapper__attach")) 449 goto cleanup; 450 451 prog_fd = bpf_program__fd(skel->progs.trigger); 452 err = bpf_prog_test_run_opts(prog_fd, &topts); 453 ASSERT_OK(err, "test_run"); 454 ASSERT_EQ(topts.retval, 0, "test_run"); 455 456 ASSERT_EQ(skel->bss->test_kprobe_1_result, 1, "test_kprobe_1_result"); 457 ASSERT_EQ(skel->bss->test_kprobe_2_result, 2, "test_kprobe_2_result"); 458 ASSERT_EQ(skel->bss->test_kprobe_3_result, 3, "test_kprobe_3_result"); 459 460cleanup: 461 bpf_link__destroy(link); 462 kprobe_multi_session_cookie__destroy(skel); 463} 464 465static void test_unique_match(void) 466{ 467 LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); 468 struct kprobe_multi *skel = NULL; 469 struct bpf_link *link = NULL; 470 471 skel = kprobe_multi__open_and_load(); 472 if (!ASSERT_OK_PTR(skel, "kprobe_multi__open_and_load")) 473 return; 474 475 opts.unique_match = true; 476 skel->bss->pid = getpid(); 477 link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual, 478 "bpf_fentry_test*", &opts); 479 if (!ASSERT_ERR_PTR(link, "bpf_program__attach_kprobe_multi_opts")) 480 bpf_link__destroy(link); 481 482 link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual, 483 "bpf_fentry_test8*", &opts); 484 if (ASSERT_OK_PTR(link, "bpf_program__attach_kprobe_multi_opts")) 485 bpf_link__destroy(link); 486 487 kprobe_multi__destroy(skel); 488} 489 490static void do_bench_test(struct kprobe_multi_empty *skel, struct bpf_kprobe_multi_opts *opts) 491{ 492 long attach_start_ns, attach_end_ns; 493 long detach_start_ns, detach_end_ns; 494 double attach_delta, detach_delta; 495 struct bpf_link *link = NULL; 496 497 attach_start_ns = get_time_ns(); 498 link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_empty, 499 NULL, opts); 500 attach_end_ns = get_time_ns(); 501 502 if (!ASSERT_OK_PTR(link, "bpf_program__attach_kprobe_multi_opts")) 503 return; 504 505 detach_start_ns = get_time_ns(); 506 bpf_link__destroy(link); 507 detach_end_ns = get_time_ns(); 508 509 attach_delta = (attach_end_ns - attach_start_ns) / 1000000000.0; 510 detach_delta = (detach_end_ns - detach_start_ns) / 1000000000.0; 511 512 printf("%s: found %lu functions\n", __func__, opts->cnt); 513 printf("%s: attached in %7.3lfs\n", __func__, attach_delta); 514 printf("%s: detached in %7.3lfs\n", __func__, detach_delta); 515} 516 517static void test_kprobe_multi_bench_attach(bool kernel) 518{ 519 LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); 520 struct kprobe_multi_empty *skel = NULL; 521 struct ksyms *ksyms = NULL; 522 523 if (!ASSERT_OK(bpf_get_ksyms(&ksyms, kernel), "bpf_get_ksyms")) 524 return; 525 526 skel = kprobe_multi_empty__open_and_load(); 527 if (!ASSERT_OK_PTR(skel, "kprobe_multi_empty__open_and_load")) 528 goto cleanup; 529 530 opts.syms = (const char **)ksyms->filtered_syms; 531 opts.cnt = ksyms->filtered_cnt; 532 533 do_bench_test(skel, &opts); 534 535cleanup: 536 kprobe_multi_empty__destroy(skel); 537 free_kallsyms_local(ksyms); 538} 539 540static void test_kprobe_multi_bench_attach_addr(bool kernel) 541{ 542 LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); 543 struct kprobe_multi_empty *skel = NULL; 544 unsigned long *addrs = NULL; 545 size_t cnt = 0; 546 int err; 547 548 err = bpf_get_addrs(&addrs, &cnt, kernel); 549 if (err == -ENOENT) { 550 test__skip(); 551 return; 552 } 553 554 if (!ASSERT_OK(err, "bpf_get_addrs")) 555 return; 556 557 skel = kprobe_multi_empty__open_and_load(); 558 if (!ASSERT_OK_PTR(skel, "kprobe_multi_empty__open_and_load")) 559 goto cleanup; 560 561 opts.addrs = addrs; 562 opts.cnt = cnt; 563 564 do_bench_test(skel, &opts); 565 566cleanup: 567 kprobe_multi_empty__destroy(skel); 568 free(addrs); 569} 570 571static void test_attach_override(void) 572{ 573 struct kprobe_multi_override *skel = NULL; 574 struct bpf_link *link = NULL; 575 576 skel = kprobe_multi_override__open_and_load(); 577 if (!ASSERT_OK_PTR(skel, "kprobe_multi_empty__open_and_load")) 578 goto cleanup; 579 580 /* The test_override calls bpf_override_return so it should fail 581 * to attach to bpf_fentry_test1 function, which is not on error 582 * injection list. 583 */ 584 link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_override, 585 "bpf_fentry_test1", NULL); 586 if (!ASSERT_ERR_PTR(link, "override_attached_bpf_fentry_test1")) { 587 bpf_link__destroy(link); 588 goto cleanup; 589 } 590 591 /* The should_fail_bio function is on error injection list, 592 * attach should succeed. 593 */ 594 link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_override, 595 "should_fail_bio", NULL); 596 if (!ASSERT_OK_PTR(link, "override_attached_should_fail_bio")) 597 goto cleanup; 598 599 bpf_link__destroy(link); 600 601cleanup: 602 kprobe_multi_override__destroy(skel); 603} 604 605static void test_override(void) 606{ 607 struct kprobe_multi_override *skel = NULL; 608 int err; 609 610 skel = kprobe_multi_override__open_and_load(); 611 if (!ASSERT_OK_PTR(skel, "kprobe_multi_empty__open_and_load")) 612 goto cleanup; 613 614 skel->bss->pid = getpid(); 615 616 /* no override */ 617 err = prctl(0xffff, 0); 618 ASSERT_EQ(err, -1, "err"); 619 620 /* kprobe.multi override */ 621 skel->links.test_override = bpf_program__attach_kprobe_multi_opts(skel->progs.test_override, 622 SYS_PREFIX "sys_prctl", NULL); 623 if (!ASSERT_OK_PTR(skel->links.test_override, "bpf_program__attach_kprobe_multi_opts")) 624 goto cleanup; 625 626 err = prctl(0xffff, 0); 627 ASSERT_EQ(err, 123, "err"); 628 629 bpf_link__destroy(skel->links.test_override); 630 skel->links.test_override = NULL; 631 632 /* kprobe override */ 633 skel->links.test_kprobe_override = bpf_program__attach_kprobe(skel->progs.test_kprobe_override, 634 false, SYS_PREFIX "sys_prctl"); 635 if (!ASSERT_OK_PTR(skel->links.test_kprobe_override, "bpf_program__attach_kprobe")) 636 goto cleanup; 637 638 err = prctl(0xffff, 0); 639 ASSERT_EQ(err, 123, "err"); 640 641cleanup: 642 kprobe_multi_override__destroy(skel); 643} 644 645#ifdef __x86_64__ 646static void test_attach_write_ctx(void) 647{ 648 struct kprobe_write_ctx *skel = NULL; 649 struct bpf_link *link = NULL; 650 651 skel = kprobe_write_ctx__open_and_load(); 652 if (!ASSERT_OK_PTR(skel, "kprobe_write_ctx__open_and_load")) 653 return; 654 655 link = bpf_program__attach_kprobe_opts(skel->progs.kprobe_multi_write_ctx, 656 "bpf_fentry_test1", NULL); 657 if (!ASSERT_ERR_PTR(link, "bpf_program__attach_kprobe_opts")) 658 bpf_link__destroy(link); 659 660 kprobe_write_ctx__destroy(skel); 661} 662#else 663static void test_attach_write_ctx(void) 664{ 665 test__skip(); 666} 667#endif 668 669/* 670 * Test kprobe_multi handles shadow symbols (vmlinux + module duplicate). 671 * bpf_fentry_shadow_test exists in both vmlinux and bpf_testmod. 672 * kprobe_multi resolves via ftrace_lookup_symbols() which finds the 673 * vmlinux symbol first and stops, so this should always succeed. 674 */ 675static void test_attach_probe_dup_sym(void) 676{ 677 LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); 678 const char *syms[1] = { "bpf_fentry_shadow_test" }; 679 struct kprobe_multi *skel = NULL; 680 struct bpf_link *link1 = NULL, *link2 = NULL; 681 682 skel = kprobe_multi__open_and_load(); 683 if (!ASSERT_OK_PTR(skel, "kprobe_multi__open_and_load")) 684 goto cleanup; 685 686 skel->bss->pid = getpid(); 687 opts.syms = syms; 688 opts.cnt = ARRAY_SIZE(syms); 689 690 link1 = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual, 691 NULL, &opts); 692 if (!ASSERT_OK_PTR(link1, "attach_kprobe_multi_dup_sym")) 693 goto cleanup; 694 695 opts.retprobe = true; 696 link2 = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kretprobe_manual, 697 NULL, &opts); 698 if (!ASSERT_OK_PTR(link2, "attach_kretprobe_multi_dup_sym")) 699 goto cleanup; 700 701cleanup: 702 bpf_link__destroy(link2); 703 bpf_link__destroy(link1); 704 kprobe_multi__destroy(skel); 705} 706 707void serial_test_kprobe_multi_bench_attach(void) 708{ 709 if (test__start_subtest("kernel")) 710 test_kprobe_multi_bench_attach(true); 711 if (test__start_subtest("modules")) 712 test_kprobe_multi_bench_attach(false); 713 if (test__start_subtest("kernel")) 714 test_kprobe_multi_bench_attach_addr(true); 715 if (test__start_subtest("modules")) 716 test_kprobe_multi_bench_attach_addr(false); 717} 718 719void test_kprobe_multi_test(void) 720{ 721 if (!ASSERT_OK(load_kallsyms(), "load_kallsyms")) 722 return; 723 724 if (test__start_subtest("skel_api")) 725 test_skel_api(); 726 if (test__start_subtest("link_api_addrs")) 727 test_link_api_syms(); 728 if (test__start_subtest("link_api_syms")) 729 test_link_api_addrs(); 730 if (test__start_subtest("attach_api_pattern")) 731 test_attach_api_pattern(); 732 if (test__start_subtest("attach_api_addrs")) 733 test_attach_api_addrs(); 734 if (test__start_subtest("attach_api_syms")) 735 test_attach_api_syms(); 736 if (test__start_subtest("attach_api_fails")) 737 test_attach_api_fails(); 738 if (test__start_subtest("attach_override")) 739 test_attach_override(); 740 if (test__start_subtest("override")) 741 test_override(); 742 if (test__start_subtest("session")) 743 test_session_skel_api(); 744 if (test__start_subtest("session_cookie")) 745 test_session_cookie_skel_api(); 746 if (test__start_subtest("unique_match")) 747 test_unique_match(); 748 if (test__start_subtest("attach_write_ctx")) 749 test_attach_write_ctx(); 750 if (test__start_subtest("dup_sym")) 751 test_attach_probe_dup_sym(); 752 RUN_TESTS(kprobe_multi_verifier); 753}