* [PATCH bpf-next] libbpf: defer arena map size check to load time
@ 2026-09-08 17:25 Mykyta Yatsenko
2026-09-08 17:38 ` sashiko-bot
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Mykyta Yatsenko @ 2026-09-08 17:25 UTC (permalink / raw)
To: bpf, ast, andrii, daniel, kernel-team, eddyz87, memxor; +Cc: Mykyta Yatsenko
From: Mykyta Yatsenko <yatsenko@meta.com>
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>
---
tools/lib/bpf/libbpf.c | 31 +++++++++++++------------------
1 file changed, 13 insertions(+), 18 deletions(-)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index c036e8a91ed8..413b8b305194 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -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);
+
+ if (obj->arena_data && 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;
+ }
- obj->arena_data_off = bpf_map_mmap_sz(arena_map) -
- roundup(obj->arena_data_sz, sysconf(_SC_PAGE_SIZE));
+ /* 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
---
base-commit: 3fa3128887a4df6057c543aae7c5c7fd2ed41f12
change-id: 20260908-libbpf_arena_thing-0d63a985f4f3
Best regards,
--
Mykyta Yatsenko <yatsenko@meta.com>
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH bpf-next] libbpf: defer arena map size check to load time
2026-09-08 17:25 [PATCH bpf-next] libbpf: defer arena map size check to load time Mykyta Yatsenko
@ 2026-09-08 17:38 ` sashiko-bot
2026-09-08 18:07 ` bot+bpf-ci
2026-09-08 19:37 ` Emil Tsalapatis
2 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-09-08 17:38 UTC (permalink / raw)
To: Mykyta Yatsenko; +Cc: bpf
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] NULL pointer dereference in init_arena_map_data() when processing a SHT_NOBITS .arena section.
--
commit 839c80f912fa6d6c52eb18408dfd0437488f602b
Author: Mykyta Yatsenko <yatsenko@meta.com>
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.
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index c036e8a91ed88..413b8b305194e 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
[ ... ]
> @@ -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);
[Severity: High]
This isn't a bug introduced by this patch, but can we pass a NULL pointer to
init_arena_map_data() here?
If the ELF section is of type SHT_NOBITS with a non-zero size, elf_getdata()
can return an Elf_Data structure where d_buf is NULL but d_size is non-zero.
In that case, bpf_object__init_user_btf_maps() passes a NULL data pointer
to init_arena_map_data(), which then executes:
tools/lib/bpf/libbpf.c:init_arena_map_data() {
...
memcpy(obj->arena_data, data, data_sz);
...
}
leading to a NULL pointer dereference. Could we validate that d_buf is not
NULL before calling memcpy, or handle SHT_NOBITS sections differently?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260908-libbpf_arena_thing-v1-1-0092c0e0d91b@meta.com?part=1
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH bpf-next] libbpf: defer arena map size check to load time
2026-09-08 17:25 [PATCH bpf-next] libbpf: defer arena map size check to load time Mykyta Yatsenko
2026-09-08 17:38 ` sashiko-bot
@ 2026-09-08 18:07 ` bot+bpf-ci
2026-09-08 19:37 ` Emil Tsalapatis
2 siblings, 0 replies; 5+ messages in thread
From: bot+bpf-ci @ 2026-09-08 18:07 UTC (permalink / raw)
To: mykyta.yatsenko5, bpf, ast, andrii, daniel, kernel-team, eddyz87,
memxor
Cc: yatsenko, ast, andrii, daniel, martin.lau, eddyz87, yonghong.song,
mason, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 2703 bytes --]
> 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>
This isn't a bug, but could the changelog say "before the arena data
offset is computed" rather than "before relocation"? The check sits
inside bpf_object__relocate(), after the CO-RE pass
(bpf_object__relocate_core) has already run.
This looks like a bug fix for cross-compilation with different page
sizes. Should this include a Fixes: tag pointing to the commit that
added init_arena_map_data()?
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index c036e8a91ed8..413b8b305194 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
[ ... ]
> @@ -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);
> +
> + if (obj->arena_data && 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;
> + }
This isn't a bug, but is the obj->arena_data && term doing any work
here? Since data_sz is derived from obj->arena_data_sz and both
obj->arena_data and obj->arena_data_sz are set together in
init_arena_map_data(), data_sz > mmap_sz already implies
obj->arena_data_sz > 0, which means obj->arena_data != NULL.
> + /* 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;
> }
[ ... ]
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/34258328082
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH bpf-next] libbpf: defer arena map size check to load time
2026-09-08 17:25 [PATCH bpf-next] libbpf: defer arena map size check to load time Mykyta Yatsenko
2026-09-08 17:38 ` sashiko-bot
2026-09-08 18:07 ` bot+bpf-ci
@ 2026-09-08 19:37 ` Emil Tsalapatis
2026-09-11 17:27 ` Andrii Nakryiko
2 siblings, 1 reply; 5+ messages in thread
From: Emil Tsalapatis @ 2026-09-08 19:37 UTC (permalink / raw)
To: Mykyta Yatsenko
Cc: bpf, ast, andrii, daniel, kernel-team, eddyz87, memxor,
Mykyta Yatsenko
On Tue, Sep 8, 2026 at 3:33 PM Mykyta Yatsenko
<mykyta.yatsenko5@gmail.com> wrote:
>
> From: Mykyta Yatsenko <yatsenko@meta.com>
>
> 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>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
The bots have a point about the unnecesary check, but not about the
NOBITS section.
> ---
> tools/lib/bpf/libbpf.c | 31 +++++++++++++------------------
> 1 file changed, 13 insertions(+), 18 deletions(-)
>
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index c036e8a91ed8..413b8b305194 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -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);
> +
> + if (obj->arena_data && 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;
> + }
>
> - obj->arena_data_off = bpf_map_mmap_sz(arena_map) -
> - roundup(obj->arena_data_sz, sysconf(_SC_PAGE_SIZE));
> + /* 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
>
> ---
> base-commit: 3fa3128887a4df6057c543aae7c5c7fd2ed41f12
> change-id: 20260908-libbpf_arena_thing-0d63a985f4f3
>
> Best regards,
> --
> Mykyta Yatsenko <yatsenko@meta.com>
>
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH bpf-next] libbpf: defer arena map size check to load time
2026-09-08 19:37 ` Emil Tsalapatis
@ 2026-09-11 17:27 ` Andrii Nakryiko
0 siblings, 0 replies; 5+ messages in thread
From: Andrii Nakryiko @ 2026-09-11 17:27 UTC (permalink / raw)
To: Emil Tsalapatis
Cc: Mykyta Yatsenko, bpf, ast, andrii, daniel, kernel-team, eddyz87,
memxor, Mykyta Yatsenko
On Tue, Sep 8, 2026 at 12:37 PM Emil Tsalapatis <emil@etsalapatis.com> wrote:
>
> On Tue, Sep 8, 2026 at 3:33 PM Mykyta Yatsenko
> <mykyta.yatsenko5@gmail.com> wrote:
> >
> > From: Mykyta Yatsenko <yatsenko@meta.com>
> >
> > 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>
>
> Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
>
> The bots have a point about the unnecesary check, but not about the
> NOBITS section.
>
> > ---
> > tools/lib/bpf/libbpf.c | 31 +++++++++++++------------------
> > 1 file changed, 13 insertions(+), 18 deletions(-)
> >
> > diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> > index c036e8a91ed8..413b8b305194 100644
> > --- a/tools/lib/bpf/libbpf.c
> > +++ b/tools/lib/bpf/libbpf.c
> > @@ -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);
> > +
> > + if (obj->arena_data && data_sz > mmap_sz) {
dropped arena_data check while applying
> > + 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;
> > + }
> >
> > - obj->arena_data_off = bpf_map_mmap_sz(arena_map) -
> > - roundup(obj->arena_data_sz, sysconf(_SC_PAGE_SIZE));
> > + /* 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
> >
> > ---
> > base-commit: 3fa3128887a4df6057c543aae7c5c7fd2ed41f12
> > change-id: 20260908-libbpf_arena_thing-0d63a985f4f3
> >
> > Best regards,
> > --
> > Mykyta Yatsenko <yatsenko@meta.com>
> >
> >
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-09-11 17:28 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-08 17:25 [PATCH bpf-next] libbpf: defer arena map size check to load time Mykyta Yatsenko
2026-09-08 17:38 ` sashiko-bot
2026-09-08 18:07 ` bot+bpf-ci
2026-09-08 19:37 ` Emil Tsalapatis
2026-09-11 17:27 ` Andrii Nakryiko
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.