BPF List
 help / color / mirror / Atom feed
* [PATCH bpf-next 0/4] Misc BPF fixes from sashiko findings
@ 2026-07-08 21:15 Daniel Borkmann
  2026-07-08 21:15 ` [PATCH bpf-next 1/4] bpf: Fix vmlinux BTF prep race in bpf_get_btf_vmlinux Daniel Borkmann
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Daniel Borkmann @ 2026-07-08 21:15 UTC (permalink / raw)
  To: memxor; +Cc: ast, bpf

Addressing some misc/random findings from sashiko that are worth fixing
which popped up as pre-existing issues while working on the signed BPF
loader series.

Daniel Borkmann (4):
  bpf: Fix vmlinux BTF prep race in bpf_get_btf_vmlinux
  bpf: Give vmlinux BTF init its own mutex
  bpf: Account insn_aux_data allocation in bpf_check
  bpf: Account scratch buffer in bpf_prog_calc_tag

 kernel/bpf/btf.c      |  2 +-
 kernel/bpf/core.c     |  2 +-
 kernel/bpf/verifier.c | 30 ++++++++++++++++++++++--------
 3 files changed, 24 insertions(+), 10 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH bpf-next 1/4] bpf: Fix vmlinux BTF prep race in bpf_get_btf_vmlinux
  2026-07-08 21:15 [PATCH bpf-next 0/4] Misc BPF fixes from sashiko findings Daniel Borkmann
@ 2026-07-08 21:15 ` Daniel Borkmann
  2026-07-08 22:17   ` bot+bpf-ci
  2026-07-08 21:15 ` [PATCH bpf-next 2/4] bpf: Give vmlinux BTF init its own mutex Daniel Borkmann
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Daniel Borkmann @ 2026-07-08 21:15 UTC (permalink / raw)
  To: memxor; +Cc: ast, bpf

bpf_get_btf_vmlinux() lazily parses the vmlinux BTF under the
bpf_verifier_lock, but publishes the result through a plain store
and re-checks it through a plain lockless load. Nothing orders
the stores initializing the struct btf inside btf_parse_vmlinux()
against the store publishing the pointer: On a weakly ordered
arch, a concurrent first-time caller taking the lockless fast
path could in principle observe the pointer before the parsed
contents are visible. The mutex_unlock() does not help such a
reader given it only synchronizes with a later acquisition of the
same lock. Thus, publish the pointer with smp_store_release()
and read it on the fast path with smp_load_acquire().

