[PATCH bpf-next v2 1/5] bpf: Verify signed loader metadata at load time
Paul Moore
paul at paul-moore.com
Wed Jun 24 18:42:23 UTC 2026
On Wed, Jun 24, 2026 at 11:37 AM Daniel Borkmann <daniel at iogearbox.net> wrote:
> 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.
There is still a reasonable amount of work between the existing and
new call sites, and the existing location outside of bpf_check()
offers an additional robustness benefit that future verifier changes
are less likely to impact the hook. If I'm completely honest, I also
need to consider the events of the past year and a half; I'm now much
less inclined to support LSM hook changes in the BPF subsystem because
I'm very concerned about our ability to revert/modify those changes in
the future if needed. That doesn't mean I won't support LSM hook
changes in BPF, but such changes are going to need to have a *very*
strong advantage from a LSM perspective to offset the risk associated
with the current BPF subsystem.
Based on what I see in this patchset, the security_bpf_prog_load()
call should remain in the current location. If you need an additional
hook after the bpf_prog_verify_signature() call I'm happy to work with
you on that.
I also have to bring up the same question I asked back in your v1
posting: have you discussed this signature approach with Alexei? Your
patches abandon and remove KP's signature scheme in favor of what is
effectively Blaise's signature scheme from last fall; Alexei argued
very strongly against these changes in the past. I'd hate to spend a
lot more time reviewing and discussing patches that Alexei is simply
going to NACK once again.
> >> 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)) {
--
paul-moore.com
More information about the Linux-security-module-archive
mailing list