All of lore.kernel.org
 help / color / mirror / Atom feed
* [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.