Acquire semantics are needed rather than a dependency-ordered
READ_ONCE(): btf_parse_vmlinux() also populates globals outside
the returned object (e.g. bpf_ctx_convert.t). An address
dependency would only order accesses performed through the
pointer and not cover other globals.

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
---
 kernel/bpf/verifier.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 001ac53825da..9217e0f87cb5 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -19559,13 +19559,25 @@ int bpf_check_attach_btf_id_multi(struct btf *btf, struct bpf_prog *prog, u32 bt
 
 struct btf *bpf_get_btf_vmlinux(void)
 {
-	if (!btf_vmlinux && IS_ENABLED(CONFIG_DEBUG_INFO_BTF)) {
+	/* Pairs with the smp_store_release() on the parse path below. */
+	struct btf *btf = smp_load_acquire(&btf_vmlinux);
+
+	if (!btf && IS_ENABLED(CONFIG_DEBUG_INFO_BTF)) {
 		mutex_lock(&bpf_verifier_lock);
-		if (!btf_vmlinux)
-			btf_vmlinux = btf_parse_vmlinux();
+		btf = btf_vmlinux;
+		if (!btf) {
+			btf = btf_parse_vmlinux();
+			/*
+			 * Order the parsed BTF contents and the globals the
+			 * parse populated (e.g. bpf_ctx_convert.t) before
+			 * the pointer publication. Pairs with the acquire
+			 * on the lockless fast path above.
+			 */
+			smp_store_release(&btf_vmlinux, btf);
+		}
 		mutex_unlock(&bpf_verifier_lock);
 	}
-	return btf_vmlinux;
+	return btf;
 }
 
 /*
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH bpf-next 2/4] bpf: Give vmlinux BTF init its own mutex
  2026-07-08 21:15 [PATCH bpf-next 0/4] Misc BPF fixes from sashiko findings Daniel Borkmann
  2026-07-08 21:15 ` [PATCH bpf-next 1/4] bpf: Fix vmlinux BTF prep race in bpf_get_btf_vmlinux Daniel Borkmann
@ 2026-07-08 21:15 ` Daniel Borkmann
  2026-07-08 21:15 ` [PATCH bpf-next 3/4] bpf: Account insn_aux_data allocation in bpf_check Daniel Borkmann
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Daniel Borkmann @ 2026-07-08 21:15 UTC (permalink / raw)
  To: memxor; +Cc: ast, bpf

bpf_get_btf_vmlinux() serializes the lazy vmlinux BTF parse with
bpf_verifier_lock, the same mutex bpf_check() holds across the whole
verification of an unprivileged program (if enabled; it's disabled
by default). The latter can potentially stall the mutex holder for
a long time (e.g. via userfaultfd), and therefore block first-time
bpf_get_btf_vmlinux() caller from any context, including privileged
program loads.

Give the vmlinux BTF initialization a dedicated btf_vmlinux_lock so
it is independent of the unprivileged verification mutex. The parse
only needs mutual exclusion against itself.

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
---
 kernel/bpf/btf.c      | 2 +-
 kernel/bpf/verifier.c | 7 ++++---
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index dff5c0d91641..8c04c340f499 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -6451,7 +6451,7 @@ struct btf *btf_parse_vmlinux(void)
 	if (IS_ERR(btf))
 		goto err_out;
 
-	/* btf_parse_vmlinux() runs under bpf_verifier_lock */
+	/* btf_parse_vmlinux() runs under btf_vmlinux_lock */
 	bpf_ctx_convert.t = btf_type_by_id(btf, bpf_ctx_convert_btf_id[0]);
 	err = btf_alloc_id(btf);
 	if (err) {
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 9217e0f87cb5..40e20dfa3212 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -324,6 +324,7 @@ static const char *btf_type_name(const struct btf *btf, u32 id)
 }
 
 static DEFINE_MUTEX(bpf_verifier_lock);
+static DEFINE_MUTEX(btf_vmlinux_lock);
 static DEFINE_MUTEX(bpf_percpu_ma_lock);
 
 __printf(2, 3) static void verbose(void *private_data, const char *fmt, ...)
@@ -19563,7 +19564,7 @@ struct btf *bpf_get_btf_vmlinux(void)
 	struct btf *btf = smp_load_acquire(&btf_vmlinux);
 
 	if (!btf && IS_ENABLED(CONFIG_DEBUG_INFO_BTF)) {
-		mutex_lock(&bpf_verifier_lock);
+		mutex_lock(&btf_vmlinux_lock);
 		btf = btf_vmlinux;
 		if (!btf) {
 			btf = btf_parse_vmlinux();
@@ -19575,7 +19576,7 @@ struct btf *bpf_get_btf_vmlinux(void)
 			 */
 			smp_store_release(&btf_vmlinux, btf);
 		}
-		mutex_unlock(&bpf_verifier_lock);
+		mutex_unlock(&btf_vmlinux_lock);
 	}
 	return btf;
 }
@@ -20089,7 +20090,7 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr,
 
 	bpf_get_btf_vmlinux();
 
-	/* grab the mutex to protect few globals used by verifier */
+	/* Serialize verification of unprivileged programs. */
 	if (!is_priv)
 		mutex_lock(&bpf_verifier_lock);
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH bpf-next 3/4] bpf: Account insn_aux_data allocation in bpf_check
  2026-07-08 21:15 [PATCH bpf-next 0/4] Misc BPF fixes from sashiko findings Daniel Borkmann
  2026-07-08 21:15 ` [PATCH bpf-next 1/4] bpf: Fix vmlinux BTF prep race in bpf_get_btf_vmlinux Daniel Borkmann
  2026-07-08 21:15 ` [PATCH bpf-next 2/4] bpf: Give vmlinux BTF init its own mutex Daniel Borkmann
@ 2026-07-08 21:15 ` Daniel Borkmann
  2026-07-08 21:15 ` [PATCH bpf-next 4/4] bpf: Account scratch buffer in bpf_prog_calc_tag Daniel Borkmann
  2026-07-09  5:10 ` [PATCH bpf-next 0/4] Misc BPF fixes from sashiko findings patchwork-bot+netdevbpf
  4 siblings, 0 replies; 8+ messages in thread
From: Daniel Borkmann @ 2026-07-08 21:15 UTC (permalink / raw)
  To: memxor; +Cc: ast, bpf

The insn_aux_data array is allocated with a plain vzalloc(), while every
other allocation scoped to the verification - verifier states, explored
states, the cfg/scc arrays, liveness masks, jump history - is charged to
the loader's memcg via GFP_KERNEL_ACCOUNT.

At 136 bytes per instruction it is one of the largest verification-time
buffers, in the range of ~130MB for a program at the 1M instruction limit
(worst case), and it lives across the whole verification. The buffer is
also inconsistent with itself: when instruction patching grows it, the
vrealloc() in bpf_patch_insn_data() already passes GFP_KERNEL_ACCOUNT.

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
---
 kernel/bpf/verifier.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 40e20dfa3212..ad8ff228c963 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -20096,7 +20096,8 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr,
 
 	len = env->prog->len;
 	env->insn_aux_data =
-		vzalloc(array_size(sizeof(struct bpf_insn_aux_data), len));
+		__vmalloc(array_size(sizeof(struct bpf_insn_aux_data), len),
+			  GFP_KERNEL_ACCOUNT | __GFP_ZERO);
 	ret = -ENOMEM;
 	if (!env->insn_aux_data)
 		goto skip_full_check;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH bpf-next 4/4] bpf: Account scratch buffer in bpf_prog_calc_tag
  2026-07-08 21:15 [PATCH bpf-next 0/4] Misc BPF fixes from sashiko findings Daniel Borkmann
                   ` (2 preceding siblings ...)
  2026-07-08 21:15 ` [PATCH bpf-next 3/4] bpf: Account insn_aux_data allocation in bpf_check Daniel Borkmann
@ 2026-07-08 21:15 ` Daniel Borkmann
  2026-07-08 21:25   ` sashiko-bot
  2026-07-09  5:10 ` [PATCH bpf-next 0/4] Misc BPF fixes from sashiko findings patchwork-bot+netdevbpf
  4 siblings, 1 reply; 8+ messages in thread
