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
55 /* Insert a magic value to the map */
56 map_fds
[i
] = bpf_find_map(__func__
, objs
[i
], "test_map_id");
57 assert(map_fds
[i
] >= 0);
58 err
= bpf_map_update_elem(map_fds
[i
], &array_key
,
59 &array_magic_value
, 0);
62 /* Check getting map info */
63 info_len
= sizeof(struct bpf_map_info
) * 2;
64 bzero(&map_infos
[i
], info_len
);
65 err
= bpf_obj_get_info_by_fd(map_fds
[i
], &map_infos
[i
],
68 map_infos
[i
].type
!= BPF_MAP_TYPE_ARRAY
||
69 map_infos
[i
].key_size
!= sizeof(__u32
) ||
70 map_infos
[i
].value_size
!= sizeof(__u64
) ||
71 map_infos
[i
].max_entries
!= 1 ||
72 map_infos
[i
].map_flags
!= 0 ||
73 info_len
!= sizeof(struct bpf_map_info
) ||
74 strcmp((char *)map_infos
[i
].name
, expected_map_name
),
76 "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",
78 map_infos
[i
].type
, BPF_MAP_TYPE_ARRAY
,
79 info_len
, sizeof(struct bpf_map_info
),
80 map_infos
[i
].key_size
,
81 map_infos
[i
].value_size
,
82 map_infos
[i
].max_entries
,
83 map_infos
[i
].map_flags
,
84 map_infos
[i
].name
, expected_map_name
))
87 /* Check getting prog info */
88 info_len
= sizeof(struct bpf_prog_info
) * 2;
89 bzero(&prog_infos
[i
], info_len
);
90 bzero(jited_insns
, sizeof(jited_insns
));
91 bzero(xlated_insns
, sizeof(xlated_insns
));
92 prog_infos
[i
].jited_prog_insns
= ptr_to_u64(jited_insns
);
93 prog_infos
[i
].jited_prog_len
= sizeof(jited_insns
);
94 prog_infos
[i
].xlated_prog_insns
= ptr_to_u64(xlated_insns
);
95 prog_infos
[i
].xlated_prog_len
= sizeof(xlated_insns
);
96 prog_infos
[i
].map_ids
= ptr_to_u64(map_ids
+ i
);
97 prog_infos
[i
].nr_map_ids
= 2;
98 err
= clock_gettime(CLOCK_REALTIME
, &real_time_ts
);
100 err
= clock_gettime(CLOCK_BOOTTIME
, &boot_time_ts
);
102 err
= bpf_obj_get_info_by_fd(prog_fds
[i
], &prog_infos
[i
],
104 load_time
= (real_time_ts
.tv_sec
- boot_time_ts
.tv_sec
)
105 + (prog_infos
[i
].load_time
/ nsec_per_sec
);
107 prog_infos
[i
].type
!= BPF_PROG_TYPE_SOCKET_FILTER
||
108 info_len
!= sizeof(struct bpf_prog_info
) ||
109 (jit_enabled
&& !prog_infos
[i
].jited_prog_len
) ||
111 !memcmp(jited_insns
, zeros
, sizeof(zeros
))) ||
112 !prog_infos
[i
].xlated_prog_len
||
113 !memcmp(xlated_insns
, zeros
, sizeof(zeros
)) ||
114 load_time
< now
- 60 || load_time
> now
+ 60 ||
115 prog_infos
[i
].created_by_uid
!= my_uid
||
116 prog_infos
[i
].nr_map_ids
!= 1 ||
117 *(int *)(long)prog_infos
[i
].map_ids
!= map_infos
[i
].id
||
118 strcmp((char *)prog_infos
[i
].name
, expected_prog_name
),
120 "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",
122 prog_infos
[i
].type
, BPF_PROG_TYPE_SOCKET_FILTER
,
123 info_len
, sizeof(struct bpf_prog_info
),
125 prog_infos
[i
].jited_prog_len
,
126 prog_infos
[i
].xlated_prog_len
,
127 !!memcmp(jited_insns
, zeros
, sizeof(zeros
)),
128 !!memcmp(xlated_insns
, zeros
, sizeof(zeros
)),
130 prog_infos
[i
].created_by_uid
, my_uid
,
131 prog_infos
[i
].nr_map_ids
, 1,
132 *(int *)(long)prog_infos
[i
].map_ids
, map_infos
[i
].id
,
133 prog_infos
[i
].name
, expected_prog_name
))
137 /* Check bpf_prog_get_next_id() */
140 while (!bpf_prog_get_next_id(next_id
, &next_id
)) {
141 struct bpf_prog_info prog_info
= {};
145 info_len
= sizeof(prog_info
);
147 prog_fd
= bpf_prog_get_fd_by_id(next_id
);
148 if (prog_fd
< 0 && errno
== ENOENT
)
149 /* The bpf_prog is in the dead row */
151 if (CHECK(prog_fd
< 0, "get-prog-fd(next_id)",
152 "prog_fd %d next_id %d errno %d\n",
153 prog_fd
, next_id
, errno
))
156 for (i
= 0; i
< nr_iters
; i
++)
157 if (prog_infos
[i
].id
== next_id
)
166 * prog_info.nr_map_ids = 1
167 * prog_info.map_ids = NULL
169 prog_info
.nr_map_ids
= 1;
170 err
= bpf_obj_get_info_by_fd(prog_fd
, &prog_info
, &info_len
);
171 if (CHECK(!err
|| errno
!= EFAULT
,
172 "get-prog-fd-bad-nr-map-ids", "err %d errno %d(%d)",
175 bzero(&prog_info
, sizeof(prog_info
));
176 info_len
= sizeof(prog_info
);
178 saved_map_id
= *(int *)((long)prog_infos
[i
].map_ids
);
179 prog_info
.map_ids
= prog_infos
[i
].map_ids
;
180 prog_info
.nr_map_ids
= 2;
181 err
= bpf_obj_get_info_by_fd(prog_fd
, &prog_info
, &info_len
);
182 prog_infos
[i
].jited_prog_insns
= 0;
183 prog_infos
[i
].xlated_prog_insns
= 0;
184 CHECK(err
|| info_len
!= sizeof(struct bpf_prog_info
) ||
185 memcmp(&prog_info
, &prog_infos
[i
], info_len
) ||
186 *(int *)(long)prog_info
.map_ids
!= saved_map_id
,
187 "get-prog-info(next_id->fd)",
188 "err %d errno %d info_len %u(%zu) memcmp %d map_id %u(%u)\n",
189 err
, errno
, info_len
, sizeof(struct bpf_prog_info
),
190 memcmp(&prog_info
, &prog_infos
[i
], info_len
),
191 *(int *)(long)prog_info
.map_ids
, saved_map_id
);
194 CHECK(nr_id_found
!= nr_iters
,
195 "check total prog id found by get_next_id",
196 "nr_id_found %u(%u)\n",
197 nr_id_found
, nr_iters
);
199 /* Check bpf_map_get_next_id() */
202 while (!bpf_map_get_next_id(next_id
, &next_id
)) {
203 struct bpf_map_info map_info
= {};
206 info_len
= sizeof(map_info
);
208 map_fd
= bpf_map_get_fd_by_id(next_id
);
209 if (map_fd
< 0 && errno
== ENOENT
)
210 /* The bpf_map is in the dead row */
212 if (CHECK(map_fd
< 0, "get-map-fd(next_id)",
213 "map_fd %d next_id %u errno %d\n",
214 map_fd
, next_id
, errno
))
217 for (i
= 0; i
< nr_iters
; i
++)
218 if (map_infos
[i
].id
== next_id
)
226 err
= bpf_map_lookup_elem(map_fd
, &array_key
, &array_value
);
229 err
= bpf_obj_get_info_by_fd(map_fd
, &map_info
, &info_len
);
230 CHECK(err
|| info_len
!= sizeof(struct bpf_map_info
) ||
231 memcmp(&map_info
, &map_infos
[i
], info_len
) ||
232 array_value
!= array_magic_value
,
233 "check get-map-info(next_id->fd)",
234 "err %d errno %d info_len %u(%zu) memcmp %d array_value %llu(%llu)\n",
235 err
, errno
, info_len
, sizeof(struct bpf_map_info
),
236 memcmp(&map_info
, &map_infos
[i
], info_len
),
237 array_value
, array_magic_value
);
241 CHECK(nr_id_found
!= nr_iters
,
242 "check total map id found by get_next_id",
243 "nr_id_found %u(%u)\n",
244 nr_id_found
, nr_iters
);
247 for (i
= 0; i
< nr_iters
; i
++)
248 bpf_object__close(objs
[i
]);