* [PATCH bpf-next 1/3] libbpf: Drop redundant self-loop in emit_check_err
@ 2026-05-29 9:41 Daniel Borkmann
2026-05-29 9:41 ` [PATCH bpf-next 2/3] libbpf: Skip hash computation when loader generation failed Daniel Borkmann
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Daniel Borkmann @ 2026-05-29 9:41 UTC (permalink / raw)
To: kpsingh; +Cc: bpf
When the cleanup-label jump offset does not fit in s16, emit_check_err()
sets gen->error = -ERANGE and then emits a BPF_JMP_IMM(BPF_JA, 0, 0, -1)
self-loop.
The latter emit() is dead: gen->error is assigned on the preceding line,
and emit() then bails out early in realloc_insn_buf() the moment gen->error
is set, so the jump is never written into the instruction stream.
gen->error alone already marks the generation as failed. This is a follow-up
to 7dd62566e0d1 ("libbpf: fix off-by-one in emit_signature_match jump offset")
which removed the jump in emit_signature_match() but not in other locations.
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
---
tools/lib/bpf/gen_loader.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/tools/lib/bpf/gen_loader.c b/tools/lib/bpf/gen_loader.c
index 9478b8f78f26..7b95ced7bcba 100644
--- a/tools/lib/bpf/gen_loader.c
+++ b/tools/lib/bpf/gen_loader.c
@@ -293,7 +293,6 @@ static void emit_check_err(struct bpf_gen *gen)
emit(gen, BPF_JMP_IMM(BPF_JSLT, BPF_REG_7, 0, off));
} else {
gen->error = -ERANGE;
- emit(gen, BPF_JMP_IMM(BPF_JA, 0, 0, -1));
}
}
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH bpf-next 2/3] libbpf: Skip hash computation when loader generation failed
2026-05-29 9:41 [PATCH bpf-next 1/3] libbpf: Drop redundant self-loop in emit_check_err Daniel Borkmann
@ 2026-05-29 9:41 ` Daniel Borkmann
2026-05-29 10:21 ` sashiko-bot
2026-05-29 9:41 ` [PATCH bpf-next 3/3] libbpf: Also reset {insn,data}_cur on realloc failure Daniel Borkmann
2026-06-01 0:50 ` [PATCH bpf-next 1/3] libbpf: Drop redundant self-loop in emit_check_err patchwork-bot+netdevbpf
2 siblings, 1 reply; 8+ messages in thread
From: Daniel Borkmann @ 2026-05-29 9:41 UTC (permalink / raw)
To: kpsingh; +Cc: bpf, sashiko
bpf_gen__finish() calls compute_sha_update_offsets() gated only on
the gen_hash option, without first consulting gen->error. On a failed
generation this is buggy: a failed realloc_data_buf() sets gen->data_start
to NULL (leaving gen->data_cur dangling), so compute_sha_update_offsets()
runs libbpf_sha256() over a NULL buffer with a bogus length; a failed
realloc_insn_buf() likewise sets gen->insn_start to NULL and the hash
immediates get patched through that NULL base.
The computed program is discarded in either case, since the following
"if (!gen->error)" block does not publish opts->insns once an error is
set. Thus, skip the hash pass when generation has already failed.
Fixes: ea923080c145 ("libbpf: Embed and verify the metadata hash in the loader")
Reported-by: sashiko <sashiko@sashiko.dev>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
---
tools/lib/bpf/gen_loader.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/tools/lib/bpf/gen_loader.c b/tools/lib/bpf/gen_loader.c
index 7b95ced7bcba..3a6e1d53f287 100644
--- a/tools/lib/bpf/gen_loader.c
+++ b/tools/lib/bpf/gen_loader.c
@@ -397,13 +397,12 @@ int bpf_gen__finish(struct bpf_gen *gen, int nr_progs, int nr_maps)
blob_fd_array_off(gen, i));
emit(gen, BPF_MOV64_IMM(BPF_REG_0, 0));
emit(gen, BPF_EXIT_INSN());
- if (OPTS_GET(gen->opts, gen_hash, false))
- compute_sha_update_offsets(gen);
-
- pr_debug("gen: finish %s\n", errstr(gen->error));
if (!gen->error) {
struct gen_loader_opts *opts = gen->opts;
+ if (OPTS_GET(opts, gen_hash, false))
+ compute_sha_update_offsets(gen);
+
opts->insns = gen->insn_start;
opts->insns_sz = gen->insn_cur - gen->insn_start;
opts->data = gen->data_start;
@@ -418,6 +417,7 @@ int bpf_gen__finish(struct bpf_gen *gen, int nr_progs, int nr_maps)
bpf_insn_bswap(insn++);
}
}
+ pr_debug("gen: finish %s\n", errstr(gen->error));
return gen->error;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH bpf-next 3/3] libbpf: Also reset {insn,data}_cur on realloc failure
2026-05-29 9:41 [PATCH bpf-next 1/3] libbpf: Drop redundant self-loop in emit_check_err Daniel Borkmann
2026-05-29 9:41 ` [PATCH bpf-next 2/3] libbpf: Skip hash computation when loader generation failed Daniel Borkmann
@ 2026-05-29 9:41 ` Daniel Borkmann
2026-05-29 10:20 ` bot+bpf-ci
2026-06-01 0:50 ` [PATCH bpf-next 1/3] libbpf: Drop redundant self-loop in emit_check_err patchwork-bot+netdevbpf
2 siblings, 1 reply; 8+ messages in thread
From: Daniel Borkmann @ 2026-05-29 9:41 UTC (permalink / raw)
To: kpsingh; +Cc: bpf
realloc_insn_buf() as well as realloc_data_buf() free and NULL
gen->insn_start / gen->data_start on -ENOMEM but leave gen->insn_cur /
gen->data_cur pointing into the old, freed buffer. Just reset the
cursors to NULL alongside the base pointers so the freed state is
coherent.
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
---
tools/lib/bpf/gen_loader.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tools/lib/bpf/gen_loader.c b/tools/lib/bpf/gen_loader.c
index 3a6e1d53f287..492360ca07ea 100644
--- a/tools/lib/bpf/gen_loader.c
+++ b/tools/lib/bpf/gen_loader.c
@@ -63,6 +63,7 @@ static int realloc_insn_buf(struct bpf_gen *gen, __u32 size)
gen->error = -ENOMEM;
free(gen->insn_start);
gen->insn_start = NULL;
+ gen->insn_cur = NULL;
return -ENOMEM;
}
gen->insn_start = insn_start;
@@ -86,6 +87,7 @@ static int realloc_data_buf(struct bpf_gen *gen, __u32 size)
gen->error = -ENOMEM;
free(gen->data_start);
gen->data_start = NULL;
+ gen->data_cur = NULL;
return -ENOMEM;
}
gen->data_start = data_start;
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH bpf-next 3/3] libbpf: Also reset {insn,data}_cur on realloc failure
2026-05-29 9:41 ` [PATCH bpf-next 3/3] libbpf: Also reset {insn,data}_cur on realloc failure Daniel Borkmann
@ 2026-05-29 10:20 ` bot+bpf-ci
2026-05-29 11:22 ` Daniel Borkmann
0 siblings, 1 reply; 8+ messages in thread
From: bot+bpf-ci @ 2026-05-29 10:20 UTC (permalink / raw)
To: daniel, kpsingh
Cc: bpf, ast, andrii, daniel, martin.lau, eddyz87, yonghong.song, clm,
ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 1051 bytes --]
> libbpf: Also reset {insn,data}_cur on realloc failure
>
> realloc_insn_buf() as well as realloc_data_buf() free and NULL
> gen->insn_start / gen->data_start on -ENOMEM but leave gen->insn_cur /
> gen->data_cur pointing into the old, freed buffer. Just reset the
> cursors to NULL alongside the base pointers so the freed state is
> coherent.
>
> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
This looks like a fix for a real bug where gen->insn_cur and
gen->data_cur are left pointing into a freed buffer on -ENOMEM. Should
it carry a Fixes: tag pointing at the commit that introduced the
free()+NULL handling in realloc_insn_buf() and realloc_data_buf()?
The exact SHA could not be determined here, so it would need to be
looked up from a full bpf-next/torvalds tree.
---
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/26630703706
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH bpf-next 2/3] libbpf: Skip hash computation when loader generation failed
2026-05-29 9:41 ` [PATCH bpf-next 2/3] libbpf: Skip hash computation when loader generation failed Daniel Borkmann
@ 2026-05-29 10:21 ` sashiko-bot
2026-05-29 13:49 ` Daniel Borkmann
0 siblings, 1 reply; 8+ messages in thread
From: sashiko-bot @ 2026-05-29 10:21 UTC (permalink / raw)
To: Daniel Borkmann; +Cc: bpf
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Unchecked `add_data()` failures lead to NULL pointer dereferences or heap buffer overflows in `bpf_gen__prog_load()` and `info_blob_bswap()` during endianness swapping.
--
commit 586ab83145acd4d3b6d7223bb61c05d593fe3860
Author: Daniel Borkmann <daniel@iogearbox.net>
libbpf: Skip hash computation when loader generation failed
This patch fixes a bug in bpf_gen__finish() where compute_sha_update_offsets()
was called on failed loader generation. It moves the hash computation inside
the !gen->error block to avoid running libbpf_sha256() over NULL buffers.
> diff --git a/tools/lib/bpf/gen_loader.c b/tools/lib/bpf/gen_loader.c
> index 7b95ced7bcbaf..3a6e1d53f287a 100644
> --- a/tools/lib/bpf/gen_loader.c
> +++ b/tools/lib/bpf/gen_loader.c
> @@ -397,13 +397,12 @@ int bpf_gen__finish(struct bpf_gen *gen, int nr_progs, int nr_maps)
> blob_fd_array_off(gen, i));
> emit(gen, BPF_MOV64_IMM(BPF_REG_0, 0));
> emit(gen, BPF_EXIT_INSN());
> - if (OPTS_GET(gen->opts, gen_hash, false))
> - compute_sha_update_offsets(gen);
> -
> - pr_debug("gen: finish %s\n", errstr(gen->error));
> if (!gen->error) {
> struct gen_loader_opts *opts = gen->opts;
>
> + if (OPTS_GET(opts, gen_hash, false))
> + compute_sha_update_offsets(gen);
> +
> opts->insns = gen->insn_start;
[Severity: Critical]
This isn't a regression introduced by this patch, but while reviewing this
file I noticed a pre-existing issue with how generation errors are handled in
bpf_gen__prog_load() and info_blob_bswap().
If realloc_data_buf() fails inside add_data(), it frees gen->data_start,
sets it to NULL, sets gen->error, and add_data() returns 0.
However, bpf_gen__prog_load() doesn't check gen->error before swapping
endianness:
tools/lib/bpf/gen_loader.c:bpf_gen__prog_load() {
...
insns_off = add_data(gen, insns, insn_cnt * sizeof(struct bpf_insn));
...
if (gen->swapped_endian) {
struct bpf_insn *insn = gen->data_start + insns_off;
int i;
for (i = 0; i < insn_cnt; i++, insn++)
bpf_insn_bswap(insn);
}
...
}
If add_data() failed, this evaluates to insn = NULL + 0. Can this cause a
NULL pointer dereference when accessing insn inside bpf_insn_bswap()?
Furthermore, if gen->error was previously set (e.g., from a failed
realloc_insn_buf) while gen->data_start is non-NULL, add_data() still returns
0.
Since the loop evaluates insn = gen->data_start + 0, can this overwrite the
beginning of gen->data_start and write past the end of the buffer if it is
smaller than insn_cnt * sizeof(struct bpf_insn)?
Could we add a check for gen->error before proceeding with the endianness
swapping?
> opts->insns_sz = gen->insn_cur - gen->insn_start;
> opts->data = gen->data_start;
> @@ -418,6 +417,7 @@ int bpf_gen__finish(struct bpf_gen *gen, int nr_progs, int nr_maps)
> bpf_insn_bswap(insn++);
> }
> }
> + pr_debug("gen: finish %s\n", errstr(gen->error));
> return gen->error;
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260529094119.307264-1-daniel@iogearbox.net?part=2
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH bpf-next 3/3] libbpf: Also reset {insn,data}_cur on realloc failure
2026-05-29 10:20 ` bot+bpf-ci
@ 2026-05-29 11:22 ` Daniel Borkmann
0 siblings, 0 replies; 8+ messages in thread
From: Daniel Borkmann @ 2026-05-29 11:22 UTC (permalink / raw)
To: bot+bpf-ci, kpsingh
Cc: bpf, ast, andrii, martin.lau, eddyz87, yonghong.song, clm,
ihor.solodrai
On 5/29/26 12:20 PM, bot+bpf-ci@kernel.org wrote:
>> libbpf: Also reset {insn,data}_cur on realloc failure
>>
>> realloc_insn_buf() as well as realloc_data_buf() free and NULL
>> gen->insn_start / gen->data_start on -ENOMEM but leave gen->insn_cur /
>> gen->data_cur pointing into the old, freed buffer. Just reset the
>> cursors to NULL alongside the base pointers so the freed state is
>> coherent.
>>
>> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
>
> This looks like a fix for a real bug where gen->insn_cur and
> gen->data_cur are left pointing into a freed buffer on -ENOMEM. Should
> it carry a Fixes: tag pointing at the commit that introduced the
> free()+NULL handling in realloc_insn_buf() and realloc_data_buf()?
>
> The exact SHA could not be determined here, so it would need to be
> looked up from a full bpf-next/torvalds tree.
(I've added this given patch 2 in this series where stale data was used.)
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH bpf-next 2/3] libbpf: Skip hash computation when loader generation failed
2026-05-29 10:21 ` sashiko-bot
@ 2026-05-29 13:49 ` Daniel Borkmann
0 siblings, 0 replies; 8+ messages in thread
From: Daniel Borkmann @ 2026-05-29 13:49 UTC (permalink / raw)
To: sashiko-reviews; +Cc: bpf
On 5/29/26 12:21 PM, sashiko-bot@kernel.org wrote:
[...]
> [Severity: Critical]
> This isn't a regression introduced by this patch, but while reviewing this
> file I noticed a pre-existing issue with how generation errors are handled in
> bpf_gen__prog_load() and info_blob_bswap().
>
> If realloc_data_buf() fails inside add_data(), it frees gen->data_start,
> sets it to NULL, sets gen->error, and add_data() returns 0.
>
> However, bpf_gen__prog_load() doesn't check gen->error before swapping
> endianness:
>
> tools/lib/bpf/gen_loader.c:bpf_gen__prog_load() {
> ...
> insns_off = add_data(gen, insns, insn_cnt * sizeof(struct bpf_insn));
> ...
> if (gen->swapped_endian) {
> struct bpf_insn *insn = gen->data_start + insns_off;
> int i;
>
> for (i = 0; i < insn_cnt; i++, insn++)
> bpf_insn_bswap(insn);
> }
> ...
> }
>
> If add_data() failed, this evaluates to insn = NULL + 0. Can this cause a
> NULL pointer dereference when accessing insn inside bpf_insn_bswap()?
>
> Furthermore, if gen->error was previously set (e.g., from a failed
> realloc_insn_buf) while gen->data_start is non-NULL, add_data() still returns
> 0.
>
> Since the loop evaluates insn = gen->data_start + 0, can this overwrite the
> beginning of gen->data_start and write past the end of the buffer if it is
> smaller than insn_cnt * sizeof(struct bpf_insn)?
>
> Could we add a check for gen->error before proceeding with the endianness
> swapping?
Yeap, for the endianess we would need something like the below ... will cook
a patch for it to address :
diff --git a/tools/lib/bpf/gen_loader.c b/tools/lib/bpf/gen_loader.c
index 19f9c05f8388..501508e5affa 100644
--- a/tools/lib/bpf/gen_loader.c
+++ b/tools/lib/bpf/gen_loader.c
@@ -1071,7 +1071,7 @@ void bpf_gen__prog_load(struct bpf_gen *gen,
prog_idx, prog_type, insns_off, insn_cnt, license_off);
/* convert blob insns to target endianness */
- if (gen->swapped_endian) {
+ if (gen->swapped_endian && !gen->error) {
struct bpf_insn *insn = gen->data_start + insns_off;
int i;
@@ -1109,7 +1109,7 @@ void bpf_gen__prog_load(struct bpf_gen *gen,
sizeof(struct bpf_core_relo));
/* convert all info blobs to target endianness */
- if (gen->swapped_endian)
+ if (gen->swapped_endian && !gen->error)
info_blob_bswap(gen, func_info, line_info, core_relos, load_attr);
libbpf_strlcpy(attr.prog_name, prog_name, sizeof(attr.prog_name));
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH bpf-next 1/3] libbpf: Drop redundant self-loop in emit_check_err
2026-05-29 9:41 [PATCH bpf-next 1/3] libbpf: Drop redundant self-loop in emit_check_err Daniel Borkmann
2026-05-29 9:41 ` [PATCH bpf-next 2/3] libbpf: Skip hash computation when loader generation failed Daniel Borkmann
2026-05-29 9:41 ` [PATCH bpf-next 3/3] libbpf: Also reset {insn,data}_cur on realloc failure Daniel Borkmann
@ 2026-06-01 0:50 ` patchwork-bot+netdevbpf
2 siblings, 0 replies; 8+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-06-01 0:50 UTC (permalink / raw)
To: Daniel Borkmann; +Cc: kpsingh, bpf
Hello:
This series was applied to bpf/bpf-next.git (master)
by Alexei Starovoitov <ast@kernel.org>:
On Fri, 29 May 2026 11:41:16 +0200 you wrote:
> When the cleanup-label jump offset does not fit in s16, emit_check_err()
> sets gen->error = -ERANGE and then emits a BPF_JMP_IMM(BPF_JA, 0, 0, -1)
> self-loop.
>
> The latter emit() is dead: gen->error is assigned on the preceding line,
> and emit() then bails out early in realloc_insn_buf() the moment gen->error
> is set, so the jump is never written into the instruction stream.
>
> [...]
Here is the summary with links:
- [bpf-next,1/3] libbpf: Drop redundant self-loop in emit_check_err
https://git.kernel.org/bpf/bpf-next/c/e2c88266147f
- [bpf-next,2/3] libbpf: Skip hash computation when loader generation failed
https://git.kernel.org/bpf/bpf-next/c/3c5e2f1a8584
- [bpf-next,3/3] libbpf: Also reset {insn,data}_cur on realloc failure
https://git.kernel.org/bpf/bpf-next/c/d2f7bd066ed4
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] 8+ messages in thread
end of thread, other threads:[~2026-06-01 0:50 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-29 9:41 [PATCH bpf-next 1/3] libbpf: Drop redundant self-loop in emit_check_err Daniel Borkmann
2026-05-29 9:41 ` [PATCH bpf-next 2/3] libbpf: Skip hash computation when loader generation failed Daniel Borkmann
2026-05-29 10:21 ` sashiko-bot
2026-05-29 13:49 ` Daniel Borkmann
2026-05-29 9:41 ` [PATCH bpf-next 3/3] libbpf: Also reset {insn,data}_cur on realloc failure Daniel Borkmann
2026-05-29 10:20 ` bot+bpf-ci
2026-05-29 11:22 ` Daniel Borkmann
2026-06-01 0:50 ` [PATCH bpf-next 1/3] libbpf: Drop redundant self-loop in emit_check_err patchwork-bot+netdevbpf
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.