1 // SPDX-License-Identifier: GPL-2.0 2 #include <test_progs.h> 3 #include "kprobe_multi.skel.h" 4 #include "trace_helpers.h" 5 #include "kprobe_multi_empty.skel.h" 6 #include "kprobe_multi_override.skel.h" 7 #include "kprobe_multi_session.skel.h" 8 #include "kprobe_multi_session_cookie.skel.h" 9 #include "kprobe_multi_verifier.skel.h" 10 #include "kprobe_write_ctx.skel.h" 11 #include "bpf/libbpf_internal.h" 12 #include "bpf/hashmap.h" 13 14 static void kprobe_multi_test_run(struct kprobe_multi *skel, bool test_return) 15 { 16 LIBBPF_OPTS(bpf_test_run_opts, topts); 17 int err, prog_fd; 18 19 prog_fd = bpf_program__fd(skel->progs.trigger); 20 err = bpf_prog_test_run_opts(prog_fd, &topts); 21 ASSERT_OK(err, "test_run"); 22 ASSERT_EQ(topts.retval, 0, "test_run"); 23 24 ASSERT_EQ(skel->bss->kprobe_test1_result, 1, "kprobe_test1_result"); 25 ASSERT_EQ(skel->bss->kprobe_test2_result, 1, "kprobe_test2_result"); 26 ASSERT_EQ(skel->bss->kprobe_test3_result, 1, "kprobe_test3_result"); 27 ASSERT_EQ(skel->bss->kprobe_test4_result, 1, "kprobe_test4_result"); 28 ASSERT_EQ(skel->bss->kprobe_test5_result, 1, "kprobe_test5_result"); 29 ASSERT_EQ(skel->bss->kprobe_test6_result, 1, "kprobe_test6_result"); 30 ASSERT_EQ(skel->bss->kprobe_test7_result, 1, "kprobe_test7_result"); 31 ASSERT_EQ(skel->bss->kprobe_test8_result, 1, "kprobe_test8_result"); 32 33 if (test_return) { 34 ASSERT_EQ(skel->bss->kretprobe_test1_result, 1, "kretprobe_test1_result"); 35 ASSERT_EQ(skel->bss->kretprobe_test2_result, 1, "kretprobe_test2_result"); 36 ASSERT_EQ(skel->bss->kretprobe_test3_result, 1, "kretprobe_test3_result"); 37 ASSERT_EQ(skel->bss->kretprobe_test4_result, 1, "kretprobe_test4_result"); 38 ASSERT_EQ(skel->bss->kretprobe_test5_result, 1, "kretprobe_test5_result"); 39 ASSERT_EQ(skel->bss->kretprobe_test6_result, 1, "kretprobe_test6_result"); 40 ASSERT_EQ(skel->bss->kretprobe_test7_result, 1, "kretprobe_test7_result"); 41 ASSERT_EQ(skel->bss->kretprobe_test8_result, 1, "kretprobe_test8_result"); 42 } 43 } 44 45 static void test_skel_api(void) 46 { 47 struct kprobe_multi *skel = NULL; 48 int err; 49 50 skel = kprobe_multi__open_and_load(); 51 if (!ASSERT_OK_PTR(skel, "kprobe_multi__open_and_load")) 52 goto cleanup; 53 54 skel->bss->pid = getpid(); 55 err = kprobe_multi__attach(skel); 56 if (!ASSERT_OK(err, "kprobe_multi__attach")) 57 goto cleanup; 58 59 kprobe_multi_test_run(skel, true); 60 61 cleanup: 62 kprobe_multi__destroy(skel); 63 } 64 65 static void test_link_api(struct bpf_link_create_opts *opts) 66 { 67 int prog_fd, link1_fd = -1, link2_fd = -1; 68 struct kprobe_multi *skel = NULL; 69 70 skel = kprobe_multi__open_and_load(); 71 if (!ASSERT_OK_PTR(skel, "fentry_raw_skel_load")) 72 goto cleanup; 73 74 skel->bss->pid = getpid(); 75 prog_fd = bpf_program__fd(skel->progs.test_kprobe); 76 link1_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_KPROBE_MULTI, opts); 77 if (!ASSERT_GE(link1_fd, 0, "link_fd")) 78 goto cleanup; 79 80 opts->kprobe_multi.flags = BPF_F_KPROBE_MULTI_RETURN; 81 prog_fd = bpf_program__fd(skel->progs.test_kretprobe); 82 link2_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_KPROBE_MULTI, opts); 83 if (!ASSERT_GE(link2_fd, 0, "link_fd")) 84 goto cleanup; 85 86 kprobe_multi_test_run(skel, true); 87 88 cleanup: 89 if (link1_fd != -1) 90 close(link1_fd); 91 if (link2_fd != -1) 92 close(link2_fd); 93 kprobe_multi__destroy(skel); 94 } 95 96 #define GET_ADDR(__sym, __addr) ({ \ 97 __addr = ksym_get_addr(__sym); \ 98 if (!ASSERT_NEQ(__addr, 0, "kallsyms load failed for " #__sym)) \ 99 return; \ 100 }) 101 102 static void test_link_api_addrs(void) 103 { 104 LIBBPF_OPTS(bpf_link_create_opts, opts); 105 unsigned long long addrs[8]; 106 107 GET_ADDR("bpf_fentry_test1", addrs[0]); 108 GET_ADDR("bpf_fentry_test2", addrs[1]); 109 GET_ADDR("bpf_fentry_test3", addrs[2]); 110 GET_ADDR("bpf_fentry_test4", addrs[3]); 111 GET_ADDR("bpf_fentry_test5", addrs[4]); 112 GET_ADDR("bpf_fentry_test6", addrs[5]); 113 GET_ADDR("bpf_fentry_test7", addrs[6]); 114 GET_ADDR("bpf_fentry_test8", addrs[7]); 115 116 opts.kprobe_multi.addrs = (const unsigned long*) addrs; 117 opts.kprobe_multi.cnt = ARRAY_SIZE(addrs); 118 test_link_api(&opts); 119 } 120 121 static void test_link_api_syms(void) 122 { 123 LIBBPF_OPTS(bpf_link_create_opts, opts); 124 const char *syms[8] = { 125 "bpf_fentry_test1", 126 "bpf_fentry_test2", 127 "bpf_fentry_test3", 128 "bpf_fentry_test4", 129 "bpf_fentry_test5", 130 "bpf_fentry_test6", 131 "bpf_fentry_test7", 132 "bpf_fentry_test8", 133 }; 134 135 opts.kprobe_multi.syms = syms; 136 opts.kprobe_multi.cnt = ARRAY_SIZE(syms); 137 test_link_api(&opts); 138 } 139 140 static void 141 test_attach_api(const char *pattern, struct bpf_kprobe_multi_opts *opts) 142 { 143 struct bpf_link *link1 = NULL, *link2 = NULL; 144 struct kprobe_multi *skel = NULL; 145 146 skel = kprobe_multi__open_and_load(); 147 if (!ASSERT_OK_PTR(skel, "fentry_raw_skel_load")) 148 goto cleanup; 149 150 skel->bss->pid = getpid(); 151 link1 = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual, 152 pattern, opts); 153 if (!ASSERT_OK_PTR(link1, "bpf_program__attach_kprobe_multi_opts")) 154 goto cleanup; 155 156 if (opts) { 157 opts->retprobe = true; 158 link2 = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kretprobe_manual, 159 pattern, opts); 160 if (!ASSERT_OK_PTR(link2, "bpf_program__attach_kprobe_multi_opts")) 161 goto cleanup; 162 } 163 164 kprobe_multi_test_run(skel, !!opts); 165 166 cleanup: 167 bpf_link__destroy(link2); 168 bpf_link__destroy(link1); 169 kprobe_multi__destroy(skel); 170 } 171 172 static void test_attach_api_pattern(void) 173 { 174 LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); 175 176 test_attach_api("bpf_fentry_test*", &opts); 177 test_attach_api("bpf_fentry_test?", NULL); 178 } 179 180 static void test_attach_api_addrs(void) 181 { 182 LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); 183 unsigned long long addrs[8]; 184 185 GET_ADDR("bpf_fentry_test1", addrs[0]); 186 GET_ADDR("bpf_fentry_test2", addrs[1]); 187 GET_ADDR("bpf_fentry_test3", addrs[2]); 188 GET_ADDR("bpf_fentry_test4", addrs[3]); 189 GET_ADDR("bpf_fentry_test5", addrs[4]); 190 GET_ADDR("bpf_fentry_test6", addrs[5]); 191 GET_ADDR("bpf_fentry_test7", addrs[6]); 192 GET_ADDR("bpf_fentry_test8", addrs[7]); 193 194 opts.addrs = (const unsigned long *) addrs; 195 opts.cnt = ARRAY_SIZE(addrs); 196 test_attach_api(NULL, &opts); 197 } 198 199 static void test_attach_api_syms(void) 200 { 201 LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); 202 const char *syms[8] = { 203 "bpf_fentry_test1", 204 "bpf_fentry_test2", 205 "bpf_fentry_test3", 206 "bpf_fentry_test4", 207 "bpf_fentry_test5", 208 "bpf_fentry_test6", 209 "bpf_fentry_test7", 210 "bpf_fentry_test8", 211 }; 212 213 opts.syms = syms; 214 opts.cnt = ARRAY_SIZE(syms); 215 test_attach_api(NULL, &opts); 216 } 217 218 static void test_attach_api_fails(void) 219 { 220 LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); 221 struct kprobe_multi *skel = NULL; 222 struct bpf_link *link = NULL; 223 unsigned long long addrs[2]; 224 const char *syms[2] = { 225 "bpf_fentry_test1", 226 "bpf_fentry_test2", 227 }; 228 __u64 cookies[2]; 229 int saved_error; 230 231 addrs[0] = ksym_get_addr("bpf_fentry_test1"); 232 addrs[1] = ksym_get_addr("bpf_fentry_test2"); 233 234 if (!ASSERT_FALSE(!addrs[0] || !addrs[1], "ksym_get_addr")) 235 goto cleanup; 236 237 skel = kprobe_multi__open_and_load(); 238 if (!ASSERT_OK_PTR(skel, "fentry_raw_skel_load")) 239 goto cleanup; 240 241 skel->bss->pid = getpid(); 242 243 /* fail_1 - pattern and opts NULL */ 244 link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual, 245 NULL, NULL); 246 saved_error = -errno; 247 if (!ASSERT_ERR_PTR(link, "fail_1")) 248 goto cleanup; 249 250 if (!ASSERT_EQ(saved_error, -EINVAL, "fail_1_error")) 251 goto cleanup; 252 253 /* fail_2 - both addrs and syms set */ 254 opts.addrs = (const unsigned long *) addrs; 255 opts.syms = syms; 256 opts.cnt = ARRAY_SIZE(syms); 257 opts.cookies = NULL; 258 259 link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual, 260 NULL, &opts); 261 saved_error = -errno; 262 if (!ASSERT_ERR_PTR(link, "fail_2")) 263 goto cleanup; 264 265 if (!ASSERT_EQ(saved_error, -EINVAL, "fail_2_error")) 266 goto cleanup; 267 268 /* fail_3 - pattern and addrs set */ 269 opts.addrs = (const unsigned long *) addrs; 270 opts.syms = NULL; 271 opts.cnt = ARRAY_SIZE(syms); 272 opts.cookies = NULL; 273 274 link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual, 275 "ksys_*", &opts); 276 saved_error = -errno; 277 if (!ASSERT_ERR_PTR(link, "fail_3")) 278 goto cleanup; 279 280 if (!ASSERT_EQ(saved_error, -EINVAL, "fail_3_error")) 281 goto cleanup; 282 283 /* fail_4 - pattern and cnt set */ 284 opts.addrs = NULL; 285 opts.syms = NULL; 286 opts.cnt = ARRAY_SIZE(syms); 287 opts.cookies = NULL; 288 289 link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual, 290 "ksys_*", &opts); 291 saved_error = -errno; 292 if (!ASSERT_ERR_PTR(link, "fail_4")) 293 goto cleanup; 294 295 if (!ASSERT_EQ(saved_error, -EINVAL, "fail_4_error")) 296 goto cleanup; 297 298 /* fail_5 - pattern and cookies */ 299 opts.addrs = NULL; 300 opts.syms = NULL; 301 opts.cnt = 0; 302 opts.cookies = cookies; 303 304 link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual, 305 "ksys_*", &opts); 306 saved_error = -errno; 307 if (!ASSERT_ERR_PTR(link, "fail_5")) 308 goto cleanup; 309 310 if (!ASSERT_EQ(saved_error, -EINVAL, "fail_5_error")) 311 goto cleanup; 312 313 /* fail_6 - abnormal cnt */ 314 opts.addrs = (const unsigned long *) addrs; 315 opts.syms = NULL; 316 opts.cnt = INT_MAX; 317 opts.cookies = NULL; 318 319 link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual, 320 NULL, &opts); 321 saved_error = -errno; 322 if (!ASSERT_ERR_PTR(link, "fail_6")) 323 goto cleanup; 324 325 if (!ASSERT_EQ(saved_error, -E2BIG, "fail_6_error")) 326 goto cleanup; 327 328 cleanup: 329 bpf_link__destroy(link); 330 kprobe_multi__destroy(skel); 331 } 332 333 static void test_session_skel_api(void) 334 { 335 struct kprobe_multi_session *skel = NULL; 336 LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); 337 LIBBPF_OPTS(bpf_test_run_opts, topts); 338 struct bpf_link *link = NULL; 339 int i, err, prog_fd; 340 341 skel = kprobe_multi_session__open_and_load(); 342 if (!ASSERT_OK_PTR(skel, "kprobe_multi_session__open_and_load")) 343 return; 344 345 skel->bss->pid = getpid(); 346 347 err = kprobe_multi_session__attach(skel); 348 if (!ASSERT_OK(err, " kprobe_multi_session__attach")) 349 goto cleanup; 350 351 prog_fd = bpf_program__fd(skel->progs.trigger); 352 err = bpf_prog_test_run_opts(prog_fd, &topts); 353 ASSERT_OK(err, "test_run"); 354 ASSERT_EQ(topts.retval, 0, "test_run"); 355 356 /* bpf_fentry_test1-4 trigger return probe, result is 2 */ 357 for (i = 0; i < 4; i++) 358 ASSERT_EQ(skel->bss->kprobe_session_result[i], 2, "kprobe_session_result"); 359 360 /* bpf_fentry_test5-8 trigger only entry probe, result is 1 */ 361 for (i = 4; i < 8; i++) 362 ASSERT_EQ(skel->bss->kprobe_session_result[i], 1, "kprobe_session_result"); 363 364 cleanup: 365 bpf_link__destroy(link); 366 kprobe_multi_session__destroy(skel); 367 } 368 369 static void test_session_cookie_skel_api(void) 370 { 371 struct kprobe_multi_session_cookie *skel = NULL; 372 LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); 373 LIBBPF_OPTS(bpf_test_run_opts, topts); 374 struct bpf_link *link = NULL; 375 int err, prog_fd; 376 377 skel = kprobe_multi_session_cookie__open_and_load(); 378 if (!ASSERT_OK_PTR(skel, "fentry_raw_skel_load")) 379 return; 380 381 skel->bss->pid = getpid(); 382 383 err = kprobe_multi_session_cookie__attach(skel); 384 if (!ASSERT_OK(err, " kprobe_multi_wrapper__attach")) 385 goto cleanup; 386 387 prog_fd = bpf_program__fd(skel->progs.trigger); 388 err = bpf_prog_test_run_opts(prog_fd, &topts); 389 ASSERT_OK(err, "test_run"); 390 ASSERT_EQ(topts.retval, 0, "test_run"); 391 392 ASSERT_EQ(skel->bss->test_kprobe_1_result, 1, "test_kprobe_1_result"); 393 ASSERT_EQ(skel->bss->test_kprobe_2_result, 2, "test_kprobe_2_result"); 394 ASSERT_EQ(skel->bss->test_kprobe_3_result, 3, "test_kprobe_3_result"); 395 396 cleanup: 397 bpf_link__destroy(link); 398 kprobe_multi_session_cookie__destroy(skel); 399 } 400 401 static void test_unique_match(void) 402 { 403 LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); 404 struct kprobe_multi *skel = NULL; 405 struct bpf_link *link = NULL; 406 407 skel = kprobe_multi__open_and_load(); 408 if (!ASSERT_OK_PTR(skel, "kprobe_multi__open_and_load")) 409 return; 410 411 opts.unique_match = true; 412 skel->bss->pid = getpid(); 413 link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual, 414 "bpf_fentry_test*", &opts); 415 if (!ASSERT_ERR_PTR(link, "bpf_program__attach_kprobe_multi_opts")) 416 bpf_link__destroy(link); 417 418 link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual, 419 "bpf_fentry_test8*", &opts); 420 if (ASSERT_OK_PTR(link, "bpf_program__attach_kprobe_multi_opts")) 421 bpf_link__destroy(link); 422 423 kprobe_multi__destroy(skel); 424 } 425 426 static void do_bench_test(struct kprobe_multi_empty *skel, struct bpf_kprobe_multi_opts *opts) 427 { 428 long attach_start_ns, attach_end_ns; 429 long detach_start_ns, detach_end_ns; 430 double attach_delta, detach_delta; 431 struct bpf_link *link = NULL; 432 433 attach_start_ns = get_time_ns(); 434 link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_empty, 435 NULL, opts); 436 attach_end_ns = get_time_ns(); 437 438 if (!ASSERT_OK_PTR(link, "bpf_program__attach_kprobe_multi_opts")) 439 return; 440 441 detach_start_ns = get_time_ns(); 442 bpf_link__destroy(link); 443 detach_end_ns = get_time_ns(); 444 445 attach_delta = (attach_end_ns - attach_start_ns) / 1000000000.0; 446 detach_delta = (detach_end_ns - detach_start_ns) / 1000000000.0; 447 448 printf("%s: found %lu functions\n", __func__, opts->cnt); 449 printf("%s: attached in %7.3lfs\n", __func__, attach_delta); 450 printf("%s: detached in %7.3lfs\n", __func__, detach_delta); 451 } 452 453 static void test_kprobe_multi_bench_attach(bool kernel) 454 { 455 LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); 456 struct kprobe_multi_empty *skel = NULL; 457 char **syms = NULL; 458 size_t cnt = 0; 459 460 if (!ASSERT_OK(bpf_get_ksyms(&syms, &cnt, kernel), "bpf_get_ksyms")) 461 return; 462 463 skel = kprobe_multi_empty__open_and_load(); 464 if (!ASSERT_OK_PTR(skel, "kprobe_multi_empty__open_and_load")) 465 goto cleanup; 466 467 opts.syms = (const char **) syms; 468 opts.cnt = cnt; 469 470 do_bench_test(skel, &opts); 471 472 cleanup: 473 kprobe_multi_empty__destroy(skel); 474 if (syms) 475 free(syms); 476 } 477 478 static void test_kprobe_multi_bench_attach_addr(bool kernel) 479 { 480 LIBBPF_OPTS(bpf_kprobe_multi_opts, opts); 481 struct kprobe_multi_empty *skel = NULL; 482 unsigned long *addrs = NULL; 483 size_t cnt = 0; 484 int err; 485 486 err = bpf_get_addrs(&addrs, &cnt, kernel); 487 if (err == -ENOENT) { 488 test__skip(); 489 return; 490 } 491 492 if (!ASSERT_OK(err, "bpf_get_addrs")) 493 return; 494 495 skel = kprobe_multi_empty__open_and_load(); 496 if (!ASSERT_OK_PTR(skel, "kprobe_multi_empty__open_and_load")) 497 goto cleanup; 498 499 opts.addrs = addrs; 500 opts.cnt = cnt; 501 502 do_bench_test(skel, &opts); 503 504 cleanup: 505 kprobe_multi_empty__destroy(skel); 506 free(addrs); 507 } 508 509 static void test_attach_override(void) 510 { 511 struct kprobe_multi_override *skel = NULL; 512 struct bpf_link *link = NULL; 513 514 skel = kprobe_multi_override__open_and_load(); 515 if (!ASSERT_OK_PTR(skel, "kprobe_multi_empty__open_and_load")) 516 goto cleanup; 517 518 /* The test_override calls bpf_override_return so it should fail 519 * to attach to bpf_fentry_test1 function, which is not on error 520 * injection list. 521 */ 522 link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_override, 523 "bpf_fentry_test1", NULL); 524 if (!ASSERT_ERR_PTR(link, "override_attached_bpf_fentry_test1")) { 525 bpf_link__destroy(link); 526 goto cleanup; 527 } 528 529 /* The should_fail_bio function is on error injection list, 530 * attach should succeed. 531 */ 532 link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_override, 533 "should_fail_bio", NULL); 534 if (!ASSERT_OK_PTR(link, "override_attached_should_fail_bio")) 535 goto cleanup; 536 537 bpf_link__destroy(link); 538 539 cleanup: 540 kprobe_multi_override__destroy(skel); 541 } 542 543 #ifdef __x86_64__ 544 static void test_attach_write_ctx(void) 545 { 546 struct kprobe_write_ctx *skel = NULL; 547 struct bpf_link *link = NULL; 548 549 skel = kprobe_write_ctx__open_and_load(); 550 if (!ASSERT_OK_PTR(skel, "kprobe_write_ctx__open_and_load")) 551 return; 552 553 link = bpf_program__attach_kprobe_opts(skel->progs.kprobe_multi_write_ctx, 554 "bpf_fentry_test1", NULL); 555 if (!ASSERT_ERR_PTR(link, "bpf_program__attach_kprobe_opts")) 556 bpf_link__destroy(link); 557 558 kprobe_write_ctx__destroy(skel); 559 } 560 #else 561 static void test_attach_write_ctx(void) 562 { 563 test__skip(); 564 } 565 #endif 566 567 void serial_test_kprobe_multi_bench_attach(void) 568 { 569 if (test__start_subtest("kernel")) 570 test_kprobe_multi_bench_attach(true); 571 if (test__start_subtest("modules")) 572 test_kprobe_multi_bench_attach(false); 573 if (test__start_subtest("kernel")) 574 test_kprobe_multi_bench_attach_addr(true); 575 if (test__start_subtest("modules")) 576 test_kprobe_multi_bench_attach_addr(false); 577 } 578 579 void test_kprobe_multi_test(void) 580 { 581 if (!ASSERT_OK(load_kallsyms(), "load_kallsyms")) 582 return; 583 584 if (test__start_subtest("skel_api")) 585 test_skel_api(); 586 if (test__start_subtest("link_api_addrs")) 587 test_link_api_syms(); 588 if (test__start_subtest("link_api_syms")) 589 test_link_api_addrs(); 590 if (test__start_subtest("attach_api_pattern")) 591 test_attach_api_pattern(); 592 if (test__start_subtest("attach_api_addrs")) 593 test_attach_api_addrs(); 594 if (test__start_subtest("attach_api_syms")) 595 test_attach_api_syms(); 596 if (test__start_subtest("attach_api_fails")) 597 test_attach_api_fails(); 598 if (test__start_subtest("attach_override")) 599 test_attach_override(); 600 if (test__start_subtest("session")) 601 test_session_skel_api(); 602 if (test__start_subtest("session_cookie")) 603 test_session_cookie_skel_api(); 604 if (test__start_subtest("unique_match")) 605 test_unique_match(); 606 if (test__start_subtest("attach_write_ctx")) 607 test_attach_write_ctx(); 608 RUN_TESTS(kprobe_multi_verifier); 609 } 610