mirror of
https://github.com/netdata/libbpf.git
synced 2026-11-05 17:30:15 +08:00
libbpf: Defer arena map size check to load time
init_arena_map_data() used the build-host page size while it opened an object. This could reject skeleton generation when the build host and target use different page sizes. Validate the size during load, before libbpf calculates the arena data offset. This uses the running kernel page size and rejects an undersized map before relocation. This problem manifested when cross compiling BPF selftests for arm64 (64K page) on x86 (4K page). In this setup skeleton generation fails. Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com> Link: https://lore.kernel.org/bpf/20260908-libbpf_arena_thing-v1-1-0092c0e0d91b@meta.com
This commit is contained in:
1 parent
b9c8ceca9c
commit
4ea184df98
1 file changed
+13
-18
+13
-18
@@ -3018,20 +3018,8 @@ static int bpf_object__init_user_btf_map(struct bpf_object *obj,
|
||||
}
|
||||
|
||||
static int init_arena_map_data(struct bpf_object *obj, struct bpf_map *map,
|
||||
const char *sec_name, int sec_idx,
|
||||
void *data, size_t data_sz)
|
||||
{
|
||||
const long page_sz = sysconf(_SC_PAGE_SIZE);
|
||||
const size_t data_alloc_sz = roundup(data_sz, page_sz);
|
||||
size_t mmap_sz;
|
||||
|
||||
mmap_sz = bpf_map_mmap_sz(map);
|
||||
if (data_alloc_sz > mmap_sz) {
|
||||
pr_warn("elf: sec '%s': declared ARENA map size (%zu) is too small to hold global __arena variables of size %zu\n",
|
||||
sec_name, mmap_sz, data_sz);
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
obj->arena_data = malloc(data_sz);
|
||||
if (!obj->arena_data)
|
||||
return -ENOMEM;
|
||||
@@ -3107,8 +3095,7 @@ static int bpf_object__init_user_btf_maps(struct bpf_object *obj, bool strict,
|
||||
obj->arena_map_idx = i;
|
||||
|
||||
if (obj->efile.arena_data) {
|
||||
err = init_arena_map_data(obj, map, ARENA_SEC, obj->efile.arena_data_shndx,
|
||||
obj->efile.arena_data->d_buf,
|
||||
err = init_arena_map_data(obj, map, obj->efile.arena_data->d_buf,
|
||||
obj->efile.arena_data->d_size);
|
||||
if (err)
|
||||
return err;
|
||||
@@ -7489,12 +7476,20 @@ static int bpf_object__relocate(struct bpf_object *obj, const char *targ_btf_pat
|
||||
bpf_object__sort_relos(obj);
|
||||
}
|
||||
|
||||
/* place globals at the end of the arena (if supported) */
|
||||
if (obj->arena_map_idx >= 0 && kernel_supports(obj, FEAT_LDIMM64_FULL_RANGE_OFF)) {
|
||||
if (obj->arena_map_idx >= 0) {
|
||||
struct bpf_map *arena_map = &obj->maps[obj->arena_map_idx];
|
||||
size_t data_sz = roundup(obj->arena_data_sz, sysconf(_SC_PAGE_SIZE));
|
||||
size_t mmap_sz = bpf_map_mmap_sz(arena_map);
|
||||
|
||||
obj->arena_data_off = bpf_map_mmap_sz(arena_map) -
|
||||
roundup(obj->arena_data_sz, sysconf(_SC_PAGE_SIZE));
|
||||
if (data_sz > mmap_sz) {
|
||||
pr_warn("map '%s': declared ARENA map size (%zu) is too small to hold global __arena variables of size %zu\n",
|
||||
arena_map->name, mmap_sz, obj->arena_data_sz);
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
/* place globals at the end of the arena (if supported) */
|
||||
if (kernel_supports(obj, FEAT_LDIMM64_FULL_RANGE_OFF))
|
||||
obj->arena_data_off = mmap_sz - data_sz;
|
||||
}
|
||||
|
||||
/* Before relocating calls pre-process relocations and mark
|
||||
|
||||
Reference in new issue
Block a user