1 // SPDX-License-Identifier: GPL-2.0 2 #include <test_progs.h> 3 4 #define EMBED_FILE(NAME, PATH) \ 5 asm ( \ 6 " .pushsection \".rodata\", \"a\", @progbits \n" \ 7 " .global "#NAME"_data \n" \ 8 #NAME"_data: \n" \ 9 " .incbin \"" PATH "\" \n" \ 10 #NAME"_data_end: \n" \ 11 " .global "#NAME"_size \n" \ 12 " .type "#NAME"_size, @object \n" \ 13 " .size "#NAME"_size, 4 \n" \ 14 " .align 4, \n" \ 15 #NAME"_size: \n" \ 16 " .int "#NAME"_data_end - "#NAME"_data \n" \ 17 " .popsection \n" \ 18 ); \ 19 extern char NAME##_data[]; \ 20 extern int NAME##_size; 21 22 ssize_t get_base_addr() { 23 size_t start; 24 char buf[256]; 25 FILE *f; 26 27 f = fopen("/proc/self/maps", "r"); 28 if (!f) 29 return -errno; 30 31 while (fscanf(f, "%zx-%*x %s %*s\n", &start, buf) == 2) { 32 if (strcmp(buf, "r-xp") == 0) { 33 fclose(f); 34 return start; 35 } 36 } 37 38 fclose(f); 39 return -EINVAL; 40 } 41 42 EMBED_FILE(probe, "test_attach_probe.o"); 43 44 void test_attach_probe(void) 45 { 46 const char *kprobe_name = "kprobe/sys_nanosleep"; 47 const char *kretprobe_name = "kretprobe/sys_nanosleep"; 48 const char *uprobe_name = "uprobe/trigger_func"; 49 const char *uretprobe_name = "uretprobe/trigger_func"; 50 const int kprobe_idx = 0, kretprobe_idx = 1; 51 const int uprobe_idx = 2, uretprobe_idx = 3; 52 const char *obj_name = "attach_probe"; 53 DECLARE_LIBBPF_OPTS(bpf_object_open_opts, open_opts, 54 .object_name = obj_name, 55 .relaxed_maps = true, 56 ); 57 struct bpf_program *kprobe_prog, *kretprobe_prog; 58 struct bpf_program *uprobe_prog, *uretprobe_prog; 59 struct bpf_object *obj; 60 int err, duration = 0, res; 61 struct bpf_link *kprobe_link = NULL; 62 struct bpf_link *kretprobe_link = NULL; 63 struct bpf_link *uprobe_link = NULL; 64 struct bpf_link *uretprobe_link = NULL; 65 int results_map_fd; 66 size_t uprobe_offset; 67 ssize_t base_addr; 68 69 base_addr = get_base_addr(); 70 if (CHECK(base_addr < 0, "get_base_addr", 71 "failed to find base addr: %zd", base_addr)) 72 return; 73 uprobe_offset = (size_t)&get_base_addr - base_addr; 74 75 /* open object */ 76 obj = bpf_object__open_mem(probe_data, probe_size, &open_opts); 77 if (CHECK(IS_ERR(obj), "obj_open_mem", "err %ld\n", PTR_ERR(obj))) 78 return; 79 80 if (CHECK(strcmp(bpf_object__name(obj), obj_name), "obj_name", 81 "wrong obj name '%s', expected '%s'\n", 82 bpf_object__name(obj), obj_name)) 83 goto cleanup; 84 85 kprobe_prog = bpf_object__find_program_by_title(obj, kprobe_name); 86 if (CHECK(!kprobe_prog, "find_probe", 87 "prog '%s' not found\n", kprobe_name)) 88 goto cleanup; 89 kretprobe_prog = bpf_object__find_program_by_title(obj, kretprobe_name); 90 if (CHECK(!kretprobe_prog, "find_probe", 91 "prog '%s' not found\n", kretprobe_name)) 92 goto cleanup; 93 uprobe_prog = bpf_object__find_program_by_title(obj, uprobe_name); 94 if (CHECK(!uprobe_prog, "find_probe", 95 "prog '%s' not found\n", uprobe_name)) 96 goto cleanup; 97 uretprobe_prog = bpf_object__find_program_by_title(obj, uretprobe_name); 98 if (CHECK(!uretprobe_prog, "find_probe", 99 "prog '%s' not found\n", uretprobe_name)) 100 goto cleanup; 101 102 /* create maps && load programs */ 103 err = bpf_object__load(obj); 104 if (CHECK(err, "obj_load", "err %d\n", err)) 105 goto cleanup; 106 107 /* load maps */ 108 results_map_fd = bpf_find_map(__func__, obj, "results_map"); 109 if (CHECK(results_map_fd < 0, "find_results_map", 110 "err %d\n", results_map_fd)) 111 goto cleanup; 112 113 kprobe_link = bpf_program__attach_kprobe(kprobe_prog, 114 false /* retprobe */, 115 SYS_NANOSLEEP_KPROBE_NAME); 116 if (CHECK(IS_ERR(kprobe_link), "attach_kprobe", 117 "err %ld\n", PTR_ERR(kprobe_link))) { 118 kprobe_link = NULL; 119 goto cleanup; 120 } 121 kretprobe_link = bpf_program__attach_kprobe(kretprobe_prog, 122 true /* retprobe */, 123 SYS_NANOSLEEP_KPROBE_NAME); 124 if (CHECK(IS_ERR(kretprobe_link), "attach_kretprobe", 125 "err %ld\n", PTR_ERR(kretprobe_link))) { 126 kretprobe_link = NULL; 127 goto cleanup; 128 } 129 uprobe_link = bpf_program__attach_uprobe(uprobe_prog, 130 false /* retprobe */, 131 0 /* self pid */, 132 "/proc/self/exe", 133 uprobe_offset); 134 if (CHECK(IS_ERR(uprobe_link), "attach_uprobe", 135 "err %ld\n", PTR_ERR(uprobe_link))) { 136 uprobe_link = NULL; 137 goto cleanup; 138 } 139 uretprobe_link = bpf_program__attach_uprobe(uretprobe_prog, 140 true /* retprobe */, 141 -1 /* any pid */, 142 "/proc/self/exe", 143 uprobe_offset); 144 if (CHECK(IS_ERR(uretprobe_link), "attach_uretprobe", 145 "err %ld\n", PTR_ERR(uretprobe_link))) { 146 uretprobe_link = NULL; 147 goto cleanup; 148 } 149 150 /* trigger & validate kprobe && kretprobe */ 151 usleep(1); 152 153 err = bpf_map_lookup_elem(results_map_fd, &kprobe_idx, &res); 154 if (CHECK(err, "get_kprobe_res", 155 "failed to get kprobe res: %d\n", err)) 156 goto cleanup; 157 if (CHECK(res != kprobe_idx + 1, "check_kprobe_res", 158 "wrong kprobe res: %d\n", res)) 159 goto cleanup; 160 161 err = bpf_map_lookup_elem(results_map_fd, &kretprobe_idx, &res); 162 if (CHECK(err, "get_kretprobe_res", 163 "failed to get kretprobe res: %d\n", err)) 164 goto cleanup; 165 if (CHECK(res != kretprobe_idx + 1, "check_kretprobe_res", 166 "wrong kretprobe res: %d\n", res)) 167 goto cleanup; 168 169 /* trigger & validate uprobe & uretprobe */ 170 get_base_addr(); 171 172 err = bpf_map_lookup_elem(results_map_fd, &uprobe_idx, &res); 173 if (CHECK(err, "get_uprobe_res", 174 "failed to get uprobe res: %d\n", err)) 175 goto cleanup; 176 if (CHECK(res != uprobe_idx + 1, "check_uprobe_res", 177 "wrong uprobe res: %d\n", res)) 178 goto cleanup; 179 180 err = bpf_map_lookup_elem(results_map_fd, &uretprobe_idx, &res); 181 if (CHECK(err, "get_uretprobe_res", 182 "failed to get uretprobe res: %d\n", err)) 183 goto cleanup; 184 if (CHECK(res != uretprobe_idx + 1, "check_uretprobe_res", 185 "wrong uretprobe res: %d\n", res)) 186 goto cleanup; 187 188 cleanup: 189 bpf_link__destroy(kprobe_link); 190 bpf_link__destroy(kretprobe_link); 191 bpf_link__destroy(uprobe_link); 192 bpf_link__destroy(uretprobe_link); 193 bpf_object__close(obj); 194 } 195