From: Daniel Borkmann @ 2026-07-08 21:15 UTC (permalink / raw)
  To: memxor; +Cc: ast, bpf

bpf_prog_calc_tag() copies the instructions into a plain vmalloc() scratch
buffer to blind the map fds before hashing. The buffer scales with the
program, up to ~8MB at the 1M instruction limit, and is allocated on every
program load, but unlike the rest of the load-time scratch memory it is
not charged to the loader's memcg. Use GFP_KERNEL_ACCOUNT to account it
like the other allocations scoped to the verification/load.

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
---
 kernel/bpf/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 6e19a030da6f..f2b6e4c888af 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -305,7 +305,7 @@ int bpf_prog_calc_tag(struct bpf_prog *fp)
 	bool was_ld_map;
 	u32 i;
 
-	dst = vmalloc(size);
+	dst = __vmalloc(size, GFP_KERNEL_ACCOUNT);
 	if (!dst)
 		return -ENOMEM;
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH bpf-next 4/4] bpf: Account scratch buffer in bpf_prog_calc_tag
  2026-07-08 21:15 ` [PATCH bpf-next 4/4] bpf: Account scratch buffer in bpf_prog_calc_tag Daniel Borkmann
@ 2026-07-08 21:25   ` sashiko-bot
  0 siblings, 0 replies; 8+ messages in thread
From: sashiko-bot @ 2026-07-08 21:25 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:
- [Medium] Missing memcg accounting for the temporary JIT scratch buffer `rw_header`.
--

--- Patch [4]: [PATCH bpf-next 4/4] bpf: Account scratch buffer in bpf_prog_calc_tag ---
commit 57c46cbb1e055c7c0a73414dd57ed04bc1cb8b73
Author: Daniel Borkmann <daniel@iogearbox.net>

bpf: Account scratch buffer in bpf_prog_calc_tag

This commit updates bpf_prog_calc_tag() to use GFP_KERNEL_ACCOUNT for its
vmalloc scratch buffer. This ensures the temporary memory, which scales with
the program size, is properly charged to the loader's memory cgroup.

> diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
> --- a/kernel/bpf/core.c
> +++ b/kernel/bpf/core.c
> @@ -305,7 +305,7 @@ int bpf_prog_calc_tag(struct bpf_prog *fp)
>  	bool was_ld_map;
>  	u32 i;
>  
> -	dst = vmalloc(size);
> +	dst = __vmalloc(size, GFP_KERNEL_ACCOUNT);

[Severity: Medium]
This is a pre-existing issue, but since this patch correctly applies memcg
accounting to load-time scratch memory, should we also account the
temporary JIT scratch buffer?

Looking at bpf_jit_binary_pack_alloc() in the same file, rw_header scales
with the program size but uses GFP_KERNEL instead of GFP_KERNEL_ACCOUNT:

kernel/bpf/core.c:bpf_jit_binary_pack_alloc() {
    ...
    *rw_header = kvmalloc(size, GFP_KERNEL);
    ...
}

Does this missing accounting allow a process to bypass its memcg limits by
triggering concurrent JIT compilations?

>  	if (!dst)
>  		return -ENOMEM;

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260708211537.371874-1-daniel@iogearbox.net?part=4

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH bpf-next 1/4] bpf: Fix vmlinux BTF prep race in bpf_get_btf_vmlinux
  2026-07-08 21:15 ` [PATCH bpf-next 1/4] bpf: Fix vmlinux BTF prep race in bpf_get_btf_vmlinux Daniel Borkmann
@ 2026-07-08 22:17   ` bot+bpf-ci
  0 siblings, 0 replies; 8+ messages in thread
