1 // SPDX-License-Identifier: GPL-2.0
2 #include <test_progs.h>
6 void test_bpf_obj_id(void)
8 const __u64 array_magic_value
= 0xfaceb00c;
9 const __u32 array_key
= 0;
10 const char *file
= "./test_obj_id.o";
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;
15 struct bpf_object
*objs
[nr_iters
] = {};
16 struct bpf_link
*links
[nr_iters
] = {};
17 struct bpf_program
*prog
;
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];
22 struct bpf_link_info link_infos
[nr_iters
+ 1];
23 /* Each prog only uses one map. +1 to test nr_map_ids
26 __u32 map_ids
[nr_iters
+ 1];
27 char jited_insns
[128], xlated_insns
[128], zeros
[128], tp_name
[128];
28 __u32 i
, next_id
, info_len
, nr_id_found
, duration
= 0;
29 struct timespec real_time_ts
, boot_time_ts
;
32 uid_t my_uid
= getuid();
33 time_t now
, load_time
;
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
);
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
);
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
);
47 /* Check bpf_obj_get_info_by_fd() */
48 bzero(zeros
, sizeof(zeros
));
49 for (i
= 0; i
< nr_iters
; i
++) {
51 err
= bpf_prog_load(file
, BPF_PROG_TYPE_RAW_TRACEPOINT
,
52 &objs
[i
], &prog_fds
[i
]);
53 /* test_obj_id.o is a dumb prog. It should never fail
59 /* Insert a magic value to the map */
60 map_fds
[i
] = bpf_find_map(__func__
, objs
[i
], "test_map_id");
61 if (CHECK_FAIL(map_fds
[i
] < 0))
63 err
= bpf_map_update_elem(map_fds
[i
], &array_key
,
64 &array_magic_value
, 0);
68 prog
= bpf_object__find_program_by_title(objs
[i
],
70 if (CHECK_FAIL(!prog
))
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
)) {
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
],
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
),
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",
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
))
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
);
118 err
= clock_gettime(CLOCK_BOOTTIME
, &boot_time_ts
);
121 err
= bpf_obj_get_info_by_fd(prog_fds
[i
], &prog_infos
[i
],
123 load_time
= (real_time_ts
.tv_sec
- boot_time_ts
.tv_sec
)
124 + (prog_infos
[i
].load_time
/ nsec_per_sec
);
126 prog_infos
[i
].type
!= BPF_PROG_TYPE_RAW_TRACEPOINT
||
127 info_len
!= sizeof(struct bpf_prog_info
) ||
128 (env
.jit_enabled
&& !prog_infos
[i
].jited_prog_len
) ||
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
),
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) "
145 prog_infos
[i
].type
, BPF_PROG_TYPE_SOCKET_FILTER
,
146 info_len
, sizeof(struct bpf_prog_info
),
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
)),
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
))
159 /* Check getting link info */
160 info_len
= sizeof(struct bpf_link_info
) * 2;
161 bzero(&link_infos
[i
], info_len
);
162 link_infos
[i
].raw_tracepoint
.tp_name
= ptr_to_u64(&tp_name
);
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
);
167 link_infos
[i
].type
!= BPF_LINK_TYPE_RAW_TRACEPOINT
||
168 link_infos
[i
].prog_id
!= prog_infos
[i
].id
||
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
),
172 info_len
!= sizeof(struct bpf_link_info
),
174 "err %d errno %d info_len %u(%zu) type %d(%d) id %d "
175 "prog_id %d (%d) tp_name %s(%s)\n",
177 info_len
, sizeof(struct bpf_link_info
),
178 link_infos
[i
].type
, BPF_LINK_TYPE_RAW_TRACEPOINT
,
180 link_infos
[i
].prog_id
, prog_infos
[i
].id
,
181 (const char *)u64_to_ptr(link_infos
[i
].raw_tracepoint
.tp_name
),
187 /* Check bpf_prog_get_next_id() */
190 while (!bpf_prog_get_next_id(next_id
, &next_id
)) {
191 struct bpf_prog_info prog_info
= {};
195 info_len
= sizeof(prog_info
);
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 */
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
))
206 for (i
= 0; i
< nr_iters
; i
++)
207 if (prog_infos
[i
].id
== next_id
)
216 * prog_info.nr_map_ids = 1
217 * prog_info.map_ids = NULL
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)",
225 bzero(&prog_info
, sizeof(prog_info
));
226 info_len
= sizeof(prog_info
);
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)",
238 "err %d errno %d info_len %u(%zu) memcmp %d map_id %u(%u)\n",
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
);
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
);
249 /* Check bpf_map_get_next_id() */
252 while (!bpf_map_get_next_id(next_id
, &next_id
)) {
253 struct bpf_map_info map_info
= {};
256 info_len
= sizeof(map_info
);
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 */
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
))
267 for (i
= 0; i
< nr_iters
; i
++)
268 if (map_infos
[i
].id
== next_id
)
276 err
= bpf_map_lookup_elem(map_fd
, &array_key
, &array_value
);
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)",
285 "err %d errno %d info_len %u(%zu) memcmp %d array_value %llu(%llu)\n",
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
);
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
);
297 /* Check bpf_link_get_next_id() */
300 while (!bpf_link_get_next_id(next_id
, &next_id
)) {
301 struct bpf_link_info link_info
;
302 int link_fd
, cmp_res
;
304 info_len
= sizeof(link_info
);
305 memset(&link_info
, 0, info_len
);
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 */
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
))
316 for (i
= 0; i
< nr_iters
; i
++)
317 if (link_infos
[i
].id
== next_id
)
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
),
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
);
341 for (i
= 0; i
< nr_iters
; i
++) {
342 bpf_link__destroy(links
[i
]);
343 bpf_object__close(objs
[i
]);