Re: [PATCH bpf-next 11/13] bpf: keep module BTF until the vmlinux BTF is parsed

From: Alexei Starovoitov

Date: Sat Oct 31 2026 - 13:11:58 EST


On Sat, Oct 31, 2026 at 06:55 AM bot+bpf-ci@xxxxxxxxxx <bot+bpf-ci@xxxxxxxxxx> wrote:
>> +/* Undo btf_parse_kept_modules() of a round that is not published */
>> +static void btf_unparse_kept_modules(void)
>> +{
> [ ... ]
>> + btf_mod->btf->data = NULL; /* the kept copy */
>> + btf_put(btf_mod->btf);
>> + btf_mod->btf = NULL;
>> + }
>> +}
[...]
> Can a module BTF that is rolled back by btf_unparse_kept_modules() still be
> reachable through btf_idr?

Yes. It's real. The NULL deref in the inline BTF is real too.

This is quite heavy. As you can see both bots poked plenty of holes.
Five of them are in the -ENOMEM rollback of patches 10 and 11:

where what goes wrong
--------------------------- -------------------------------------------
btf_get_fd_by_id() takes a ref on a BTF that is rolled back
btf_free_rcu() reads btf_mod->data that rmmod freed
btf_parse_kept_modules() -ENOMEM in the inline BTF removes its file
bpf_struct_ops_desc_init() -ENOMEM of ->init() becomes -EINVAL
btf_vmlinux_data() -ENOMEM without btf_zst repeats forever

The rollback exists because vmalloc() gives up when the task is killed.

can we run the parse from a work item, schedule_work() + flush_work() ?
A kworker gets no signals, so -ENOMEM can be final, like without the
option. Every parse then ends in smp_store_release(&btf_vmlinux), and
btf_get_fd_by_id() sleeps on btf_vmlinux_lock until that.
Then no need for the retry, btf_unparse_kept_modules(), the 2nd call
of ->init(), etc.

See my other reply.

pw-bot: cr