Re: [PATCH bpf-next v4 0/9] Verify BPF signed loader at load time
Paul Moore <[email protected]>
| Newsgroups | org.kernel.vger.linux-security-module,org.kernel.vger.bpf |
|---|---|
| Message-ID | <CAHC9VhRmhwCzJRgw+QikBcXFWB0ju1gYvi8h4K3=fARf-sO34w@mail.gmail.com> |
On Mon, Jul 6, 2026 at 1:47 PM Daniel Borkmann <[email protected]> wrote: > On 7/6/26 7:13 PM, Paul Moore wrote: > > On Mon, Jul 6, 2026 at 9:56 AM Daniel Borkmann <[email protected]> wrote: > >> > >> The BPF signing scheme signs a light skeleton's loader program and lets > >> the loader vouch for everything else: bpftool bakes the SHA256 of the > >> metadata map into the loader's instructions, signs the instructions, and > >> the loader compares the (frozen, exclusive) map against that hash from > >> within BPF once it runs. The construction is sound as a trusted hash > >> chain, but the kernel itself never attests the metadata, and that split > >> has been the recurring objection from the LSM / integrity side since the > >> scheme was proposed. > >> > >> This proposal closes both gaps by having the kernel verify the metadata > >> at BPF_PROG_LOAD time, before the LSM admission hook and before the > >> verifier, /without/ growing the UAPI. A signed loader binds its metadata > >> map(s) through the existing fd_array/fd_array_cnt, and exclusive maps > >> are already bound to the loader's digest via excl_prog_hash. When a > >> signature is present, the kernel collects the exclusive maps from the > >> fd_array and appends their frozen contents to the instructions before > >> PKCS#7 verification, so the signature covers ... > >> > >> insns || metadata_0 || metadata_1 || [...] > >> > >> ... in fd_array order. The in-loader hash check is dropped from the > >> gen_loader entirely: generated loaders carry no verification logic > >> anymore, and signing or verifying a skeleton becomes an ordinary CMS > >> operation over bytes that sit verbatim in the skeleton, reproducible > >> offline. A signed program is either BPF_SIG_UNSIGNED or BPF_SIG_VERIFIED > >> with nothing in between. > >> > >> There is no new UAPI, we now have a single signature scheme, no LSM > >> code reaching into BPF internals, no new LSM hook, and unsigned loads > >> are completely unaffected. It is also less complex since the loader > >> does not need to deal with BTF, an extra kfunc, etc, as proposed in > >> an earlier series [0]. Tested against full BPF CI which came back > >> green. For more details and examples, see the documentation patch in > >> this series. > >> > >> [0] https://lore.kernel.org/bpf/[email protected]/ > >> > >> v3 -> v4: > >> - Fix upper limit in MAX_FD_ARRAY_CNT (Anton) > >> - Reject !fd_array && attr->fd_array_cnt (Anton) > >> - Add bpftool patch wrt ignored return value of EVP_Digest() (sashiko) > >> - Fix setting of gen_loader_fixture_init (sashiko) > >> - Fix unused map_fd cleanup branch in selftest (bot+bpf-ci) > >> - Remove now unused map->excl member and adjust selftests > >> - Added more BPF signed_loader corner case selftest coverage > >> - Added Paul's Nack wrt bpf_prog_load LSM hook dispute > >> - Added patch 2 to move bigger allocations below fd_array > >> resolution (Paul) > > > > If you want to squash patch 2/9 and 3/9 together so that one can't > > easily merge 3/9 without the vzalloc(program) relocation I'll gladly > > drop my NACK on patch 3/9. > > Okay, I can do that and send a v5. Great, thanks. > Btw, I saw one sashiko complaint > about the security_bpf_prog_load() internally not needing the: > > [...] > if (unlikely(rc)) > security_bpf_prog_free(prog); > [...] > > since the security_bpf_prog_free() is already called via the regular > teardown path now. While there are no in-tree LSM users that are > affected by this, I'll include this as well into the squashed patch, > so its really only called once and not twice. I'd prefer to handle it like it was handled in commit 868d43cf8f97 ("bpf: Fix security_bpf_prog_load() error handling"). Since security_bpf_prog_load() acts not only as an access control point, but potentially an allocation function as well, I think it is more consistent in the error case to have the hook do whatever cleanup is necessary before returning to the caller. -- paul-moore.com