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