1 // SPDX-License-Identifier: GPL-2.0
2 #include <test_progs.h>
4 void test_bpf_obj_id(void)
6 const __u64 array_magic_value
= 0xfaceb00c;
7 const __u32 array_key
= 0;
8 const int nr_iters
= 2;
9 const char *file
= "./test_obj_id.o";
10 const char *expected_prog_name
= "test_obj_id";
11 const char *expected_map_name
= "test_map_id";
12 const __u64 nsec_per_sec
= 1000000000;
14 struct bpf_object
*objs
[nr_iters
];
15 int prog_fds
[nr_iters
], map_fds
[nr_iters
];
16 /* +1 to test for the info_len returned by kernel */
17 struct bpf_prog_info prog_infos
[nr_iters
+ 1];
18 struct bpf_map_info map_infos
[nr_iters
+ 1];
19 /* Each prog only uses one map. +1 to test nr_map_ids
22 __u32 map_ids
[nr_iters
+ 1];
23 char jited_insns
[128], xlated_insns
[128], zeros
[128];
24 __u32 i
, next_id
, info_len
, nr_id_found
, duration
= 0;
25 struct timespec real_time_ts
, boot_time_ts
;
28 uid_t my_uid
= getuid();
29 time_t now
, load_time
;
31 err
= bpf_prog_get_fd_by_id(0);
32 CHECK(err
>= 0 || errno
!= ENOENT
,
33 "get-fd-by-notexist-prog-id", "err %d errno %d\n", err
, errno
);
35 err
= bpf_map_get_fd_by_id(0);
36 CHECK(err
>= 0 || errno
!= ENOENT
,
37 "get-fd-by-notexist-map-id", "err %d errno %d\n", err
, errno
);
39 for (i
= 0; i
< nr_iters
; i
++)
42 /* Check bpf_obj_get_info_by_fd() */
43 bzero(zeros
, sizeof(zeros
));
44 for (i
= 0; i
< nr_iters
; i
++) {
46 err
= bpf_prog_load(file
, BPF_PROG_TYPE_SOCKET_FILTER
,
47 &objs
[i
], &prog_fds
[i
]);
48 /* test_obj_id.o is a dumb prog. It should never fail
54 /* Insert a magic value to the map */
55 map_fds
[i
] = bpf_find_map(__func__
, objs
[i
], "test_map_id");
56 if (CHECK_FAIL(map_fds
[i
] < 0))
58 err
= bpf_map_update_elem(map_fds
[i
], &array_key
,
59 &array_magic_value
, 0);
63 /* Check getting map info */
64 info_len
= sizeof(struct bpf_map_info
) * 2;
65 bzero(&map_infos
[i
], info_len
);
66 err
= bpf_obj_get_info_by_fd(map_fds
[i
], &map_infos
[i
],
69 map_infos
[i
].type
!= BPF_MAP_TYPE_ARRAY
||
70 map_infos
[i
].key_size
!= sizeof(__u32
) ||
71 map_infos
[i
].value_size
!= sizeof(__u64
) ||
72 map_infos
[i
].max_entries
!= 1 ||
73 map_infos
[i
].map_flags
!= 0 ||
74 info_len
!= sizeof(struct bpf_map_info
) ||
75 strcmp((char *)map_infos
[i
].name
, expected_map_name
),
77 "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",
79 map_infos
[i
].type
, BPF_MAP_TYPE_ARRAY
,
80 info_len
, sizeof(struct bpf_map_info
),
81 map_infos
[i
].key_size
,
82 map_infos
[i
].value_size
,
83 map_infos
[i
].max_entries
,
84 map_infos
[i
].map_flags
,
85 map_infos
[i
].name
, expected_map_name
))
88 /* Check getting prog info */
89 info_len
= sizeof(struct bpf_prog_info
) * 2;
90 bzero(&prog_infos
[i
], info_len
);
91 bzero(jited_insns
, sizeof(jited_insns
));
92 bzero(xlated_insns
, sizeof(xlated_insns
));
93 prog_infos
[i
].jited_prog_insns
= ptr_to_u64(jited_insns
);
94 prog_infos
[i
].jited_prog_len
= sizeof(jited_insns
);
95 prog_infos
[i
].xlated_prog_insns
= ptr_to_u64(xlated_insns
);
96 prog_infos
[i
].xlated_prog_len
= sizeof(xlated_insns
);
97 prog_infos
[i
].map_ids
= ptr_to_u64(map_ids
+ i
);
98 prog_infos
[i
].nr_map_ids
= 2;
99 err
= clock_gettime(CLOCK_REALTIME
, &real_time_ts
);
102 err
= clock_gettime(CLOCK_BOOTTIME
, &boot_time_ts
);
105 err
= bpf_obj_get_info_by_fd(prog_fds
[i
], &prog_infos
[i
],
107 load_time
= (real_time_ts
.tv_sec
- boot_time_ts
.tv_sec
)
108 + (prog_infos
[i
].load_time
/ nsec_per_sec
);
110 prog_infos
[i
].type
!= BPF_PROG_TYPE_SOCKET_FILTER
||
111 info_len
!= sizeof(struct bpf_prog_info
) ||
112 (env
.jit_enabled
&& !prog_infos
[i
].jited_prog_len
) ||
114 !memcmp(jited_insns
, zeros
, sizeof(zeros
))) ||
115 !prog_infos
[i
].xlated_prog_len
||
116 !memcmp(xlated_insns
, zeros
, sizeof(zeros
)) ||
117 load_time
< now
- 60 || load_time
> now
+ 60 ||
118 prog_infos
[i
].created_by_uid
!= my_uid
||
119 prog_infos
[i
].nr_map_ids
!= 1 ||
120 *(int *)(long)prog_infos
[i
].map_ids
!= map_infos
[i
].id
||
121 strcmp((char *)prog_infos
[i
].name
, expected_prog_name
),
123 "err %d errno %d i %d type %d(%d) info_len %u(%zu) jit_enabled %d jited_prog_len %u xlated_prog_len %u jited_prog %d xlated_prog %d load_time %lu(%lu) uid %u(%u) nr_map_ids %u(%u) map_id %u(%u) name %s(%s)\n",
125 prog_infos
[i
].type
, BPF_PROG_TYPE_SOCKET_FILTER
,
126 info_len
, sizeof(struct bpf_prog_info
),
128 prog_infos
[i
].jited_prog_len
,
129 prog_infos
[i
].xlated_prog_len
,
130 !!memcmp(jited_insns
, zeros
, sizeof(zeros
)),
131 !!memcmp(xlated_insns
, zeros
, sizeof(zeros
)),
133 prog_infos
[i
].created_by_uid
, my_uid
,
134 prog_infos
[i
].nr_map_ids
, 1,
135 *(int *)(long)prog_infos
[i
].map_ids
, map_infos
[i
].id
,
136 prog_infos
[i
].name
, expected_prog_name
))
140 /* Check bpf_prog_get_next_id() */
143 while (!bpf_prog_get_next_id(next_id
, &next_id
)) {
144 struct bpf_prog_info prog_info
= {};
148 info_len
= sizeof(prog_info
);
150 prog_fd
= bpf_prog_get_fd_by_id(next_id
);
151 if (prog_fd
< 0 && errno
== ENOENT
)
152 /* The bpf_prog is in the dead row */
154 if (CHECK(prog_fd
< 0, "get-prog-fd(next_id)",
155 "prog_fd %d next_id %d errno %d\n",
156 prog_fd
, next_id
, errno
))
159 for (i
= 0; i
< nr_iters
; i
++)
160 if (prog_infos
[i
].id
== next_id
)
169 * prog_info.nr_map_ids = 1
170 * prog_info.map_ids = NULL
172 prog_info
.nr_map_ids
= 1;
173 err
= bpf_obj_get_info_by_fd(prog_fd
, &prog_info
, &info_len
);
174 if (CHECK(!err
|| errno
!= EFAULT
,
175 "get-prog-fd-bad-nr-map-ids", "err %d errno %d(%d)",
178 bzero(&prog_info
, sizeof(prog_info
));
179 info_len
= sizeof(prog_info
);
181 saved_map_id
= *(int *)((long)prog_infos
[i
].map_ids
);
182 prog_info
.map_ids
= prog_infos
[i
].map_ids
;
183 prog_info
.nr_map_ids
= 2;
184 err
= bpf_obj_get_info_by_fd(prog_fd
, &prog_info
, &info_len
);
185 prog_infos
[i
].jited_prog_insns
= 0;
186 prog_infos
[i
].xlated_prog_insns
= 0;
187 CHECK(err
|| info_len
!= sizeof(struct bpf_prog_info
) ||
188 memcmp(&prog_info
, &prog_infos
[i
], info_len
) ||
189 *(int *)(long)prog_info
.map_ids
!= saved_map_id
,
190 "get-prog-info(next_id->fd)",
191 "err %d errno %d info_len %u(%zu) memcmp %d map_id %u(%u)\n",
192 err
, errno
, info_len
, sizeof(struct bpf_prog_info
),
193 memcmp(&prog_info
, &prog_infos
[i
], info_len
),
194 *(int *)(long)prog_info
.map_ids
, saved_map_id
);
197 CHECK(nr_id_found
!= nr_iters
,
198 "check total prog id found by get_next_id",
199 "nr_id_found %u(%u)\n",
200 nr_id_found
, nr_iters
);
202 /* Check bpf_map_get_next_id() */
205 while (!bpf_map_get_next_id(next_id
, &next_id
)) {
206 struct bpf_map_info map_info
= {};
209 info_len
= sizeof(map_info
);
211 map_fd
= bpf_map_get_fd_by_id(next_id
);
212 if (map_fd
< 0 && errno
== ENOENT
)
213 /* The bpf_map is in the dead row */
215 if (CHECK(map_fd
< 0, "get-map-fd(next_id)",
216 "map_fd %d next_id %u errno %d\n",
217 map_fd
, next_id
, errno
))
220 for (i
= 0; i
< nr_iters
; i
++)
221 if (map_infos
[i
].id
== next_id
)
229 err
= bpf_map_lookup_elem(map_fd
, &array_key
, &array_value
);
233 err
= bpf_obj_get_info_by_fd(map_fd
, &map_info
, &info_len
);
234 CHECK(err
|| info_len
!= sizeof(struct bpf_map_info
) ||
235 memcmp(&map_info
, &map_infos
[i
], info_len
) ||
236 array_value
!= array_magic_value
,
237 "check get-map-info(next_id->fd)",
238 "err %d errno %d info_len %u(%zu) memcmp %d array_value %llu(%llu)\n",
239 err
, errno
, info_len
, sizeof(struct bpf_map_info
),
240 memcmp(&map_info
, &map_infos
[i
], info_len
),
241 array_value
, array_magic_value
);
245 CHECK(nr_id_found
!= nr_iters
,
246 "check total map id found by get_next_id",
247 "nr_id_found %u(%u)\n",
248 nr_id_found
, nr_iters
);
251 for (i
= 0; i
< nr_iters
; i
++)
252 bpf_object__close(objs
[i
]);