[PATCH bpf-next v2 1/5] bpf: Verify signed loader metadata at load time
Daniel Borkmann
daniel at iogearbox.net
Wed Jun 24 15:37:17 UTC 2026
Hi Paul,
On 6/24/26 5:12 PM, Paul Moore wrote:
> On Wed, Jun 24, 2026 at 10:03 AM Daniel Borkmann <daniel at iogearbox.net> wrote:
[...]
>> include/linux/bpf_verifier.h | 1 +
>> kernel/bpf/syscall.c | 76 +---------------
>> kernel/bpf/verifier.c | 163 ++++++++++++++++++++++++++++++++++-
>> 3 files changed, 165 insertions(+), 75 deletions(-)
>
> ...
>
>> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
>> index b44106c8ea75..026b61d78bdb 100644
>> --- a/kernel/bpf/syscall.c
>> +++ b/kernel/bpf/syscall.c
>> @@ -3189,10 +3121,6 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, struct bpf_log_at
>> if (err < 0)
>> goto free_prog;
>>
>> - err = security_bpf_prog_load(prog, attr, token, uattr.is_kernel);
>> - if (err)
>> - goto free_prog;
>> -
>> /* run eBPF verifier */
>> err = bpf_check(&prog, attr, uattr, attr_log);
>> if (err < 0)
>
> We must preserve the existing location of the call into the
> security_bpf_prog_load() hook as some users rely on this hook being
> called *before* the verifier runs.
Keep in mind that the verifier /at this point/ of the new location did
_not_ verify anything. So there is no heavy-duty work happening yet at
security_bpf_prog_load. The work that is done before security_bpf_prog_load
is basically setting up the env, initializing the verifier log, and doing
the process_fd_array which is resolving the map/BTF objects. But it did
not walk any instructions etc, so semantics of the security_bpf_prog_load
hook did not change from a user PoV.
>> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
>> index 2abc79dbf281..9cd2b62da380 100644
>> --- a/kernel/bpf/verifier.c
>> +++ b/kernel/bpf/verifier.c
>> @@ -19758,11 +19895,28 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr,
>> ret = bpf_vlog_init(&env->log, attr_log->level, attr_log->ubuf, attr_log->size);
>> if (ret)
>> goto err_unlock;
>> + if (env->check_signature) {
>> + ret = bpf_prog_calc_tag(env->prog);
>> + if (ret < 0)
>> + goto skip_full_check;
>> + }
>>
>> ret = process_fd_array(env, attr, uattr);
>> if (ret)
>> goto skip_full_check;
>>
>> + if (env->check_signature) {
>> + ret = bpf_prog_verify_signature(env, attr, uattr.is_kernel);
>> + if (ret)
>> + goto skip_full_check;
>> + signed_map_cnt = env->used_map_cnt;
>> + }
>> +
>> + ret = security_bpf_prog_load(env->prog, attr, env->prog->aux->token,
>> + uattr.is_kernel);
>> + if (ret)
>> + goto skip_full_check;
>
> We can always create a new LSM hook for this call site, e.g.
> security_bpf_prog_verify_signature(...).
>
>> mark_verifier_state_clean(env);
>>
>> if (IS_ERR(btf_vmlinux)) {
>
More information about the Linux-security-module-archive
mailing list