mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 04:34:03 +02:00
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.
Fixes: 8580ac9404 ("bpf: Process in-kernel BTF")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20260708211537.371874-2-daniel@iogearbox.net
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
This commit is contained in:
parent
41ec7e4a17
commit
92863e6780
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user