From: bot+bpf-ci @ 2026-07-08 22:17 UTC (permalink / raw)
  To: daniel, memxor
  Cc: ast, bpf, ast, andrii, daniel, martin.lau, eddyz87, yonghong.song,
	clm, ihor.solodrai

[-- Attachment #1: Type: text/plain, Size: 1773 bytes --]

>     bpf: Fix vmlinux BTF prep race in bpf_get_btf_vmlinux
>
>     bpf_get_btf_vmlinux() lazily parses the vmlinux BTF under the
>     bpf_verifier_lock, but publishes the result through a plain store
>     and re-checks it through a plain lockless load. Nothing orders
>     the stores initializing the struct btf inside btf_parse_vmlinux()
>     against the store publishing the pointer: On a weakly ordered
>     arch, a concurrent first-time caller taking the lockless fast
>     path could in principle observe the pointer before the parsed
>     contents are visible. The mutex_unlock() does not help such a
>     reader given it only synchronizes with a later acquisition of the
>     same lock. Thus, publish the pointer with smp_store_release()
>     and read it on the fast path with smp_load_acquire().
>
>     Acquire semantics are needed rather than a dependency-ordered
>     READ_ONCE(): btf_parse_vmlinux() also populates globals outside
>     the returned object (e.g. bpf_ctx_convert.t). An address
>     dependency would only order accesses performed through the
>     pointer and not cover other globals.
>
>     Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>

This looks like a fix for a real memory-ordering bug on weakly ordered
architectures.  Should it carry a Fixes: tag?

The plain store publishing the pointer together with the plain lockless
load appears to go back to the introduction of the in-kernel BTF parsing,
so a candidate would be:

  Fixes: 8580ac9404f6 ("bpf: Process in-kernel BTF")


---
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/28977272970

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH bpf-next 0/4] Misc BPF fixes from sashiko findings
  2026-07-08 21:15 [PATCH bpf-next 0/4] Misc BPF fixes from sashiko findings Daniel Borkmann
                   ` (3 preceding siblings ...)
  2026-07-08 21:15 ` [PATCH bpf-next 4/4] bpf: Account scratch buffer in bpf_prog_calc_tag Daniel Borkmann
@ 2026-07-09  5:10 ` patchwork-bot+netdevbpf
  4 siblings, 0 replies; 8+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-07-09  5:10 UTC (permalink / raw)
  To: Daniel Borkmann; +Cc: memxor, ast, bpf

Hello:

This series was applied to bpf/bpf-next.git (master)
by Kumar Kartikeya Dwivedi <memxor@gmail.com>:

On Wed,  8 Jul 2026 23:15:33 +0200 you wrote:
> Addressing some misc/random findings from sashiko that are worth fixing
> which popped up as pre-existing issues while working on the signed BPF
> loader series.
> 
> Daniel Borkmann (4):
>   bpf: Fix vmlinux BTF prep race in bpf_get_btf_vmlinux
>   bpf: Give vmlinux BTF init its own mutex
>   bpf: Account insn_aux_data allocation in bpf_check
>   bpf: Account scratch buffer in bpf_prog_calc_tag
> 
> [...]

Here is the summary with links:
  - [bpf-next,1/4] bpf: Fix vmlinux BTF prep race in bpf_get_btf_vmlinux
    https://git.kernel.org/bpf/bpf-next/c/92863e678070
  - [bpf-next,2/4] bpf: Give vmlinux BTF init its own mutex
    https://git.kernel.org/bpf/bpf-next/c/5e5e94d87dea
  - [bpf-next,3/4] bpf: Account insn_aux_data allocation in bpf_check
    https://git.kernel.org/bpf/bpf-next/c/42560699a83d
  - [bpf-next,4/4] bpf: Account scratch buffer in bpf_prog_calc_tag
    https://git.kernel.org/bpf/bpf-next/c/ff755b600790

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-07-09  5:10 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-08 21:15 [PATCH bpf-next 0/4] Misc BPF fixes from sashiko findings Daniel Borkmann
2026-07-08 21:15 ` [PATCH bpf-next 1/4] bpf: Fix vmlinux BTF prep race in bpf_get_btf_vmlinux Daniel Borkmann
2026-07-08 22:17   ` bot+bpf-ci
2026-07-08 21:15 ` [PATCH bpf-next 2/4] bpf: Give vmlinux BTF init its own mutex Daniel Borkmann
2026-07-08 21:15 ` [PATCH bpf-next 3/4] bpf: Account insn_aux_data allocation in bpf_check Daniel Borkmann
2026-07-08 21:15 ` [PATCH bpf-next 4/4] bpf: Account scratch buffer in bpf_prog_calc_tag Daniel Borkmann
2026-07-08 21:25   ` sashiko-bot
2026-07-09  5:10 ` [PATCH bpf-next 0/4] Misc BPF fixes from sashiko findings patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox