* [PATCH bpf-next 1/4] libarena: remove in-code licenses
2026-10-27 16:29 [PATCH bpf-next 0/4] selftests/bpf: libarena: compatibility fixups Emil Tsalapatis
@ 2026-10-27 16:29 ` Emil Tsalapatis
2026-10-27 16:36 ` sashiko-bot
2026-10-27 16:29 ` [PATCH bpf-next 2/4] selftests/bpf: libarena: make allocator growth on alloc failure optional Emil Tsalapatis
` (2 subsequent siblings)
3 siblings, 1 reply; 7+ messages in thread
From: Emil Tsalapatis @ 2026-10-27 16:29 UTC (permalink / raw)
To: bpf; +Cc: ast, andrii, eddyz87, memxor, daniel, Emil Tsalapatis
The libarena code currently specifies a license section in multiple
locations. These sections are a) inaccurate, since the license is
actually Dual BSD/GPL, not pure GPL, and b) superfluous, since the
files already have the license on them and libarena is distributed
as a source. Remove the license strings: The code that includes the
the libarena sources should be the one with the license section.
Signed-off-by: Emil Tsalapatis <emil@etsalapatis.com>
---
tools/testing/selftests/bpf/libarena/src/asan.bpf.c | 2 --
tools/testing/selftests/bpf/libarena/src/buddy.bpf.c | 2 --
tools/testing/selftests/bpf/libarena/src/common.bpf.c | 2 --
3 files changed, 6 deletions(-)
diff --git a/tools/testing/selftests/bpf/libarena/src/asan.bpf.c b/tools/testing/selftests/bpf/libarena/src/asan.bpf.c
index de656b69d13a..8a0f06110606 100644
--- a/tools/testing/selftests/bpf/libarena/src/asan.bpf.c
+++ b/tools/testing/selftests/bpf/libarena/src/asan.bpf.c
@@ -532,5 +532,3 @@ __weak __noasan int asan_init(struct asan_init_args *args)
#pragma clang attribute pop
#endif /* BPF_ARENA_ASAN */
-
-__weak char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/libarena/src/buddy.bpf.c b/tools/testing/selftests/bpf/libarena/src/buddy.bpf.c
index 2490ab1396de..552ce87875e3 100644
--- a/tools/testing/selftests/bpf/libarena/src/buddy.bpf.c
+++ b/tools/testing/selftests/bpf/libarena/src/buddy.bpf.c
@@ -899,5 +899,3 @@ __weak int buddy_free(struct buddy __arena *buddy, void __arena *addr)
return ret;
}
-
-__weak char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/libarena/src/common.bpf.c b/tools/testing/selftests/bpf/libarena/src/common.bpf.c
index d1af60b81838..d859bd538c52 100644
--- a/tools/testing/selftests/bpf/libarena/src/common.bpf.c
+++ b/tools/testing/selftests/bpf/libarena/src/common.bpf.c
@@ -85,5 +85,3 @@ __weak void arena_free(void __arena *ptr)
{
buddy_free(&buddy, ptr);
}
-
-char _license[] SEC("license") = "GPL";
--
2.52.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH bpf-next 1/4] libarena: remove in-code licenses
2026-10-27 16:29 ` [PATCH bpf-next 1/4] libarena: remove in-code licenses Emil Tsalapatis
@ 2026-10-27 16:36 ` sashiko-bot
0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-10-27 16:36 UTC (permalink / raw)
To: Emil Tsalapatis, bpf
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] selftests/bpf: missing license section in libarena_bench.bpf.o
--
commit 1bfbb56cf90063a6a767e7e64926692dd815ff9b
Author: Emil Tsalapatis <emil@etsalapatis.com>
libarena: remove in-code licenses
This commit removes the SEC("license") definitions from the libarena BPF
source files (asan.bpf.c, buddy.bpf.c, and common.bpf.c) so that consumers
of libarena provide their own license section.
> diff --git a/tools/testing/selftests/bpf/libarena/src/asan.bpf.c b/tools/testing/selftests/bpf/libarena/src/asan.bpf.c
> index de656b69d13af..8a0f061106064 100644
> --- a/tools/testing/selftests/bpf/libarena/src/asan.bpf.c
> +++ b/tools/testing/selftests/bpf/libarena/src/asan.bpf.c
> @@ -532,5 +532,3 @@ __weak __noasan int asan_init(struct asan_init_args *args)
> #pragma clang attribute pop
>
> #endif /* BPF_ARENA_ASAN */
> -
> -__weak char _license[] SEC("license") = "GPL";
> diff --git a/tools/testing/selftests/bpf/libarena/src/buddy.bpf.c b/tools/testing/selftests/bpf/libarena/src/buddy.bpf.c
> index 2490ab1396de0..552ce87875e3b 100644
> --- a/tools/testing/selftests/bpf/libarena/src/buddy.bpf.c
> +++ b/tools/testing/selftests/bpf/libarena/src/buddy.bpf.c
> @@ -899,5 +899,3 @@ __weak int buddy_free(struct buddy __arena *buddy, void __arena *addr)
>
> return ret;
> }
> -
> -__weak char _license[] SEC("license") = "GPL";
> diff --git a/tools/testing/selftests/bpf/libarena/src/common.bpf.c b/tools/testing/selftests/bpf/libarena/src/common.bpf.c
> index d1af60b818389..d859bd538c52d 100644
> --- a/tools/testing/selftests/bpf/libarena/src/common.bpf.c
> +++ b/tools/testing/selftests/bpf/libarena/src/common.bpf.c
> @@ -85,5 +85,3 @@ __weak void arena_free(void __arena *ptr)
> {
> buddy_free(&buddy, ptr);
> }
> -
> -char _license[] SEC("license") = "GPL";
[Severity: Medium]
Does removing _license from common.bpf.c, buddy.bpf.c, and asan.bpf.c leave
libarena_bench.bpf.o without a license section and break the libarena
benchmarks at load time?
In tools/testing/selftests/bpf/libarena/Makefile, libarena_bench.bpf.o is
linked solely from LIBARENA_CORE_SOURCES and LIBARENA_BENCH_SOURCES:
LIBARENA_BENCH_OBJECTS = $(notdir $(LIBARENA_CORE_SOURCES:.bpf.c=.bpf.o) \
$(LIBARENA_BENCH_SOURCES:.bpf.c=.bpf.o))
Unlike the selftests in selftests/test_buddy.bpf.c and
selftests/test_asan_buddy.bpf.c, the benchmark source in
tools/testing/selftests/bpf/libarena/benchs/bench_malloc.bpf.c does not
define a SEC("license") section.
When running the libarena-malloc or libarena-calloc benchmarks in
tools/testing/selftests/bpf/benchs/bench_libarena.c:
malloc_setup() / calloc_setup()
-> setup_common()
-> libarena_bench__open_and_load()
libarena_bench.bpf.o now loads with an empty license string, so the BPF
verifier rejects the programs with -EINVAL when checking GPL compatibility
for their kfunc calls, kernel BTF accesses, and bpf_trace_printk usage.
Should tools/testing/selftests/bpf/libarena/benchs/bench_malloc.bpf.c define
a SEC("license") section now that the core library sources no longer provide
one?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261027162916.10996-1-emil@etsalapatis.com?part=1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH bpf-next 2/4] selftests/bpf: libarena: make allocator growth on alloc failure optional
2026-10-27 16:29 [PATCH bpf-next 0/4] selftests/bpf: libarena: compatibility fixups Emil Tsalapatis
2026-10-27 16:29 ` [PATCH bpf-next 1/4] libarena: remove in-code licenses Emil Tsalapatis
@ 2026-10-27 16:29 ` Emil Tsalapatis
2026-10-27 16:29 ` [PATCH bpf-next 3/4] selftests/bpf: libarena: add explicit buddy_grow() call Emil Tsalapatis
2026-10-27 16:29 ` [PATCH bpf-next 4/4] selftests/bpf: libarena: Make zero variable type __u32 instead of u32 Emil Tsalapatis
3 siblings, 0 replies; 7+ messages in thread
From: Emil Tsalapatis @ 2026-10-27 16:29 UTC (permalink / raw)
To: bpf; +Cc: ast, andrii, eddyz87, memxor, daniel, Emil Tsalapatis
The buddy allocator currently always grows when an allocation fails due
to a lack of allocated arena pages. This behavior assumes that the user
sizes the arena to be as large as the maximum allocation size, but that
is not always the case.
Add a nogrow allocation option for users that want to explicitly control
the total mapped size of the arena. With this API, an allocation request
that cannot be serviced from currently mapped arena pages fails instead
of triggering bpf_arena_alloc_pages(). The user instead explicitly maps
additional memory into the arena with a separate buddy_grow() call.
Signed-off-by: Emil Tsalapatis <emil@etsalapatis.com>
---
.../bpf/libarena/include/libarena/buddy.h | 1 +
.../selftests/bpf/libarena/src/buddy.bpf.c | 20 +++++++++++++++++--
2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/bpf/libarena/include/libarena/buddy.h b/tools/testing/selftests/bpf/libarena/include/libarena/buddy.h
index 528c69a1f38e..958450fc5f9d 100644
--- a/tools/testing/selftests/bpf/libarena/include/libarena/buddy.h
+++ b/tools/testing/selftests/bpf/libarena/include/libarena/buddy.h
@@ -77,5 +77,6 @@ int buddy_init(struct buddy __arena *buddy);
int buddy_destroy(struct buddy __arena *buddy);
int buddy_free(struct buddy __arena *buddy, void __arena *free);
void __arena *buddy_alloc(struct buddy __arena *buddy, size_t size);
+void __arena *buddy_alloc_nogrow(struct buddy __arena *buddy, size_t size);
#endif /* __BPF__ */
diff --git a/tools/testing/selftests/bpf/libarena/src/buddy.bpf.c b/tools/testing/selftests/bpf/libarena/src/buddy.bpf.c
index 552ce87875e3..ed359d4af1f4 100644
--- a/tools/testing/selftests/bpf/libarena/src/buddy.bpf.c
+++ b/tools/testing/selftests/bpf/libarena/src/buddy.bpf.c
@@ -747,8 +747,9 @@ static u64 buddy_alloc_from_new_chunk(struct buddy __arena *buddy, struct buddy_
return (u64)address;
}
-__weak
-void __arena *buddy_alloc(struct buddy __arena *buddy, size_t size)
+
+static __always_inline
+void __arena *buddy_alloc_maygrow(struct buddy __arena *buddy, size_t size, bool grow)
{
void __arena *address = NULL;
struct buddy_chunk __arena *chunk;
@@ -772,6 +773,9 @@ void __arena *buddy_alloc(struct buddy __arena *buddy, size_t size)
if (address)
goto done;
+ if (!grow)
+ return NULL;
+
/* Get a new chunk. */
chunk = buddy_chunk_get(buddy);
if (chunk)
@@ -796,6 +800,18 @@ void __arena *buddy_alloc(struct buddy __arena *buddy, size_t size)
return address;
}
+__weak
+void __arena *buddy_alloc(struct buddy __arena *buddy, size_t size)
+{
+ return buddy_alloc_maygrow(buddy, size, true);
+}
+
+__weak
+void __arena *buddy_alloc_nogrow(struct buddy __arena *buddy, size_t size)
+{
+ return buddy_alloc_maygrow(buddy, size, false);
+}
+
static __always_inline int buddy_free_unlocked(struct buddy __arena *buddy, u64 addr)
{
struct buddy_header __arena *header, *buddy_header;
--
2.52.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH bpf-next 3/4] selftests/bpf: libarena: add explicit buddy_grow() call
2026-10-27 16:29 [PATCH bpf-next 0/4] selftests/bpf: libarena: compatibility fixups Emil Tsalapatis
2026-10-27 16:29 ` [PATCH bpf-next 1/4] libarena: remove in-code licenses Emil Tsalapatis
2026-10-27 16:29 ` [PATCH bpf-next 2/4] selftests/bpf: libarena: make allocator growth on alloc failure optional Emil Tsalapatis
@ 2026-10-27 16:29 ` Emil Tsalapatis
2026-10-27 16:52 ` sashiko-bot
2026-10-27 16:29 ` [PATCH bpf-next 4/4] selftests/bpf: libarena: Make zero variable type __u32 instead of u32 Emil Tsalapatis
3 siblings, 1 reply; 7+ messages in thread
From: Emil Tsalapatis @ 2026-10-27 16:29 UTC (permalink / raw)
To: bpf; +Cc: ast, andrii, eddyz87, memxor, daniel, Emil Tsalapatis
Add an API call for explicitly growing the arena through
page allocation. Useful for programs that do not do so
implicitly through buddy_alloc().
Signed-off-by: Emil Tsalapatis <emil@etsalapatis.com>
---
.../bpf/libarena/include/libarena/buddy.h | 1 +
.../selftests/bpf/libarena/src/buddy.bpf.c | 26 +++++++++++++++++++
2 files changed, 27 insertions(+)
diff --git a/tools/testing/selftests/bpf/libarena/include/libarena/buddy.h b/tools/testing/selftests/bpf/libarena/include/libarena/buddy.h
index 958450fc5f9d..4cad0649dc17 100644
--- a/tools/testing/selftests/bpf/libarena/include/libarena/buddy.h
+++ b/tools/testing/selftests/bpf/libarena/include/libarena/buddy.h
@@ -78,5 +78,6 @@ int buddy_destroy(struct buddy __arena *buddy);
int buddy_free(struct buddy __arena *buddy, void __arena *free);
void __arena *buddy_alloc(struct buddy __arena *buddy, size_t size);
void __arena *buddy_alloc_nogrow(struct buddy __arena *buddy, size_t size);
+int buddy_grow(struct buddy __arena *buddy, size_t size);
#endif /* __BPF__ */
diff --git a/tools/testing/selftests/bpf/libarena/src/buddy.bpf.c b/tools/testing/selftests/bpf/libarena/src/buddy.bpf.c
index ed359d4af1f4..f06b6bd5c088 100644
--- a/tools/testing/selftests/bpf/libarena/src/buddy.bpf.c
+++ b/tools/testing/selftests/bpf/libarena/src/buddy.bpf.c
@@ -812,6 +812,32 @@ void __arena *buddy_alloc_nogrow(struct buddy __arena *buddy, size_t size)
return buddy_alloc_maygrow(buddy, size, false);
}
+__weak
+int buddy_grow(struct buddy __arena *buddy, size_t size)
+{
+ struct buddy_chunk __arena *chunk;
+ unsigned long flags;
+ int i;
+
+ for (i = zero; i < size && can_loop; i++) {
+ chunk = buddy_chunk_get(buddy);
+ if (!chunk)
+ return -ENOMEM;
+
+ if (buddy_lock(buddy, flags)) {
+ bpf_arena_free_pages(&arena, chunk, BUDDY_CHUNK_PAGES);
+ return -ENOMEM;
+ }
+
+ chunk->next = buddy->first_chunk;
+ buddy->first_chunk = chunk;
+
+ buddy_unlock(buddy, flags);
+ }
+
+ return 0;
+}
+
static __always_inline int buddy_free_unlocked(struct buddy __arena *buddy, u64 addr)
{
struct buddy_header __arena *header, *buddy_header;
--
2.52.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH bpf-next 3/4] selftests/bpf: libarena: add explicit buddy_grow() call
2026-10-27 16:29 ` [PATCH bpf-next 3/4] selftests/bpf: libarena: add explicit buddy_grow() call Emil Tsalapatis
@ 2026-10-27 16:52 ` sashiko-bot
0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-10-27 16:52 UTC (permalink / raw)
To: Emil Tsalapatis, bpf
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] selftests/bpf: buddy_grow() treats byte size parameter as 1 MiB chunk count
--
commit 423ea247cbc2154b99ae3fbf8b3a6fc0e7d6e98f
Author: Emil Tsalapatis <emil@etsalapatis.com>
selftests/bpf: libarena: add explicit buddy_grow() call
This commit adds buddy_grow() to libarena to allow BPF programs to
explicitly grow the buddy allocator arena instead of relying on implicit
growth during buddy_alloc().
> diff --git a/tools/testing/selftests/bpf/libarena/include/libarena/buddy.h b/tools/testing/selftests/bpf/libarena/include/libarena/buddy.h
> index 958450fc5f9db..4cad0649dc17a 100644
> --- a/tools/testing/selftests/bpf/libarena/include/libarena/buddy.h
> +++ b/tools/testing/selftests/bpf/libarena/include/libarena/buddy.h
> @@ -78,5 +78,6 @@ int buddy_destroy(struct buddy __arena *buddy);
> int buddy_free(struct buddy __arena *buddy, void __arena *free);
> void __arena *buddy_alloc(struct buddy __arena *buddy, size_t size);
> void __arena *buddy_alloc_nogrow(struct buddy __arena *buddy, size_t size);
> +int buddy_grow(struct buddy __arena *buddy, size_t size);
>
> #endif /* __BPF__ */
> diff --git a/tools/testing/selftests/bpf/libarena/src/buddy.bpf.c b/tools/testing/selftests/bpf/libarena/src/buddy.bpf.c
> index ed359d4af1f4b..f06b6bd5c088e 100644
> --- a/tools/testing/selftests/bpf/libarena/src/buddy.bpf.c
> +++ b/tools/testing/selftests/bpf/libarena/src/buddy.bpf.c
> @@ -812,6 +812,32 @@ void __arena *buddy_alloc_nogrow(struct buddy __arena *buddy, size_t size)
> return buddy_alloc_maygrow(buddy, size, false);
> }
>
> +__weak
> +int buddy_grow(struct buddy __arena *buddy, size_t size)
> +{
> + struct buddy_chunk __arena *chunk;
> + unsigned long flags;
> + int i;
> +
> + for (i = zero; i < size && can_loop; i++) {
> + chunk = buddy_chunk_get(buddy);
> + if (!chunk)
> + return -ENOMEM;
[Severity: Medium]
In tools/testing/selftests/bpf/libarena/include/libarena/buddy.h,
buddy_grow() is declared right below buddy_alloc() and
buddy_alloc_nogrow() with the same size_t size parameter, which takes a
size in bytes in those functions.
In tools/testing/selftests/bpf/libarena/src/buddy.bpf.c, buddy_grow() uses
size directly as the loop trip count for buddy_chunk_get(buddy). Each call
to buddy_chunk_get() allocates a 1 MiB chunk (BUDDY_CHUNK_BYTES, or
BUDDY_CHUNK_PAGES = 256 pages) out of the 1 GiB reserved virtual address
range (BUDDY_VADDR_SIZE = 1024 chunks).
If a caller passes a byte count (consistent with buddy_alloc()) or a page
count to buddy_grow(buddy, size), it will allocate size 1 MiB chunks, and
any size greater than 1024 will exhaust BUDDY_VADDR_SIZE and fail with
-ENOMEM while leaving the 1024 allocated chunks attached to
buddy->first_chunk.
Should buddy_grow() convert a byte size into the number of chunks to
allocate, or should the parameter be renamed (for example, to nr_chunks)
and documented to make the unit explicit?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261027162916.10996-1-emil@etsalapatis.com?part=3
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH bpf-next 4/4] selftests/bpf: libarena: Make zero variable type __u32 instead of u32
2026-10-27 16:29 [PATCH bpf-next 0/4] selftests/bpf: libarena: compatibility fixups Emil Tsalapatis
` (2 preceding siblings ...)
2026-10-27 16:29 ` [PATCH bpf-next 3/4] selftests/bpf: libarena: add explicit buddy_grow() call Emil Tsalapatis
@ 2026-10-27 16:29 ` Emil Tsalapatis
3 siblings, 0 replies; 7+ messages in thread
From: Emil Tsalapatis @ 2026-10-27 16:29 UTC (permalink / raw)
To: bpf; +Cc: ast, andrii, eddyz87, memxor, daniel, Emil Tsalapatis
Change the zero variable used for loop convergence to the user-visible
__u32 type to avoid missing type issues when including the skeleton
in userspace.
Signed-off-by: Emil Tsalapatis <emil@etsalapatis.com>
---
tools/testing/selftests/bpf/libarena/include/libarena/common.h | 2 +-
tools/testing/selftests/bpf/libarena/src/common.bpf.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/bpf/libarena/include/libarena/common.h b/tools/testing/selftests/bpf/libarena/include/libarena/common.h
index a6220355a697..940e82cc2928 100644
--- a/tools/testing/selftests/bpf/libarena/include/libarena/common.h
+++ b/tools/testing/selftests/bpf/libarena/include/libarena/common.h
@@ -43,7 +43,7 @@ struct {
* imprecise. To force the variable to be imprecise, initialize it with
* the opaque volatile variable 0 instead of the constant 0.
*/
-volatile u32 zero __weak;
+volatile __u32 zero __weak;
extern volatile u64 asan_violated;
int arena_fls(__u64 word);
diff --git a/tools/testing/selftests/bpf/libarena/src/common.bpf.c b/tools/testing/selftests/bpf/libarena/src/common.bpf.c
index d859bd538c52..c3c5326d8ca2 100644
--- a/tools/testing/selftests/bpf/libarena/src/common.bpf.c
+++ b/tools/testing/selftests/bpf/libarena/src/common.bpf.c
@@ -7,7 +7,7 @@
#include <libarena/buddy.h>
struct buddy __arena buddy;
-volatile u32 zero = 0;
+volatile __u32 zero = 0;
/*
* Storage for the queue nodes declared by bpf_arena_spin_lock.h. Each program
--
2.52.0
^ permalink raw reply related [flat|nested] 7+ messages in thread