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 LIBBPF_OPTS(bpf_prog_load_opts, load_opts, 65 .expected_attach_type = BPF_TRACE_FENTRY, 66 ); 67 68 const struct bpf_insn trace_program[] = { 69 BPF_MOV64_IMM(BPF_REG_0, 0), 70 BPF_EXIT_INSN(), 71 }; 72 73 vmlinux_btf = btf__load_vmlinux_btf(); 74 if (!ASSERT_OK_PTR(vmlinux_btf, "load_vmlinux_btf")) 75 return; 76 77 btf_fd[1] = get_bpf_testmod_btf_fd(); 78 if (!ASSERT_GE(btf_fd[1], 0, "get_bpf_testmod_btf_fd")) 79 goto out; 80 81 mod_btf = btf_get_from_fd(btf_fd[1], vmlinux_btf); 82 if (!ASSERT_OK_PTR(mod_btf, "btf_get_from_fd")) 83 goto out; 84 85 btf_id[0] = btf__find_by_name_kind(vmlinux_btf, symbol_name, BTF_KIND_FUNC); 86 if (!ASSERT_GT(btf_id[0], 0, "btf_find_by_name")) 87 goto out; 88 89 btf_id[1] = btf__find_by_name_kind(mod_btf, symbol_name, BTF_KIND_FUNC); 90 if (!ASSERT_GT(btf_id[1], 0, "btf_find_by_name")) 91 goto out; 92 93 for (i = 0; i < 2; i++) { 94 load_opts.attach_btf_id = btf_id[i]; 95 load_opts.attach_btf_obj_fd = btf_fd[i]; 96 prog_fd[i] = bpf_prog_load(BPF_PROG_TYPE_TRACING, NULL, "GPL", 97 trace_program, 98 sizeof(trace_program) / sizeof(struct bpf_insn), 99 &load_opts); 100 if (!ASSERT_GE(prog_fd[i], 0, "bpf_prog_load")) 101 goto out; 102 103 /* If the verifier incorrectly resolves addresses of the 104 * shadowed functions and uses the same address for both the 105 * vmlinux and the bpf_testmod functions, this will fail on 106 * attempting to create two trampolines for the same address, 107 * which is forbidden. 108 */ 109 link_fd[i] = bpf_link_create(prog_fd[i], 0, BPF_TRACE_FENTRY, NULL); 110 if (!ASSERT_GE(link_fd[i], 0, "bpf_link_create")) 111 goto out; 112 } 113 114 err = bpf_prog_test_run_opts(prog_fd[0], NULL); 115 ASSERT_OK(err, "running test"); 116 117 out: 118 btf__free(vmlinux_btf); 119 btf__free(mod_btf); 120 for (i = 0; i < 2; i++) { 121 if (btf_fd[i]) 122 close(btf_fd[i]); 123 if (prog_fd[i] > 0) 124 close(prog_fd[i]); 125 if (link_fd[i] > 0) 126 close(link_fd[i]); 127 } 128 } 129