* [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