| 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | /* Copyright (c) 2019 Facebook */ |
| 3 | #include <test_progs.h> |
| 4 | #include <network_helpers.h> |
| 5 | #include <bpf/btf.h> |
| 6 | #include "bind4_prog.skel.h" |
| 7 | |
| 8 | typedef int (*test_cb)(struct bpf_object *obj); |
| 9 | |
| 10 | static int check_data_map(struct bpf_object *obj, int prog_cnt, bool reset) |
| 11 | { |
| 12 | struct bpf_map *data_map = NULL, *map; |
| 13 | __u64 *result = NULL; |
| 14 | const int zero = 0; |
| 15 | __u32 duration = 0; |
| 16 | int ret = -1, i; |
| 17 | |
| 18 | result = malloc((prog_cnt + 32 /* spare */) * sizeof(__u64)); |
| 19 | if (CHECK(!result, "alloc_memory", "failed to alloc memory")) |
| 20 | return -ENOMEM; |
| 21 | |
| 22 | bpf_object__for_each_map(map, obj) |
| 23 | if (bpf_map__is_internal(map)) { |
| 24 | data_map = map; |
| 25 | break; |
| 26 | } |
| 27 | if (CHECK(!data_map, "find_data_map", "data map not found\n")) |
| 28 | goto out; |
| 29 | |
| 30 | ret = bpf_map_lookup_elem(bpf_map__fd(data_map), &zero, result); |
| 31 | if (CHECK(ret, "get_result", |
| 32 | "failed to get output data: %d\n", ret)) |
| 33 | goto out; |
| 34 | |
| 35 | for (i = 0; i < prog_cnt; i++) { |
| 36 | if (CHECK(result[i] != 1, "result", |
| 37 | "fexit_bpf2bpf result[%d] failed err %llu\n", |
| 38 | i, result[i])) |
| 39 | goto out; |
| 40 | result[i] = 0; |
| 41 | } |
| 42 | if (reset) { |
| 43 | ret = bpf_map_update_elem(bpf_map__fd(data_map), &zero, result, 0); |
| 44 | if (CHECK(ret, "reset_result", "failed to reset result\n")) |
| 45 | goto out; |
| 46 | } |
| 47 | |
| 48 | ret = 0; |
| 49 | out: |
| 50 | free(result); |
| 51 | return ret; |
| 52 | } |
| 53 | |
| 54 | static void test_fexit_bpf2bpf_common(const char *obj_file, |
| 55 | const char *target_obj_file, |
| 56 | int prog_cnt, |
| 57 | const char **prog_name, |
| 58 | bool run_prog, |
| 59 | test_cb cb) |
| 60 | { |
| 61 | struct bpf_object *obj = NULL, *tgt_obj; |
| 62 | __u32 tgt_prog_id, info_len; |
| 63 | struct bpf_prog_info prog_info = {}; |
| 64 | struct bpf_program **prog = NULL, *p; |
| 65 | struct bpf_link **link = NULL; |
| 66 | int err, tgt_fd, i; |
| 67 | struct btf *btf; |
| 68 | LIBBPF_OPTS(bpf_test_run_opts, topts, |
| 69 | .data_in = &pkt_v6, |
| 70 | .data_size_in = sizeof(pkt_v6), |
| 71 | .repeat = 1, |
| 72 | ); |
| 73 | |
| 74 | err = bpf_prog_test_load(target_obj_file, BPF_PROG_TYPE_UNSPEC, |
| 75 | &tgt_obj, &tgt_fd); |
| 76 | if (!ASSERT_OK(err, "tgt_prog_load")) |
| 77 | return; |
| 78 | |
| 79 | info_len = sizeof(prog_info); |
| 80 | err = bpf_obj_get_info_by_fd(tgt_fd, &prog_info, &info_len); |
| 81 | if (!ASSERT_OK(err, "tgt_fd_get_info")) |
| 82 | goto close_prog; |
| 83 | |
| 84 | tgt_prog_id = prog_info.id; |
| 85 | btf = bpf_object__btf(tgt_obj); |
| 86 | |
| 87 | link = calloc(sizeof(struct bpf_link *), prog_cnt); |
| 88 | if (!ASSERT_OK_PTR(link, "link_ptr")) |
| 89 | goto close_prog; |
| 90 | |
| 91 | prog = calloc(sizeof(struct bpf_program *), prog_cnt); |
| 92 | if (!ASSERT_OK_PTR(prog, "prog_ptr")) |
| 93 | goto close_prog; |
| 94 | |
| 95 | obj = bpf_object__open_file(obj_file, NULL); |
| 96 | if (!ASSERT_OK_PTR(obj, "obj_open")) |
| 97 | goto close_prog; |
| 98 | |
| 99 | bpf_object__for_each_program(p, obj) { |
| 100 | err = bpf_program__set_attach_target(p, tgt_fd, NULL); |
| 101 | ASSERT_OK(err, "set_attach_target"); |
| 102 | } |
| 103 | |
| 104 | err = bpf_object__load(obj); |
| 105 | if (!ASSERT_OK(err, "obj_load")) |
| 106 | goto close_prog; |
| 107 | |
| 108 | for (i = 0; i < prog_cnt; i++) { |
| 109 | struct bpf_link_info link_info; |
| 110 | struct bpf_program *pos; |
| 111 | const char *pos_sec_name; |
| 112 | char *tgt_name; |
| 113 | __s32 btf_id; |
| 114 | |
| 115 | tgt_name = strstr(prog_name[i], "/"); |
| 116 | if (!ASSERT_OK_PTR(tgt_name, "tgt_name")) |
| 117 | goto close_prog; |
| 118 | btf_id = btf__find_by_name_kind(btf, tgt_name + 1, BTF_KIND_FUNC); |
| 119 | |
| 120 | prog[i] = NULL; |
| 121 | bpf_object__for_each_program(pos, obj) { |
| 122 | pos_sec_name = bpf_program__section_name(pos); |
| 123 | if (pos_sec_name && !strcmp(pos_sec_name, prog_name[i])) { |
| 124 | prog[i] = pos; |
| 125 | break; |
| 126 | } |
| 127 | } |
| 128 | if (!ASSERT_OK_PTR(prog[i], prog_name[i])) |
| 129 | goto close_prog; |
| 130 | |
| 131 | link[i] = bpf_program__attach_trace(prog[i]); |
| 132 | if (!ASSERT_OK_PTR(link[i], "attach_trace")) |
| 133 | goto close_prog; |
| 134 | |
| 135 | info_len = sizeof(link_info); |
| 136 | memset(&link_info, 0, sizeof(link_info)); |
| 137 | err = bpf_obj_get_info_by_fd(bpf_link__fd(link[i]), |
| 138 | &link_info, &info_len); |
| 139 | ASSERT_OK(err, "link_fd_get_info"); |
| 140 | ASSERT_EQ(link_info.tracing.attach_type, |
| 141 | bpf_program__expected_attach_type(prog[i]), |
| 142 | "link_attach_type"); |
| 143 | ASSERT_EQ(link_info.tracing.target_obj_id, tgt_prog_id, "link_tgt_obj_id"); |
| 144 | ASSERT_EQ(link_info.tracing.target_btf_id, btf_id, "link_tgt_btf_id"); |
| 145 | } |
| 146 | |
| 147 | if (cb) { |
| 148 | err = cb(obj); |
| 149 | if (err) |
| 150 | goto close_prog; |
| 151 | } |
| 152 | |
| 153 | if (!run_prog) |
| 154 | goto close_prog; |
| 155 | |
| 156 | err = bpf_prog_test_run_opts(tgt_fd, &topts); |
| 157 | ASSERT_OK(err, "prog_run"); |
| 158 | ASSERT_EQ(topts.retval, 0, "prog_run_ret"); |
| 159 | |
| 160 | if (check_data_map(obj, prog_cnt, false)) |
| 161 | goto close_prog; |
| 162 | |
| 163 | close_prog: |
| 164 | for (i = 0; i < prog_cnt; i++) |
| 165 | bpf_link__destroy(link[i]); |
| 166 | bpf_object__close(obj); |
| 167 | bpf_object__close(tgt_obj); |
| 168 | free(link); |
| 169 | free(prog); |
| 170 | } |
| 171 | |
| 172 | static void test_target_no_callees(void) |
| 173 | { |
| 174 | const char *prog_name[] = { |
| 175 | "fexit/test_pkt_md_access", |
| 176 | }; |
| 177 | test_fexit_bpf2bpf_common("./fexit_bpf2bpf_simple.bpf.o", |
| 178 | "./test_pkt_md_access.bpf.o", |
| 179 | ARRAY_SIZE(prog_name), |
| 180 | prog_name, true, NULL); |
| 181 | } |
| 182 | |
| 183 | static void test_target_yes_callees(void) |
| 184 | { |
| 185 | const char *prog_name[] = { |
| 186 | "fexit/test_pkt_access", |
| 187 | "fexit/test_pkt_access_subprog1", |
| 188 | "fexit/test_pkt_access_subprog2", |
| 189 | "fexit/test_pkt_access_subprog3", |
| 190 | }; |
| 191 | test_fexit_bpf2bpf_common("./fexit_bpf2bpf.bpf.o", |
| 192 | "./test_pkt_access.bpf.o", |
| 193 | ARRAY_SIZE(prog_name), |
| 194 | prog_name, true, NULL); |
| 195 | } |
| 196 | |
| 197 | static void test_func_replace(void) |
| 198 | { |
| 199 | const char *prog_name[] = { |
| 200 | "fexit/test_pkt_access", |
| 201 | "fexit/test_pkt_access_subprog1", |
| 202 | "fexit/test_pkt_access_subprog2", |
| 203 | "fexit/test_pkt_access_subprog3", |
| 204 | "freplace/get_skb_len", |
| 205 | "freplace/get_skb_ifindex", |
| 206 | "freplace/get_constant", |
| 207 | "freplace/test_pkt_write_access_subprog", |
| 208 | }; |
| 209 | test_fexit_bpf2bpf_common("./fexit_bpf2bpf.bpf.o", |
| 210 | "./test_pkt_access.bpf.o", |
| 211 | ARRAY_SIZE(prog_name), |
| 212 | prog_name, true, NULL); |
| 213 | } |
| 214 | |
| 215 | static void test_func_replace_verify(void) |
| 216 | { |
| 217 | const char *prog_name[] = { |
| 218 | "freplace/do_bind", |
| 219 | }; |
| 220 | test_fexit_bpf2bpf_common("./freplace_connect4.bpf.o", |
| 221 | "./connect4_prog.bpf.o", |
| 222 | ARRAY_SIZE(prog_name), |
| 223 | prog_name, false, NULL); |
| 224 | } |
| 225 | |
| 226 | static int test_second_attach(struct bpf_object *obj) |
| 227 | { |
| 228 | const char *prog_name = "security_new_get_constant"; |
| 229 | const char *tgt_name = "get_constant"; |
| 230 | const char *tgt_obj_file = "./test_pkt_access.bpf.o"; |
| 231 | struct bpf_program *prog = NULL; |
| 232 | struct bpf_object *tgt_obj; |
| 233 | struct bpf_link *link; |
| 234 | int err = 0, tgt_fd; |
| 235 | LIBBPF_OPTS(bpf_test_run_opts, topts, |
| 236 | .data_in = &pkt_v6, |
| 237 | .data_size_in = sizeof(pkt_v6), |
| 238 | .repeat = 1, |
| 239 | ); |
| 240 | |
| 241 | prog = bpf_object__find_program_by_name(obj, prog_name); |
| 242 | if (!ASSERT_OK_PTR(prog, "find_prog")) |
| 243 | return -ENOENT; |
| 244 | |
| 245 | err = bpf_prog_test_load(tgt_obj_file, BPF_PROG_TYPE_UNSPEC, |
| 246 | &tgt_obj, &tgt_fd); |
| 247 | if (!ASSERT_OK(err, "second_prog_load")) |
| 248 | return err; |
| 249 | |
| 250 | link = bpf_program__attach_freplace(prog, tgt_fd, tgt_name); |
| 251 | if (!ASSERT_OK_PTR(link, "second_link")) |
| 252 | goto out; |
| 253 | |
| 254 | err = bpf_prog_test_run_opts(tgt_fd, &topts); |
| 255 | if (!ASSERT_OK(err, "ipv6 test_run")) |
| 256 | goto out; |
| 257 | if (!ASSERT_OK(topts.retval, "ipv6 retval")) |
| 258 | goto out; |
| 259 | |
| 260 | err = check_data_map(obj, 1, true); |
| 261 | if (err) |
| 262 | goto out; |
| 263 | |
| 264 | out: |
| 265 | bpf_link__destroy(link); |
| 266 | bpf_object__close(tgt_obj); |
| 267 | return err; |
| 268 | } |
| 269 | |
| 270 | static void test_func_replace_multi(void) |
| 271 | { |
| 272 | const char *prog_name[] = { |
| 273 | "freplace/get_constant", |
| 274 | }; |
| 275 | test_fexit_bpf2bpf_common("./freplace_get_constant.bpf.o", |
| 276 | "./test_pkt_access.bpf.o", |
| 277 | ARRAY_SIZE(prog_name), |
| 278 | prog_name, true, test_second_attach); |
| 279 | } |
| 280 | |
| 281 | static void test_fmod_ret_freplace(void) |
| 282 | { |
| 283 | struct bpf_object *freplace_obj = NULL, *pkt_obj, *fmod_obj = NULL; |
| 284 | const char *freplace_name = "./freplace_get_constant.bpf.o"; |
| 285 | const char *fmod_ret_name = "./fmod_ret_freplace.bpf.o"; |
| 286 | DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts); |
| 287 | const char *tgt_name = "./test_pkt_access.bpf.o"; |
| 288 | struct bpf_link *freplace_link = NULL; |
| 289 | struct bpf_program *prog; |
| 290 | __u32 duration = 0; |
| 291 | int err, pkt_fd, attach_prog_fd; |
| 292 | |
| 293 | err = bpf_prog_test_load(tgt_name, BPF_PROG_TYPE_UNSPEC, |
| 294 | &pkt_obj, &pkt_fd); |
| 295 | /* the target prog should load fine */ |
| 296 | if (CHECK(err, "tgt_prog_load", "file %s err %d errno %d\n", |
| 297 | tgt_name, err, errno)) |
| 298 | return; |
| 299 | |
| 300 | freplace_obj = bpf_object__open_file(freplace_name, NULL); |
| 301 | if (!ASSERT_OK_PTR(freplace_obj, "freplace_obj_open")) |
| 302 | goto out; |
| 303 | |
| 304 | prog = bpf_object__next_program(freplace_obj, NULL); |
| 305 | err = bpf_program__set_attach_target(prog, pkt_fd, NULL); |
| 306 | ASSERT_OK(err, "freplace__set_attach_target"); |
| 307 | |
| 308 | err = bpf_object__load(freplace_obj); |
| 309 | if (CHECK(err, "freplace_obj_load", "err %d\n", err)) |
| 310 | goto out; |
| 311 | |
| 312 | freplace_link = bpf_program__attach_trace(prog); |
| 313 | if (!ASSERT_OK_PTR(freplace_link, "freplace_attach_trace")) |
| 314 | goto out; |
| 315 | |
| 316 | fmod_obj = bpf_object__open_file(fmod_ret_name, NULL); |
| 317 | if (!ASSERT_OK_PTR(fmod_obj, "fmod_obj_open")) |
| 318 | goto out; |
| 319 | |
| 320 | attach_prog_fd = bpf_program__fd(prog); |
| 321 | prog = bpf_object__next_program(fmod_obj, NULL); |
| 322 | err = bpf_program__set_attach_target(prog, attach_prog_fd, NULL); |
| 323 | ASSERT_OK(err, "fmod_ret_set_attach_target"); |
| 324 | |
| 325 | err = bpf_object__load(fmod_obj); |
| 326 | if (CHECK(!err, "fmod_obj_load", "loading fmod_ret should fail\n")) |
| 327 | goto out; |
| 328 | |
| 329 | out: |
| 330 | bpf_link__destroy(freplace_link); |
| 331 | bpf_object__close(freplace_obj); |
| 332 | bpf_object__close(fmod_obj); |
| 333 | bpf_object__close(pkt_obj); |
| 334 | } |
| 335 | |
| 336 | |
| 337 | static void test_func_sockmap_update(void) |
| 338 | { |
| 339 | const char *prog_name[] = { |
| 340 | "freplace/cls_redirect", |
| 341 | }; |
| 342 | test_fexit_bpf2bpf_common("./freplace_cls_redirect.bpf.o", |
| 343 | "./test_cls_redirect.bpf.o", |
| 344 | ARRAY_SIZE(prog_name), |
| 345 | prog_name, false, NULL); |
| 346 | } |
| 347 | |
| 348 | static void test_obj_load_failure_common(const char *obj_file, |
| 349 | const char *target_obj_file) |
| 350 | { |
| 351 | /* |
| 352 | * standalone test that asserts failure to load freplace prog |
| 353 | * because of invalid return code. |
| 354 | */ |
| 355 | struct bpf_object *obj = NULL, *pkt_obj; |
| 356 | struct bpf_program *prog; |
| 357 | int err, pkt_fd; |
| 358 | __u32 duration = 0; |
| 359 | |
| 360 | err = bpf_prog_test_load(target_obj_file, BPF_PROG_TYPE_UNSPEC, |
| 361 | &pkt_obj, &pkt_fd); |
| 362 | /* the target prog should load fine */ |
| 363 | if (CHECK(err, "tgt_prog_load", "file %s err %d errno %d\n", |
| 364 | target_obj_file, err, errno)) |
| 365 | return; |
| 366 | |
| 367 | obj = bpf_object__open_file(obj_file, NULL); |
| 368 | if (!ASSERT_OK_PTR(obj, "obj_open")) |
| 369 | goto close_prog; |
| 370 | |
| 371 | prog = bpf_object__next_program(obj, NULL); |
| 372 | err = bpf_program__set_attach_target(prog, pkt_fd, NULL); |
| 373 | ASSERT_OK(err, "set_attach_target"); |
| 374 | |
| 375 | /* It should fail to load the program */ |
| 376 | err = bpf_object__load(obj); |
| 377 | if (CHECK(!err, "bpf_obj_load should fail", "err %d\n", err)) |
| 378 | goto close_prog; |
| 379 | |
| 380 | close_prog: |
| 381 | bpf_object__close(obj); |
| 382 | bpf_object__close(pkt_obj); |
| 383 | } |
| 384 | |
| 385 | static void test_func_replace_return_code(void) |
| 386 | { |
| 387 | /* test invalid return code in the replaced program */ |
| 388 | test_obj_load_failure_common("./freplace_connect_v4_prog.bpf.o", |
| 389 | "./connect4_prog.bpf.o"); |
| 390 | } |
| 391 | |
| 392 | static void test_func_map_prog_compatibility(void) |
| 393 | { |
| 394 | /* test with spin lock map value in the replaced program */ |
| 395 | test_obj_load_failure_common("./freplace_attach_probe.bpf.o", |
| 396 | "./test_attach_probe.bpf.o"); |
| 397 | } |
| 398 | |
| 399 | static void test_func_replace_global_func(void) |
| 400 | { |
| 401 | const char *prog_name[] = { |
| 402 | "freplace/test_pkt_access", |
| 403 | }; |
| 404 | |
| 405 | test_fexit_bpf2bpf_common("./freplace_global_func.bpf.o", |
| 406 | "./test_pkt_access.bpf.o", |
| 407 | ARRAY_SIZE(prog_name), |
| 408 | prog_name, false, NULL); |
| 409 | } |
| 410 | |
| 411 | static int find_prog_btf_id(const char *name, __u32 attach_prog_fd) |
| 412 | { |
| 413 | struct bpf_prog_info info = {}; |
| 414 | __u32 info_len = sizeof(info); |
| 415 | struct btf *btf; |
| 416 | int ret; |
| 417 | |
| 418 | ret = bpf_obj_get_info_by_fd(attach_prog_fd, &info, &info_len); |
| 419 | if (ret) |
| 420 | return ret; |
| 421 | |
| 422 | if (!info.btf_id) |
| 423 | return -EINVAL; |
| 424 | |
| 425 | btf = btf__load_from_kernel_by_id(info.btf_id); |
| 426 | ret = libbpf_get_error(btf); |
| 427 | if (ret) |
| 428 | return ret; |
| 429 | |
| 430 | ret = btf__find_by_name_kind(btf, name, BTF_KIND_FUNC); |
| 431 | btf__free(btf); |
| 432 | return ret; |
| 433 | } |
| 434 | |
| 435 | static int load_fentry(int attach_prog_fd, int attach_btf_id) |
| 436 | { |
| 437 | LIBBPF_OPTS(bpf_prog_load_opts, opts, |
| 438 | .expected_attach_type = BPF_TRACE_FENTRY, |
| 439 | .attach_prog_fd = attach_prog_fd, |
| 440 | .attach_btf_id = attach_btf_id, |
| 441 | ); |
| 442 | struct bpf_insn insns[] = { |
| 443 | BPF_MOV64_IMM(BPF_REG_0, 0), |
| 444 | BPF_EXIT_INSN(), |
| 445 | }; |
| 446 | |
| 447 | return bpf_prog_load(BPF_PROG_TYPE_TRACING, |
| 448 | "bind4_fentry", |
| 449 | "GPL", |
| 450 | insns, |
| 451 | ARRAY_SIZE(insns), |
| 452 | &opts); |
| 453 | } |
| 454 | |
| 455 | static void test_fentry_to_cgroup_bpf(void) |
| 456 | { |
| 457 | struct bind4_prog *skel = NULL; |
| 458 | struct bpf_prog_info info = {}; |
| 459 | __u32 info_len = sizeof(info); |
| 460 | int cgroup_fd = -1; |
| 461 | int fentry_fd = -1; |
| 462 | int btf_id; |
| 463 | |
| 464 | cgroup_fd = test__join_cgroup("/fentry_to_cgroup_bpf"); |
| 465 | if (!ASSERT_GE(cgroup_fd, 0, "cgroup_fd")) |
| 466 | return; |
| 467 | |
| 468 | skel = bind4_prog__open_and_load(); |
| 469 | if (!ASSERT_OK_PTR(skel, "skel")) |
| 470 | goto cleanup; |
| 471 | |
| 472 | skel->links.bind_v4_prog = bpf_program__attach_cgroup(skel->progs.bind_v4_prog, cgroup_fd); |
| 473 | if (!ASSERT_OK_PTR(skel->links.bind_v4_prog, "bpf_program__attach_cgroup")) |
| 474 | goto cleanup; |
| 475 | |
| 476 | btf_id = find_prog_btf_id("bind_v4_prog", bpf_program__fd(skel->progs.bind_v4_prog)); |
| 477 | if (!ASSERT_GE(btf_id, 0, "find_prog_btf_id")) |
| 478 | goto cleanup; |
| 479 | |
| 480 | fentry_fd = load_fentry(bpf_program__fd(skel->progs.bind_v4_prog), btf_id); |
| 481 | if (!ASSERT_GE(fentry_fd, 0, "load_fentry")) |
| 482 | goto cleanup; |
| 483 | |
| 484 | /* Make sure bpf_obj_get_info_by_fd works correctly when attaching |
| 485 | * to another BPF program. |
| 486 | */ |
| 487 | |
| 488 | ASSERT_OK(bpf_obj_get_info_by_fd(fentry_fd, &info, &info_len), |
| 489 | "bpf_obj_get_info_by_fd"); |
| 490 | |
| 491 | ASSERT_EQ(info.btf_id, 0, "info.btf_id"); |
| 492 | ASSERT_EQ(info.attach_btf_id, btf_id, "info.attach_btf_id"); |
| 493 | ASSERT_GT(info.attach_btf_obj_id, 0, "info.attach_btf_obj_id"); |
| 494 | |
| 495 | cleanup: |
| 496 | if (cgroup_fd >= 0) |
| 497 | close(cgroup_fd); |
| 498 | if (fentry_fd >= 0) |
| 499 | close(fentry_fd); |
| 500 | bind4_prog__destroy(skel); |
| 501 | } |
| 502 | |
| 503 | /* NOTE: affect other tests, must run in serial mode */ |
| 504 | void serial_test_fexit_bpf2bpf(void) |
| 505 | { |
| 506 | if (test__start_subtest("target_no_callees")) |
| 507 | test_target_no_callees(); |
| 508 | if (test__start_subtest("target_yes_callees")) |
| 509 | test_target_yes_callees(); |
| 510 | if (test__start_subtest("func_replace")) |
| 511 | test_func_replace(); |
| 512 | if (test__start_subtest("func_replace_verify")) |
| 513 | test_func_replace_verify(); |
| 514 | if (test__start_subtest("func_sockmap_update")) |
| 515 | test_func_sockmap_update(); |
| 516 | if (test__start_subtest("func_replace_return_code")) |
| 517 | test_func_replace_return_code(); |
| 518 | if (test__start_subtest("func_map_prog_compatibility")) |
| 519 | test_func_map_prog_compatibility(); |
| 520 | if (test__start_subtest("func_replace_multi")) |
| 521 | test_func_replace_multi(); |
| 522 | if (test__start_subtest("fmod_ret_freplace")) |
| 523 | test_fmod_ret_freplace(); |
| 524 | if (test__start_subtest("func_replace_global_func")) |
| 525 | test_func_replace_global_func(); |
| 526 | if (test__start_subtest("fentry_to_cgroup_bpf")) |
| 527 | test_fentry_to_cgroup_bpf(); |
| 528 | } |