Re: [PATCH] bpf: fix btf_types_are_same for cross-BTF type comparison

From: Alan Maguire

Date: Tue Apr 07 2026 - 07:21:33 EST


On 07/04/2026 09:09, chenyuan_fl@xxxxxxx wrote:
> From: Yuan Chen <chenyuan@xxxxxxxxxx>
>
> When comparing types from different BTF objects (e.g., module BTF vs
> vmlinux BTF), the original btf_types_are_same() returns false because:
> - Type IDs are local to each BTF
> - Pointer comparison of btf_type_by_id results always fails
>
> This prevents kfuncs with KF_IMPLICIT_ARGS flag from modules (like
> bpf_kfunc_multi_st_ops_test_1_assoc) from properly recognizing implicit
> arguments such as 'struct bpf_prog_aux *', causing the verifier to not
> inject the aux pointer value during fixup.
>
> Fix by comparing actual type content (kind, size, name) when BTFs are
> different instead of comparing pointers.
>
> Signed-off-by: Yuan Chen <chenyuan@xxxxxxxxxx>
> ---
> kernel/bpf/btf.c | 32 ++++++++++++++++++++++++++++----
> 1 file changed, 28 insertions(+), 4 deletions(-)
>
> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
> index a62d78581207..daad28ae32e5 100644
> --- a/kernel/bpf/btf.c
> +++ b/kernel/bpf/btf.c
> @@ -7432,15 +7432,39 @@ int btf_struct_access(struct bpf_verifier_log *log,
> * the same. Trivial ID check is not enough due to module BTFs, because we can
> * end up with two different module BTFs, but IDs point to the common type in
> * vmlinux BTF.
> + *
> + * When comparing types across different BTF objects (e.g., module BTF vs
> + * vmlinux BTF), we need to compare the actual type content (name, kind, size)
> + * since type IDs may differ between BTF objects even for the same type.
> */
> bool btf_types_are_same(const struct btf *btf1, u32 id1,
> const struct btf *btf2, u32 id2)
> {
> - if (id1 != id2)
> - return false;
> + const struct btf_type *t1, *t2;it wo
> +
> + /* If same BTF object, ID comparison is sufficient */
> if (btf1 == btf2)
> - return true;
> - return btf_type_by_id(btf1, id1) == btf_type_by_id(btf2, id2);
> + return id1 == id2;
> +
> + /* Different BTF objects - compare actual type content.
> + * Type IDs may differ between module BTF and vmlinux BTF,
> + * so we need to check if the types are semantically identical.
> + */
> + t1 = btf_type_by_id(btf1, id1);
> + t2 = btf_type_by_id(btf2, id2);
> + if (!t1 || !t2)
> + return false;
> +
> + /* Must be same kind and have same name */
> + if (BTF_INFO_KIND(t1->info) != BTF_INFO_KIND(t2->info))
> + return false;
> + if (t1->size != t2->size)
> + return false;
> + if (strcmp(__btf_name_by_offset(btf1, t1->name_off),
> + __btf_name_by_offset(btf2, t2->name_off)) != 0)
> + return false;
> +
> + return true;
> }
>
> bool btf_struct_ids_match(struct bpf_verifier_log *log,

This feels insufficient as a type equality check; for pointer types
as cited in the commit message, it will only really work if the
pointed-to type ids (t1->size, t2->size above) are identical ids.
That may work narrowly in the specific case you're dealing with but I'd suggest
looking at how libbpf dedup handles this and figure out a depth-limited
recursive equivalence check that winds up comparing structs/base types rather than
reference types.