From: Daniel Borkmann <daniel@iogearbox.net>
To: ast@kernel.org
Cc: kpsingh@kernel.org, James.Bottomley@hansenpartnership.com,
paul@paul-moore.com, bboscaccy@linux.microsoft.com,
memxor@gmail.com, torvalds@linux-foundation.org,
bpf@vger.kernel.org, linux-security-module@vger.kernel.org
Subject: [PATCH bpf-next 0/5] Verify BPF signed loader at load time
Date: Thu, 11 Jun 2026 01:03:24 +0200 [thread overview]
Message-ID: <20260610230329.727075-1-daniel@iogearbox.net> (raw)
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/20260522023234.3778588-1-kpsingh@kernel.org/
Daniel Borkmann (5):
bpf: Verify signed loader metadata at load time
libbpf: Drop in-loader metadata check for load-time verification
bpftool: Cover loader metadata with the program signature
selftests/bpf: Verify load-time signed loader metadata
Documentation/bpf: Add BPF signing and enforcement doc
Documentation/bpf/index.rst | 1 +
Documentation/bpf/signing.rst | 537 ++++++++++++++++++
kernel/bpf/syscall.c | 169 +++++-
tools/bpf/bpftool/gen.c | 2 +
tools/bpf/bpftool/sign.c | 15 +-
tools/lib/bpf/bpf_gen_internal.h | 1 -
tools/lib/bpf/gen_loader.c | 76 +--
tools/lib/bpf/skel_internal.h | 27 +-
.../selftests/bpf/prog_tests/signed_loader.c | 460 +++++++++------
9 files changed, 994 insertions(+), 294 deletions(-)
create mode 100644 Documentation/bpf/signing.rst
--
2.43.0
next reply other threads:[~2026-06-10 23:03 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-10 23:03 Daniel Borkmann [this message]
2026-06-10 23:03 ` [PATCH bpf-next 1/5] bpf: Verify signed loader metadata at load time Daniel Borkmann
2026-06-10 23:03 ` [PATCH bpf-next 2/5] libbpf: Drop in-loader metadata check for load-time verification Daniel Borkmann
2026-06-10 23:03 ` [PATCH bpf-next 3/5] bpftool: Cover loader metadata with the program signature Daniel Borkmann
2026-06-10 23:48 ` bot+bpf-ci
2026-06-10 23:03 ` [PATCH bpf-next 4/5] selftests/bpf: Verify load-time signed loader metadata Daniel Borkmann
2026-06-10 23:03 ` [PATCH bpf-next 5/5] Documentation/bpf: Add BPF signing and enforcement doc Daniel Borkmann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260610230329.727075-1-daniel@iogearbox.net \
--to=daniel@iogearbox.net \
--cc=James.Bottomley@hansenpartnership.com \
--cc=ast@kernel.org \
--cc=bboscaccy@linux.microsoft.com \
--cc=bpf@vger.kernel.org \
--cc=kpsingh@kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=memxor@gmail.com \
--cc=paul@paul-moore.com \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox