Re: [PATCH] libbpf: poison unresolved weak kfuncs in light skeletons

From: Alexei Starovoitov

Date: Thu Jun 25 2026 - 20:46:08 EST


On Mon, Jun 22, 2026 at 4:04 PM Siddharth Nayyar <sidnayyar@xxxxxxxxxx> wrote:
>
> When the light skeleton generator (gen_loader) fails to find a BTF ID
> for a weak kfunc, it correctly clears the immediate value (imm = 0) to
> convert the pseudo kfunc call into an invalid instruction.
>
> However, the generator fails to clear src_reg (which is set to
> BPF_PSEUDO_KFUNC_CALL). This leaves the instruction looking like a valid
> pseudo kfunc call with a zero BTF ID. When the target verifier's
> add_subprog_and_kfunc encounters this, it unconditionally scans all
> BPF_PSEUDO_KFUNC_CALL instructions, sees imm == 0, and panics or
> fails the load (e.g. bpf_unspec#0 or -EINVAL). This entirely breaks
> the verifier's dead-code elimination logic which expects to cleanly prune
> branches protected by bpf_ksym_exists().
>
> Furthermore, when the generator processes subsequent references to the
> same unresolved weak kfunc, it copies the imm and off fields from
> the first occurrence but skips the src_reg field, meaning subsequent
> calls also retain the poisonous BPF_PSEUDO_KFUNC_CALL flag.
>
> This patch fixes the issue by explicitly clearing src_reg for both the
> initial occurrence and all subsequent occurrences of unresolved weak
> kfuncs, converting them into standard invalid helper calls that the
> verifier's dead-code eliminator can safely recognize and discard.
>
> Signed-off-by: Siddharth Nayyar <sidnayyar@xxxxxxxxxx>
> ---
> tools/lib/bpf/gen_loader.c | 15 ++++++++++++---
> 1 file changed, 12 insertions(+), 3 deletions(-)
>
> diff --git a/tools/lib/bpf/gen_loader.c b/tools/lib/bpf/gen_loader.c
> index d79695f01c87..a08071114347 100644
> --- a/tools/lib/bpf/gen_loader.c
> +++ b/tools/lib/bpf/gen_loader.c
> @@ -783,10 +783,17 @@ static void emit_relo_kfunc_btf(struct bpf_gen *gen, struct ksym_relo_desc *relo
> return;
> /* try to copy from existing bpf_insn */
> if (kdesc->ref > 1) {
> - move_blob2blob(gen, insn + offsetof(struct bpf_insn, imm), 4,
> - kdesc->insn + offsetof(struct bpf_insn, imm));
> move_blob2blob(gen, insn + offsetof(struct bpf_insn, off), 2,
> kdesc->insn + offsetof(struct bpf_insn, off));
> + move_blob2blob(gen, insn + offsetof(struct bpf_insn, imm), 4,
> + kdesc->insn + offsetof(struct bpf_insn, imm));

why did you change the order?
Looks like an unrelated change.

pw-bot: cr