]>
Commit | Line | Data |
---|---|---|
1e8611bb AN |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #include <test_progs.h> | |
3 | ||
928ca75e AN |
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 | ||
1e8611bb AN |
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 | ||
928ca75e AN |
42 | EMBED_FILE(probe, "test_attach_probe.o"); |
43 | ||
1e8611bb AN |
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; | |
928ca75e | 52 | const char *obj_name = "attach_probe"; |
e00aca65 | 53 | DECLARE_LIBBPF_OPTS(bpf_object_open_opts, open_opts, |
928ca75e AN |
54 | .object_name = obj_name, |
55 | .relaxed_maps = true, | |
56 | ); | |
1e8611bb AN |
57 | struct bpf_program *kprobe_prog, *kretprobe_prog; |
58 | struct bpf_program *uprobe_prog, *uretprobe_prog; | |
59 | struct bpf_object *obj; | |
928ca75e | 60 | int err, duration = 0, res; |
1e8611bb AN |
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 | ||
928ca75e AN |
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))) | |
1e8611bb AN |
78 | return; |
79 | ||
928ca75e AN |
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 | ||
1e8611bb AN |
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 | ||
928ca75e AN |
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 | ||
1e8611bb AN |
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 */, | |
1cb59a60 | 115 | SYS_NANOSLEEP_KPROBE_NAME); |
1e8611bb AN |
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 */, | |
1cb59a60 | 123 | SYS_NANOSLEEP_KPROBE_NAME); |
1e8611bb AN |
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 | } |