* [PATCH bpf] libbpf: Reject excessive program counts in generated loaders
@ 2026-10-28 18:39 Mahe Tardy
2026-10-29 16:10 ` patchwork-bot+netdevbpf
2026-10-29 16:33 ` Alexei Starovoitov
0 siblings, 2 replies; 4+ messages in thread
From: Mahe Tardy @ 2026-10-28 18:39 UTC (permalink / raw)
To: bpf
Cc: Andrii Nakryiko, Eduard Zingerman, Ihor Solodrai,
Alexei Starovoitov, Daniel Borkmann, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, linux-kernel, John Fastabend, Mahe Tardy
An object containing MAX_USED_PROGS+1 (33) programs successfully
produces a light skeleton that laters fails at load time with -EACCES
because saving the 33rd FD emits a store at r10 + 0:
*(u32 *)(r10 +0) = r7
invalid write to stack R10 off=0 size=4
This catches the unsupported count during generation instead of
producing a loader that the verifier rejects later.
Fixes: 67234743736a ("libbpf: Generate loader program out of BPF ELF file.")
Signed-off-by: Mahe Tardy <mahe.tardy@gmail.com>
---
tools/lib/bpf/gen_loader.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/tools/lib/bpf/gen_loader.c b/tools/lib/bpf/gen_loader.c
index 251392aa8b41..80a6b5306183 100644
--- a/tools/lib/bpf/gen_loader.c
+++ b/tools/lib/bpf/gen_loader.c
@@ -122,6 +122,11 @@ void bpf_gen__init(struct bpf_gen *gen, int log_level, int nr_progs, int nr_maps
gen->log_level = log_level;
gen->nr_obj_maps = nr_maps;
gen->max_func_ptr_maps = max_func_ptr_maps;
+ if (nr_progs > MAX_USED_PROGS) {
+ pr_warn("Total programs exceeds %d\n", MAX_USED_PROGS);
+ gen->error = -E2BIG;
+ return;
+ }
if (nr_maps + max_func_ptr_maps > MAX_USED_MAPS) {
pr_warn("Total maps exceeds %d\n", MAX_USED_MAPS);
gen->error = -E2BIG;
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH bpf] libbpf: Reject excessive program counts in generated loaders 2026-10-28 18:39 [PATCH bpf] libbpf: Reject excessive program counts in generated loaders Mahe Tardy @ 2026-10-29 16:10 ` patchwork-bot+netdevbpf 2026-10-29 16:33 ` Alexei Starovoitov 1 sibling, 0 replies; 4+ messages in thread From: patchwork-bot+netdevbpf @ 2026-10-29 16:10 UTC (permalink / raw) To: Mahe Tardy Cc: bpf, andrii, eddyz87, ihor.solodrai, ast, daniel, memxor, martin.lau, song, yonghong.song, jolsa, emil, linux-kernel, john.fastabend Hello: This patch was applied to bpf/bpf-next.git (master) by Andrii Nakryiko <andrii@kernel.org>: On Wed, 28 Oct 2026 18:39:47 +0000 you wrote: > An object containing MAX_USED_PROGS+1 (33) programs successfully > produces a light skeleton that laters fails at load time with -EACCES > because saving the 33rd FD emits a store at r10 + 0: > > *(u32 *)(r10 +0) = r7 > invalid write to stack R10 off=0 size=4 > > [...] Here is the summary with links: - [bpf] libbpf: Reject excessive program counts in generated loaders https://git.kernel.org/bpf/bpf-next/c/aac5ba0a4d52 You are awesome, thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH bpf] libbpf: Reject excessive program counts in generated loaders 2026-10-28 18:39 [PATCH bpf] libbpf: Reject excessive program counts in generated loaders Mahe Tardy 2026-10-29 16:10 ` patchwork-bot+netdevbpf @ 2026-10-29 16:33 ` Alexei Starovoitov 2026-10-29 20:03 ` Mahe Tardy 1 sibling, 1 reply; 4+ messages in thread From: Alexei Starovoitov @ 2026-10-29 16:33 UTC (permalink / raw) To: Mahe Tardy, bpf Cc: Andrii Nakryiko, Eduard Zingerman, Ihor Solodrai, Daniel Borkmann, Kumar Kartikeya Dwivedi, Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, linux-kernel, John Fastabend On Wed, Oct 28, 2026 at 11:39 AM Mahe Tardy <mahe.tardy@gmail.com> wrote: > @@ -122,6 +122,11 @@ void bpf_gen__init(struct bpf_gen *gen, int log_level, int nr_progs, int nr_maps > + if (nr_progs > MAX_USED_PROGS) { > + pr_warn("Total programs exceeds %d\n", MAX_USED_PROGS); > + gen->error = -E2BIG; > + return; > + } nr_progs is obj->nr_programs. It counts subprogs and progs with autoload == false too. See commit 259172bb6514 ("libbpf: Fix gen_loader assumption on number of programs."). Only a prog that reaches bpf_gen__prog_load() takes a slot in prog_fd[]. Two objects with obj->nr_programs == 33: object today this patch should be ------------------- --------------- ------------- ------------- 33 progs -EACCES at load -E2BIG at gen -E2BIG at gen 1 prog, 32 subprogs -EACCES at load -E2BIG at gen loads The second object fails today because of the cleanup loop in bpf_gen__init(). It closes nr_progs slots of prog_fd[], and prog_fd[32] is at r10 + 0: r1 = *(u32 *)(r10 +0) invalid read from stack R10 off=0 size=4 Lets fix both: clamp the loop and check the limit where a prog takes the slot, like add_map_fd() does. Something like this (not even compile tested): diff --git a/tools/lib/bpf/gen_loader.c b/tools/lib/bpf/gen_loader.c --- a/tools/lib/bpf/gen_loader.c +++ b/tools/lib/bpf/gen_loader.c @@ -139,6 +139,8 @@ void bpf_gen__init(struct bpf_gen *gen, int log_level, int nr_progs, int nr_maps emit(gen, BPF_MOV64_IMM(BPF_REG_3, 0)); emit(gen, BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel)); + /* nr_progs includes subprogs and progs that are not loaded */ + nr_progs = min(nr_progs, MAX_USED_PROGS); /* amount of stack actually used, only used to calculate iterations, not stack offset */ nr_progs_sz = offsetof(struct loader_stack, prog_fd[nr_progs]); /* jump over cleanup code */ @@ -1134,6 +1136,11 @@ void bpf_gen__prog_load(struct bpf_gen *gen, gen->attach_kind = 0; } emit_check_err(gen); + if (gen->nr_progs == MAX_USED_PROGS) { + pr_warn("Total programs exceeds %d\n", MAX_USED_PROGS); + gen->error = -E2BIG; + return; + } /* remember prog_fd in the stack, if successful */ emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_7, stack_off(prog_fd[gen->nr_progs]))); since it was already applied. pls send a follow up. ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH bpf] libbpf: Reject excessive program counts in generated loaders 2026-10-29 16:33 ` Alexei Starovoitov @ 2026-10-29 20:03 ` Mahe Tardy 0 siblings, 0 replies; 4+ messages in thread From: Mahe Tardy @ 2026-10-29 20:03 UTC (permalink / raw) To: Alexei Starovoitov Cc: bpf, Andrii Nakryiko, Eduard Zingerman, Ihor Solodrai, Daniel Borkmann, Kumar Kartikeya Dwivedi, Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, linux-kernel, John Fastabend On Thu, Oct 29, 2026 at 04:33:56PM +0000, Alexei Starovoitov wrote: > On Wed, Oct 28, 2026 at 11:39 AM Mahe Tardy <mahe.tardy@gmail.com> wrote: > > @@ -122,6 +122,11 @@ void bpf_gen__init(struct bpf_gen *gen, int log_level, int nr_progs, int nr_maps > > + if (nr_progs > MAX_USED_PROGS) { > > + pr_warn("Total programs exceeds %d\n", MAX_USED_PROGS); > > + gen->error = -E2BIG; > > + return; > > + } > > nr_progs is obj->nr_programs. It counts subprogs and progs with > autoload == false too. See commit 259172bb6514 > ("libbpf: Fix gen_loader assumption on number of programs."). > Only a prog that reaches bpf_gen__prog_load() takes a slot in prog_fd[]. > > Two objects with obj->nr_programs == 33: > > object today this patch should be > ------------------- --------------- ------------- ------------- > 33 progs -EACCES at load -E2BIG at gen -E2BIG at gen > 1 prog, 32 subprogs -EACCES at load -E2BIG at gen loads > > The second object fails today because of the cleanup loop in > bpf_gen__init(). It closes nr_progs slots of prog_fd[], and > prog_fd[32] is at r10 + 0: > > r1 = *(u32 *)(r10 +0) > invalid read from stack R10 off=0 size=4 > > Lets fix both: clamp the loop and check the limit where a prog takes > the slot, like add_map_fd() does. > Something like this (not even compile tested): > > diff --git a/tools/lib/bpf/gen_loader.c b/tools/lib/bpf/gen_loader.c > --- a/tools/lib/bpf/gen_loader.c > +++ b/tools/lib/bpf/gen_loader.c > @@ -139,6 +139,8 @@ void bpf_gen__init(struct bpf_gen *gen, int log_level, int nr_progs, int nr_maps > emit(gen, BPF_MOV64_IMM(BPF_REG_3, 0)); > emit(gen, BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel)); > > + /* nr_progs includes subprogs and progs that are not loaded */ > + nr_progs = min(nr_progs, MAX_USED_PROGS); > /* amount of stack actually used, only used to calculate iterations, not stack offset */ > nr_progs_sz = offsetof(struct loader_stack, prog_fd[nr_progs]); > /* jump over cleanup code */ > @@ -1134,6 +1136,11 @@ void bpf_gen__prog_load(struct bpf_gen *gen, > gen->attach_kind = 0; > } > emit_check_err(gen); > + if (gen->nr_progs == MAX_USED_PROGS) { > + pr_warn("Total programs exceeds %d\n", MAX_USED_PROGS); > + gen->error = -E2BIG; > + return; > + } > /* remember prog_fd in the stack, if successful */ > emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_7, > stack_off(prog_fd[gen->nr_progs]))); > > since it was already applied. pls send a follow up. Ah yes this is correct, I bumped into this trying extend the lskel (but mostly trying to understand their generation for now to be honest) to allow them to call BPF_LINK_CREATE and somehow I adjusted the nr_progs passed to bpf_gen__init() earlier to the actual number of progs so I was not paying attention. Your patch makes sense to me now and works locally (since bpf_object__load_progs() is filtering the subprogs and autoload=false we have at the stage of filling the prog_fd, of course, the correct number of progs), I tested on an object with 1 prog and 32 subprogs and it's good now. I'll send this shortly! Thanks! ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-10-29 20:03 UTC | newest] Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-10-28 18:39 [PATCH bpf] libbpf: Reject excessive program counts in generated loaders Mahe Tardy 2026-10-29 16:10 ` patchwork-bot+netdevbpf 2026-10-29 16:33 ` Alexei Starovoitov 2026-10-29 20:03 ` Mahe Tardy
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®