1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2022 Red Hat */ 3 #include <test_progs.h> 4 #include <bpf/btf.h> 5 #include "bpf/libbpf_internal.h" 6 #include "cgroup_helpers.h" 7 8 static const char *module_name = "bpf_testmod"; 9 static const char *symbol_name = "bpf_fentry_shadow_test"; 10 11 static int get_bpf_testmod_btf_fd(void) 12 { 13 struct bpf_btf_info info; 14 char name[64]; 15 __u32 id = 0, len; 16 int err, fd; 17 18 while (true) { 19 err = bpf_btf_get_next_id(id, &id); 20 if (err) { 21 log_err("failed to iterate BTF objects"); 22 return err; 23 } 24 25 fd = bpf_btf_get_fd_by_id(id); 26 if (fd < 0) { 27 if (errno == ENOENT) 28 continue; /* expected race: BTF was unloaded */ 29 err = -errno; 30 log_err("failed to get FD for BTF object #%d", id); 31 return err; 32 } 33 34 len = sizeof(info); 35 memset(&info, 0, sizeof(info)); 36 info.name = ptr_to_u64(name); 37 info.name_len = sizeof(name); 38 39 err = bpf_obj_get_info_by_fd(fd, &info, &len); 40 if (err) { 41 err = -errno; 42 log_err("failed to get info for BTF object #%d", id); 43 close(fd); 44 return err; 45 } 46 47 if (strcmp(name, module_name) == 0) 48 return fd; 49 50 close(fd); 51 } 52 return -ENOENT; 53 } 54 55 void test_module_fentry_shadow(void) 56 { 57 struct btf *vmlinux_btf = NULL, *mod_btf = NULL; 58 int err, i; 59 int btf_fd[2] = {}; 60 int prog_fd[2] = {}; 61 int link_fd[2] = {}; 62 __s32 btf_id[2] = {}; 63 64 if (!env.has_testmod) { 65 test__skip(); 66 return; 67 } 68 69 LIBBPF_OPTS(bpf_prog_load_opts, load_opts, 70 .expected_attach_type = BPF_TRACE_FENTRY, 71 ); 72 73 const struct bpf_insn trace_program[] = { 74 BPF_MOV64_IMM(BPF_REG_0, 0), 75 BPF_EXIT_INSN(), 76 }; 77 78 vmlinux_btf = btf__load_vmlinux_btf(); 79 if (!ASSERT_OK_PTR(vmlinux_btf, "load_vmlinux_btf")) 80 return; 81 82 btf_fd[1] = get_bpf_testmod_btf_fd(); 83 if (!ASSERT_GE(btf_fd[1], 0, "get_bpf_testmod_btf_fd")) 84 goto out; 85 86 mod_btf = btf_get_from_fd(btf_fd[1], vmlinux_btf); 87 if (!ASSERT_OK_PTR(mod_btf, "btf_get_from_fd")) 88 goto out; 89 90 btf_id[0] = btf__find_by_name_kind(vmlinux_btf, symbol_name, BTF_KIND_FUNC); 91 if (!ASSERT_GT(btf_id[0], 0, "btf_find_by_name")) 92 goto out; 93 94 btf_id[1] = btf__find_by_name_kind(mod_btf, symbol_name, BTF_KIND_FUNC); 95 if (!ASSERT_GT(btf_id[1], 0, "btf_find_by_name")) 96 goto out; 97 98 for (i = 0; i < 2; i++) { 99 load_opts.attach_btf_id = btf_id[i]; 100 load_opts.attach_btf_obj_fd = btf_fd[i]; 101 prog_fd[i] = bpf_prog_load(BPF_PROG_TYPE_TRACING, NULL, "GPL", 102 trace_program, 103 sizeof(trace_program) / sizeof(struct bpf_insn), 104 &load_opts); 105 if (!ASSERT_GE(prog_fd[i], 0, "bpf_prog_load")) 106 goto out; 107 108 /* If the verifier incorrectly resolves addresses of the 109 * shadowed functions and uses the same address for both the 110 * vmlinux and the bpf_testmod functions, this will fail on 111 * attempting to create two trampolines for the same address, 112 * which is forbidden. 113 */ 114 link_fd[i] = bpf_link_create(prog_fd[i], 0, BPF_TRACE_FENTRY, NULL); 115 if (!ASSERT_GE(link_fd[i], 0, "bpf_link_create")) 116 goto out; 117 } 118 119 err = bpf_prog_test_run_opts(prog_fd[0], NULL); 120 ASSERT_OK(err, "running test"); 121 122 out: 123 btf__free(vmlinux_btf); 124 btf__free(mod_btf); 125 for (i = 0; i < 2; i++) { 126 if (btf_fd[i]) 127 close(btf_fd[i]); 128 if (prog_fd[i] > 0) 129 close(prog_fd[i]); 130 if (link_fd[i] > 0) 131 close(link_fd[i]); 132 } 133 } 134
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.