From: bot+bpf-ci@kernel.org
To: wanjay@amazon.com,bpf@vger.kernel.org,ast@kernel.org,daniel@iogearbox.net,andrii@kernel.org,eddyz87@gmail.com,memxor@gmail.com
Cc: alan.maguire@oracle.com,martin.lau@linux.dev,yonghong.song@linux.dev,nathan@kernel.org,nsc@kernel.org,linux-kbuild@vger.kernel.org,mcgrof@kernel.org,petr.pavlu@suse.com,linux-modules@vger.kernel.org,arnd@arndb.de,linux-kernel@vger.kernel.org,abuehaze@amazon.com,doebel@amazon.de,jay.wang.upstream@gmail.com,ast@kernel.org,andrii@kernel.org,daniel@iogearbox.net,martin.lau@kernel.org,eddyz87@gmail.com,yonghong.song@linux.dev,mason@kernel.org,ihor.solodrai@linux.dev
Subject: Re: [PATCH bpf-next 3/6] bpf: fetch the vmlinux BTF where kernel types enter a program
Date: Wed, 23 Sep 2026 06:28:43 +0000 (UTC) [thread overview]
Message-ID: <39f6151d364d966f70b7802cfd4bbca15734a7945478265ecc681f1779e50abb@mail.kernel.org> (raw)
In-Reply-To: <20260923053948.30617-4-wanjay@amazon.com>
[-- Attachment #1: Type: text/plain, Size: 7017 bytes --]
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index e7c5e203eddd..a3c4caad5dfc 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -3165,6 +3165,7 @@ static inline s32 bpf_call_args_imm(s16 idx)
> #endif
>
> struct btf *bpf_get_btf_vmlinux(void);
> +struct btf *bpf_peek_btf_vmlinux(void);
>
> /* Map specifics */
> struct xdp_frame;
[ ... ]
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index a7c9e2d8965d..2425ea74b61d 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
[ ... ]
> @@ -21724,7 +21762,11 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr,
> if (ret)
> goto err_prep;
>
> - bpf_get_btf_vmlinux();
> + /*
> + * The vmlinux BTF is not fetched up front: with CONFIG_DEBUG_INFO_BTF=m
> + * it is loaded on demand, at the points where kernel types enter the
> + * program (attach_btf, kfuncs, ksyms, map pointers, BTF-typed helpers).
> + */
>
> /* Serialize verification of unprivileged programs. */
> if (!is_priv)
Does removing this unconditional bpf_get_btf_vmlinux() call break
program-context type resolution? The removed call was the sole caller of
btf_parse_vmlinux(), which is the only place that populates the file-scope
bpf_ctx_convert.t table needed by find_canonical_prog_ctx_type().
On a CONFIG_DEBUG_INFO_BTF=m kernel where the BTF hasn't been parsed yet,
consider this chain:
bpf_check() -> do_check_subprogs() -> do_check_common() ->
btf_prepare_func_args() -> btf_is_prog_ctx_type() ->
find_canonical_prog_ctx_type()
At this point, find_canonical_prog_ctx_type() returns NULL because
conv_struct = bpf_ctx_convert.t is still NULL. Then btf_is_prog_ctx_type()
logs "btf_vmlinux is malformed" and returns false.
A global subprog argument like 'struct __sk_buff *skb' or 'struct xdp_md
*ctx' then falls through to the 'generic user data pointer' branch and gets
typed ARG_PTR_TO_MEM instead of ARG_PTR_TO_CTX. At the call site
btf_check_func_arg_match() -> check_mem_reg() rejects the caller's
PTR_TO_CTX register with a confusing type error.
When libbpf emits the common 'arg:ctx' decl tag, btf_prepare_func_args()
-> btf_validate_prog_ctx_type() returns -EINVAL directly with "btf_vmlinux
is malformed".
The same NULL bpf_ctx_convert.t also breaks btf_ctx_access() ->
btf_translate_to_vmlinux() for BPF_PROG_TYPE_EXT programs loaded with
attach_prog_fd, so ctx member access in the replacement program fails.
The changelog lists the new fetch sites: kfuncs, ksyms, map_ptr access,
BTF-typed helpers, attach_btf. None of these cover the program-context
path, which needs the vmlinux BTF but never touches a PTR_TO_BTF_ID
register. The claim that "every PTR_TO_BTF_ID register a program can hold
originates from one of these sites" is true but insufficient as a coverage
argument.
The failure is non-deterministic: if anything else (a kfunc-using program,
mounting bpffs, BPF_BTF_GET_NEXT_ID) already forced the parse, the same
program loads fine. Programs that work on CONFIG_DEBUG_INFO_BTF=y
intermittently fail on =m.
Commits later in this series make this reachable: d80d57b4ec13 defers
kfunc registration until the BTF is available (removing the boot-time parse
from the first kfunc registration), and 2f5aab95d2b8 makes
CONFIG_DEBUG_INFO_BTF=m selectable. A search of the forward range
90fe51b6b36a..2f5aab95d2b8 for bpf_ctx_convert, find_canonical_prog_ctx_type,
btf_is_prog_ctx_type and btf_prepare_func_args finds only
comment/documentation text - no fix.
> @@ -21790,0 +21832,5 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr,
> if (IS_ERR(btf_vmlinux)) {
> /* Either gcc or pahole or kernel are broken. */
> verbose(env, "in-kernel BTF is malformed\n");
> ret = PTR_ERR(btf_vmlinux);
> goto skip_full_check;
> }
This check a few lines below the deleted fetch was the consumer of that
fetch: bpf_get_btf_vmlinux() stores an error pointer with
smp_store_release(&btf_vmlinux, btf) on parse failure, and bpf_check() then
converted it into the "in-kernel BTF is malformed" diagnostic.
With the fetch gone, this check reads a global that this program hasn't
caused to be populated. Whether a malformed-BTF kernel reports the clear
error or a confusing downstream one now depends on whether some earlier,
unrelated program already triggered the parse.
It also reads btf_vmlinux directly rather than through the new
bpf_peek_btf_vmlinux() accessor, so the load is not ordered against the
smp_store_release() that publishes it.
Could this check either move next to a real fetch or be dropped and let the
per-site IS_ERR_OR_NULL() handling report the failure?
> diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
> index 195f78db9bda..c022b2877f0b 100644
> --- a/kernel/trace/bpf_trace.c
> +++ b/kernel/trace/bpf_trace.c
> @@ -1015,7 +1015,8 @@ static int bpf_btf_printf_prepare(struct btf_ptr *ptr, u32 btf_ptr_size,
> if (btf_ptr_size != sizeof(struct btf_ptr))
> return -EINVAL;
>
> - *btf = bpf_get_btf_vmlinux();
> + /* Called from a running program: only use the BTF if it is parsed. */
> + *btf = bpf_peek_btf_vmlinux();
>
> if (IS_ERR_OR_NULL(*btf))
> return IS_ERR(*btf) ? PTR_ERR(*btf) : -EINVAL;
Swapping bpf_get_btf_vmlinux() for bpf_peek_btf_vmlinux() is correct as a
sleeping-in-program-context fix, but does anything in this commit arrange
for the BTF to have been parsed by the time bpf_snprintf_btf() or
bpf_seq_printf_btf() run?
The compensating verifier-time fetch in check_helper_call() is gated on
helper_uses_vmlinux_btf(), which only matches base_type(ret_type) ==
RET_PTR_TO_BTF_ID or base_type(arg_type[i]) == ARG_PTR_TO_BTF_ID.
bpf_snprintf_btf_proto and bpf_seq_printf_btf_proto contain neither: their
arguments are ARG_PTR_TO_MEM / ARG_CONST_SIZE / ARG_ANYTHING and the return
is RET_INTEGER, because the BTF type id travels inside the struct btf_ptr
the program passes by value rather than in a register type.
So helper_uses_vmlinux_btf() returns false for exactly the two helpers
whose runtime fetch was just weakened.
On a CONFIG_DEBUG_INFO_BTF=m kernel where the BTF is present but not yet
parsed, bpf_peek_btf_vmlinux() returns NULL and the helper returns -EINVAL.
A working bpf_snprintf_btf() or bpf_seq_printf_btf() call silently starts
failing, depending on whether unrelated activity already triggered the
parse.
The changelog frames this as behaving "as they do on a kernel without BTF",
but the BTF is available, just unparsed, and the previous code would have
produced correct output.
Should the fix be at verify time - teaching helper_uses_vmlinux_btf(), or
check_bpf_snprintf_call(), or the *_btf protos, to force the fetch? The
forward range 90fe51b6b36a..2f5aab95d2b8 contains no code change for this.
---
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/35824427607
next prev parent reply other threads:[~2026-09-23 6:28 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-23 5:39 [PATCH bpf-next 0/6] bpf: make the vmlinux BTF an on-demand loadable module (CONFIG_DEBUG_INFO_BTF=m) to save ~5.4 MB memory Jay Wang
2026-09-23 5:39 ` [PATCH bpf-next 1/6] bpf: pass the vmlinux BTF to btf_parse_module() and let it adopt the data Jay Wang
2026-09-23 5:39 ` [PATCH bpf-next 2/6] bpf: split the kfunc, dtor kfunc and struct_ops registration bodies Jay Wang
2026-09-23 6:16 ` bot+bpf-ci
2026-09-25 23:02 ` Jay Wang
2026-09-23 5:39 ` [PATCH bpf-next 3/6] bpf: fetch the vmlinux BTF where kernel types enter a program Jay Wang
2026-09-23 6:28 ` bot+bpf-ci [this message]
2026-09-24 11:26 ` Jiri Olsa
2026-09-25 23:02 ` Jay Wang
2026-09-25 23:02 ` Jay Wang
2026-09-23 5:39 ` [PATCH bpf-next 4/6] bpf: take the vmlinux BTF from the btf_vmlinux module Jay Wang
2026-09-23 5:39 ` [PATCH bpf-next 5/6] bpf: defer registrations until the vmlinux BTF is available Jay Wang
2026-09-23 6:41 ` bot+bpf-ci
2026-09-25 23:02 ` Jay Wang
2026-09-23 5:39 ` [PATCH bpf-next 6/6] kbuild, bpf: allow building the vmlinux BTF as a module Jay Wang
2026-09-23 8:27 ` [PATCH bpf-next 0/6] bpf: make the vmlinux BTF an on-demand loadable module (CONFIG_DEBUG_INFO_BTF=m) to save ~5.4 MB memory Alan Maguire
2026-09-25 21:23 ` Jay Wang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=39f6151d364d966f70b7802cfd4bbca15734a7945478265ecc681f1779e50abb@mail.kernel.org \
--to=bot+bpf-ci@kernel.org \
--cc=abuehaze@amazon.com \
--cc=alan.maguire@oracle.com \
--cc=andrii@kernel.org \
--cc=arnd@arndb.de \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=doebel@amazon.de \
--cc=eddyz87@gmail.com \
--cc=ihor.solodrai@linux.dev \
--cc=jay.wang.upstream@gmail.com \
--cc=linux-kbuild@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-modules@vger.kernel.org \
--cc=martin.lau@kernel.org \
--cc=martin.lau@linux.dev \
--cc=mason@kernel.org \
--cc=mcgrof@kernel.org \
--cc=memxor@gmail.com \
--cc=nathan@kernel.org \
--cc=nsc@kernel.org \
--cc=petr.pavlu@suse.com \
--cc=wanjay@amazon.com \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®