]>
Commit | Line | Data |
---|---|---|
886225bb SF |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #include <test_progs.h> | |
3 | ||
2c2837b0 AN |
4 | #define nr_iters 2 |
5 | ||
d3f7b166 | 6 | void serial_test_bpf_obj_id(void) |
886225bb SF |
7 | { |
8 | const __u64 array_magic_value = 0xfaceb00c; | |
9 | const __u32 array_key = 0; | |
afef88e6 | 10 | const char *file = "./test_obj_id.bpf.o"; |
886225bb SF |
11 | const char *expected_prog_name = "test_obj_id"; |
12 | const char *expected_map_name = "test_map_id"; | |
13 | const __u64 nsec_per_sec = 1000000000; | |
14 | ||
2c2837b0 AN |
15 | struct bpf_object *objs[nr_iters] = {}; |
16 | struct bpf_link *links[nr_iters] = {}; | |
17 | struct bpf_program *prog; | |
886225bb SF |
18 | int prog_fds[nr_iters], map_fds[nr_iters]; |
19 | /* +1 to test for the info_len returned by kernel */ | |
20 | struct bpf_prog_info prog_infos[nr_iters + 1]; | |
21 | struct bpf_map_info map_infos[nr_iters + 1]; | |
2c2837b0 | 22 | struct bpf_link_info link_infos[nr_iters + 1]; |
886225bb SF |
23 | /* Each prog only uses one map. +1 to test nr_map_ids |
24 | * returned by kernel. | |
25 | */ | |
26 | __u32 map_ids[nr_iters + 1]; | |
2c2837b0 | 27 | char jited_insns[128], xlated_insns[128], zeros[128], tp_name[128]; |
886225bb SF |
28 | __u32 i, next_id, info_len, nr_id_found, duration = 0; |
29 | struct timespec real_time_ts, boot_time_ts; | |
30 | int err = 0; | |
31 | __u64 array_value; | |
32 | uid_t my_uid = getuid(); | |
33 | time_t now, load_time; | |
34 | ||
35 | err = bpf_prog_get_fd_by_id(0); | |
36 | CHECK(err >= 0 || errno != ENOENT, | |
37 | "get-fd-by-notexist-prog-id", "err %d errno %d\n", err, errno); | |
38 | ||
39 | err = bpf_map_get_fd_by_id(0); | |
40 | CHECK(err >= 0 || errno != ENOENT, | |
41 | "get-fd-by-notexist-map-id", "err %d errno %d\n", err, errno); | |
42 | ||
2c2837b0 AN |
43 | err = bpf_link_get_fd_by_id(0); |
44 | CHECK(err >= 0 || errno != ENOENT, | |
45 | "get-fd-by-notexist-link-id", "err %d errno %d\n", err, errno); | |
886225bb SF |
46 | |
47 | /* Check bpf_obj_get_info_by_fd() */ | |
48 | bzero(zeros, sizeof(zeros)); | |
49 | for (i = 0; i < nr_iters; i++) { | |
50 | now = time(NULL); | |
cbdb1461 | 51 | err = bpf_prog_test_load(file, BPF_PROG_TYPE_RAW_TRACEPOINT, |
886225bb SF |
52 | &objs[i], &prog_fds[i]); |
53 | /* test_obj_id.o is a dumb prog. It should never fail | |
54 | * to load. | |
55 | */ | |
62d69f24 SF |
56 | if (CHECK_FAIL(err)) |
57 | continue; | |
886225bb SF |
58 | |
59 | /* Insert a magic value to the map */ | |
60 | map_fds[i] = bpf_find_map(__func__, objs[i], "test_map_id"); | |
62d69f24 SF |
61 | if (CHECK_FAIL(map_fds[i] < 0)) |
62 | goto done; | |
886225bb SF |
63 | err = bpf_map_update_elem(map_fds[i], &array_key, |
64 | &array_magic_value, 0); | |
62d69f24 SF |
65 | if (CHECK_FAIL(err)) |
66 | goto done; | |
886225bb | 67 | |
a393ea80 KFL |
68 | prog = bpf_object__find_program_by_name(objs[i], |
69 | "test_obj_id"); | |
2c2837b0 AN |
70 | if (CHECK_FAIL(!prog)) |
71 | goto done; | |
72 | links[i] = bpf_program__attach(prog); | |
73 | err = libbpf_get_error(links[i]); | |
74 | if (CHECK(err, "prog_attach", "prog #%d, err %d\n", i, err)) { | |
75 | links[i] = NULL; | |
76 | goto done; | |
77 | } | |
78 | ||
886225bb SF |
79 | /* Check getting map info */ |
80 | info_len = sizeof(struct bpf_map_info) * 2; | |
81 | bzero(&map_infos[i], info_len); | |
82 | err = bpf_obj_get_info_by_fd(map_fds[i], &map_infos[i], | |
83 | &info_len); | |
84 | if (CHECK(err || | |
85 | map_infos[i].type != BPF_MAP_TYPE_ARRAY || | |
86 | map_infos[i].key_size != sizeof(__u32) || | |
87 | map_infos[i].value_size != sizeof(__u64) || | |
88 | map_infos[i].max_entries != 1 || | |
89 | map_infos[i].map_flags != 0 || | |
90 | info_len != sizeof(struct bpf_map_info) || | |
91 | strcmp((char *)map_infos[i].name, expected_map_name), | |
92 | "get-map-info(fd)", | |
a918b03e | 93 | "err %d errno %d type %d(%d) info_len %u(%zu) key_size %u value_size %u max_entries %u map_flags %X name %s(%s)\n", |
886225bb SF |
94 | err, errno, |
95 | map_infos[i].type, BPF_MAP_TYPE_ARRAY, | |
96 | info_len, sizeof(struct bpf_map_info), | |
97 | map_infos[i].key_size, | |
98 | map_infos[i].value_size, | |
99 | map_infos[i].max_entries, | |
100 | map_infos[i].map_flags, | |
101 | map_infos[i].name, expected_map_name)) | |
102 | goto done; | |
103 | ||
104 | /* Check getting prog info */ | |
105 | info_len = sizeof(struct bpf_prog_info) * 2; | |
106 | bzero(&prog_infos[i], info_len); | |
107 | bzero(jited_insns, sizeof(jited_insns)); | |
108 | bzero(xlated_insns, sizeof(xlated_insns)); | |
109 | prog_infos[i].jited_prog_insns = ptr_to_u64(jited_insns); | |
110 | prog_infos[i].jited_prog_len = sizeof(jited_insns); | |
111 | prog_infos[i].xlated_prog_insns = ptr_to_u64(xlated_insns); | |
112 | prog_infos[i].xlated_prog_len = sizeof(xlated_insns); | |
113 | prog_infos[i].map_ids = ptr_to_u64(map_ids + i); | |
114 | prog_infos[i].nr_map_ids = 2; | |
115 | err = clock_gettime(CLOCK_REALTIME, &real_time_ts); | |
62d69f24 SF |
116 | if (CHECK_FAIL(err)) |
117 | goto done; | |
886225bb | 118 | err = clock_gettime(CLOCK_BOOTTIME, &boot_time_ts); |
62d69f24 SF |
119 | if (CHECK_FAIL(err)) |
120 | goto done; | |
886225bb SF |
121 | err = bpf_obj_get_info_by_fd(prog_fds[i], &prog_infos[i], |
122 | &info_len); | |
123 | load_time = (real_time_ts.tv_sec - boot_time_ts.tv_sec) | |
124 | + (prog_infos[i].load_time / nsec_per_sec); | |
125 | if (CHECK(err || | |
2c2837b0 | 126 | prog_infos[i].type != BPF_PROG_TYPE_RAW_TRACEPOINT || |
886225bb | 127 | info_len != sizeof(struct bpf_prog_info) || |
0ff97e56 AN |
128 | (env.jit_enabled && !prog_infos[i].jited_prog_len) || |
129 | (env.jit_enabled && | |
886225bb SF |
130 | !memcmp(jited_insns, zeros, sizeof(zeros))) || |
131 | !prog_infos[i].xlated_prog_len || | |
132 | !memcmp(xlated_insns, zeros, sizeof(zeros)) || | |
133 | load_time < now - 60 || load_time > now + 60 || | |
134 | prog_infos[i].created_by_uid != my_uid || | |
135 | prog_infos[i].nr_map_ids != 1 || | |
136 | *(int *)(long)prog_infos[i].map_ids != map_infos[i].id || | |
137 | strcmp((char *)prog_infos[i].name, expected_prog_name), | |
138 | "get-prog-info(fd)", | |
2c2837b0 AN |
139 | "err %d errno %d i %d type %d(%d) info_len %u(%zu) " |
140 | "jit_enabled %d jited_prog_len %u xlated_prog_len %u " | |
141 | "jited_prog %d xlated_prog %d load_time %lu(%lu) " | |
142 | "uid %u(%u) nr_map_ids %u(%u) map_id %u(%u) " | |
143 | "name %s(%s)\n", | |
886225bb SF |
144 | err, errno, i, |
145 | prog_infos[i].type, BPF_PROG_TYPE_SOCKET_FILTER, | |
146 | info_len, sizeof(struct bpf_prog_info), | |
0ff97e56 | 147 | env.jit_enabled, |
886225bb SF |
148 | prog_infos[i].jited_prog_len, |
149 | prog_infos[i].xlated_prog_len, | |
150 | !!memcmp(jited_insns, zeros, sizeof(zeros)), | |
151 | !!memcmp(xlated_insns, zeros, sizeof(zeros)), | |
152 | load_time, now, | |
153 | prog_infos[i].created_by_uid, my_uid, | |
154 | prog_infos[i].nr_map_ids, 1, | |
155 | *(int *)(long)prog_infos[i].map_ids, map_infos[i].id, | |
156 | prog_infos[i].name, expected_prog_name)) | |
157 | goto done; | |
2c2837b0 AN |
158 | |
159 | /* Check getting link info */ | |
160 | info_len = sizeof(struct bpf_link_info) * 2; | |
161 | bzero(&link_infos[i], info_len); | |
9028bbcc | 162 | link_infos[i].raw_tracepoint.tp_name = ptr_to_u64(&tp_name); |
2c2837b0 AN |
163 | link_infos[i].raw_tracepoint.tp_name_len = sizeof(tp_name); |
164 | err = bpf_obj_get_info_by_fd(bpf_link__fd(links[i]), | |
165 | &link_infos[i], &info_len); | |
166 | if (CHECK(err || | |
167 | link_infos[i].type != BPF_LINK_TYPE_RAW_TRACEPOINT || | |
168 | link_infos[i].prog_id != prog_infos[i].id || | |
9028bbcc AN |
169 | link_infos[i].raw_tracepoint.tp_name != ptr_to_u64(&tp_name) || |
170 | strcmp(u64_to_ptr(link_infos[i].raw_tracepoint.tp_name), | |
2c2837b0 AN |
171 | "sys_enter") || |
172 | info_len != sizeof(struct bpf_link_info), | |
173 | "get-link-info(fd)", | |
174 | "err %d errno %d info_len %u(%zu) type %d(%d) id %d " | |
175 | "prog_id %d (%d) tp_name %s(%s)\n", | |
176 | err, errno, | |
177 | info_len, sizeof(struct bpf_link_info), | |
178 | link_infos[i].type, BPF_LINK_TYPE_RAW_TRACEPOINT, | |
179 | link_infos[i].id, | |
180 | link_infos[i].prog_id, prog_infos[i].id, | |
9028bbcc | 181 | (const char *)u64_to_ptr(link_infos[i].raw_tracepoint.tp_name), |
2c2837b0 AN |
182 | "sys_enter")) |
183 | goto done; | |
184 | ||
886225bb SF |
185 | } |
186 | ||
187 | /* Check bpf_prog_get_next_id() */ | |
188 | nr_id_found = 0; | |
189 | next_id = 0; | |
190 | while (!bpf_prog_get_next_id(next_id, &next_id)) { | |
191 | struct bpf_prog_info prog_info = {}; | |
192 | __u32 saved_map_id; | |
193 | int prog_fd; | |
194 | ||
195 | info_len = sizeof(prog_info); | |
196 | ||
197 | prog_fd = bpf_prog_get_fd_by_id(next_id); | |
198 | if (prog_fd < 0 && errno == ENOENT) | |
199 | /* The bpf_prog is in the dead row */ | |
200 | continue; | |
201 | if (CHECK(prog_fd < 0, "get-prog-fd(next_id)", | |
202 | "prog_fd %d next_id %d errno %d\n", | |
203 | prog_fd, next_id, errno)) | |
204 | break; | |
205 | ||
206 | for (i = 0; i < nr_iters; i++) | |
207 | if (prog_infos[i].id == next_id) | |
208 | break; | |
209 | ||
210 | if (i == nr_iters) | |
211 | continue; | |
212 | ||
213 | nr_id_found++; | |
214 | ||
215 | /* Negative test: | |
216 | * prog_info.nr_map_ids = 1 | |
217 | * prog_info.map_ids = NULL | |
218 | */ | |
219 | prog_info.nr_map_ids = 1; | |
220 | err = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &info_len); | |
221 | if (CHECK(!err || errno != EFAULT, | |
222 | "get-prog-fd-bad-nr-map-ids", "err %d errno %d(%d)", | |
223 | err, errno, EFAULT)) | |
224 | break; | |
225 | bzero(&prog_info, sizeof(prog_info)); | |
226 | info_len = sizeof(prog_info); | |
227 | ||
228 | saved_map_id = *(int *)((long)prog_infos[i].map_ids); | |
229 | prog_info.map_ids = prog_infos[i].map_ids; | |
230 | prog_info.nr_map_ids = 2; | |
231 | err = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &info_len); | |
232 | prog_infos[i].jited_prog_insns = 0; | |
233 | prog_infos[i].xlated_prog_insns = 0; | |
234 | CHECK(err || info_len != sizeof(struct bpf_prog_info) || | |
235 | memcmp(&prog_info, &prog_infos[i], info_len) || | |
236 | *(int *)(long)prog_info.map_ids != saved_map_id, | |
237 | "get-prog-info(next_id->fd)", | |
a918b03e | 238 | "err %d errno %d info_len %u(%zu) memcmp %d map_id %u(%u)\n", |
886225bb SF |
239 | err, errno, info_len, sizeof(struct bpf_prog_info), |
240 | memcmp(&prog_info, &prog_infos[i], info_len), | |
241 | *(int *)(long)prog_info.map_ids, saved_map_id); | |
242 | close(prog_fd); | |
243 | } | |
244 | CHECK(nr_id_found != nr_iters, | |
245 | "check total prog id found by get_next_id", | |
246 | "nr_id_found %u(%u)\n", | |
247 | nr_id_found, nr_iters); | |
248 | ||
249 | /* Check bpf_map_get_next_id() */ | |
250 | nr_id_found = 0; | |
251 | next_id = 0; | |
252 | while (!bpf_map_get_next_id(next_id, &next_id)) { | |
253 | struct bpf_map_info map_info = {}; | |
254 | int map_fd; | |
255 | ||
256 | info_len = sizeof(map_info); | |
257 | ||
258 | map_fd = bpf_map_get_fd_by_id(next_id); | |
259 | if (map_fd < 0 && errno == ENOENT) | |
260 | /* The bpf_map is in the dead row */ | |
261 | continue; | |
262 | if (CHECK(map_fd < 0, "get-map-fd(next_id)", | |
263 | "map_fd %d next_id %u errno %d\n", | |
264 | map_fd, next_id, errno)) | |
265 | break; | |
266 | ||
267 | for (i = 0; i < nr_iters; i++) | |
268 | if (map_infos[i].id == next_id) | |
269 | break; | |
270 | ||
271 | if (i == nr_iters) | |
272 | continue; | |
273 | ||
274 | nr_id_found++; | |
275 | ||
276 | err = bpf_map_lookup_elem(map_fd, &array_key, &array_value); | |
62d69f24 SF |
277 | if (CHECK_FAIL(err)) |
278 | goto done; | |
886225bb SF |
279 | |
280 | err = bpf_obj_get_info_by_fd(map_fd, &map_info, &info_len); | |
281 | CHECK(err || info_len != sizeof(struct bpf_map_info) || | |
282 | memcmp(&map_info, &map_infos[i], info_len) || | |
283 | array_value != array_magic_value, | |
284 | "check get-map-info(next_id->fd)", | |
a918b03e | 285 | "err %d errno %d info_len %u(%zu) memcmp %d array_value %llu(%llu)\n", |
886225bb SF |
286 | err, errno, info_len, sizeof(struct bpf_map_info), |
287 | memcmp(&map_info, &map_infos[i], info_len), | |
288 | array_value, array_magic_value); | |
289 | ||
290 | close(map_fd); | |
291 | } | |
292 | CHECK(nr_id_found != nr_iters, | |
293 | "check total map id found by get_next_id", | |
294 | "nr_id_found %u(%u)\n", | |
295 | nr_id_found, nr_iters); | |
296 | ||
2c2837b0 AN |
297 | /* Check bpf_link_get_next_id() */ |
298 | nr_id_found = 0; | |
299 | next_id = 0; | |
300 | while (!bpf_link_get_next_id(next_id, &next_id)) { | |
301 | struct bpf_link_info link_info; | |
302 | int link_fd, cmp_res; | |
303 | ||
304 | info_len = sizeof(link_info); | |
305 | memset(&link_info, 0, info_len); | |
306 | ||
307 | link_fd = bpf_link_get_fd_by_id(next_id); | |
308 | if (link_fd < 0 && errno == ENOENT) | |
309 | /* The bpf_link is in the dead row */ | |
310 | continue; | |
311 | if (CHECK(link_fd < 0, "get-link-fd(next_id)", | |
312 | "link_fd %d next_id %u errno %d\n", | |
313 | link_fd, next_id, errno)) | |
314 | break; | |
315 | ||
316 | for (i = 0; i < nr_iters; i++) | |
317 | if (link_infos[i].id == next_id) | |
318 | break; | |
319 | ||
320 | if (i == nr_iters) | |
321 | continue; | |
322 | ||
323 | nr_id_found++; | |
324 | ||
325 | err = bpf_obj_get_info_by_fd(link_fd, &link_info, &info_len); | |
326 | cmp_res = memcmp(&link_info, &link_infos[i], | |
327 | offsetof(struct bpf_link_info, raw_tracepoint)); | |
328 | CHECK(err || info_len != sizeof(link_info) || cmp_res, | |
329 | "check get-link-info(next_id->fd)", | |
330 | "err %d errno %d info_len %u(%zu) memcmp %d\n", | |
331 | err, errno, info_len, sizeof(struct bpf_link_info), | |
332 | cmp_res); | |
333 | ||
334 | close(link_fd); | |
335 | } | |
336 | CHECK(nr_id_found != nr_iters, | |
337 | "check total link id found by get_next_id", | |
338 | "nr_id_found %u(%u)\n", nr_id_found, nr_iters); | |
339 | ||
886225bb | 340 | done: |
2c2837b0 AN |
341 | for (i = 0; i < nr_iters; i++) { |
342 | bpf_link__destroy(links[i]); | |
886225bb | 343 | bpf_object__close(objs[i]); |
2c2837b0 | 344 | } |
886225bb | 345 | } |