Thread (26 messages) 26 messages, 7 authors, 2025-06-04

Re: [PATCH 0/3] BPF signature verification

From: Blaise Boscaccy <hidden>
Date: 2025-05-30 22:14:58
Also in: bpf, keyrings, linux-crypto, lkml

KP Singh [off-list ref] writes:
On Fri, May 30, 2025 at 11:19 PM Blaise Boscaccy
[off-list ref] wrote:
quoted
KP Singh [off-list ref] writes:
[...]
quoted
quoted
And that isn't at odds with the kernel being able to do it nor is it
with what I posted.
quoted
If your build environment that signs the BPF program is compromised
and can inject arbitrary code, then signing does not help.  Can you
explain what a supply chain attack would look like here?
Most people here can read C code. The number of people that can read
ebpf assembly metaprogramming code is much smaller. Compromising clang
is one thing, compromising libbpf is another. Your proposal increases
the attack surface with no observable benefit. If I was going to leave a
hard-to-find backdoor into ring0, gen.c would be a fun place to explore
doing it. Module and UEFI signature verification code doesn't live
inside of GCC or Clang as set of meta-instructions that get emitted, and
there are very good reasons for that.

Further, since the signature verification code is unique for each and
every program it needs to be verified/proved/tested for each and every
program. Additionally, since all these checks are being forced outside
of the kernel proper, with the insistence of keeping the LSM layer in
the dark of the ultimate result, the only way to test that a program
will fail if the map is corrupted is to physically corrupt each and
every program and test that individually. That isn't "elegant" nor "user
friendly" in any way, shape or form.
quoted
quoted
subsystem.  Additionally, it is impossible to verify the code
performing the signature verification, as it is uniquely regenerated
The LSM needs to ensure that it allows trusted LOADER programs i.e.
with signatures and potentially trusted signed user-space binaries
with unsigned or delegated signing (this will be needed for Cilium and
bpftrace that dynamically generate BPF programs), that's a more
important aspect of the LSM policy from a BPF perspective.
I would like to be able to sign my programs please and have the kernel
verify it was done correctly. Why are you insisting that I *don't* do
that?  I'm yet to see any technical objection to doing that. Do you have
one that you'd like to share at this point?
The kernel allows a trusted loader that's signed with your private
key, that runs in the kernel context to delegate the verification.
This pattern of a trusted / delegated loader is going to be required
for many of the BPF use-cases that are out there (Cilium, bpftrace)
that dynamically generate eBPF programs.

The technical objection is that:

* It does not align with most BPF use-cases out there as most
use-cases need a trusted loader.
No, it's definitely a use case. It's trivial to support both a trusted
loader and a signature over the hash chain of supplied assets.
* Locks us into a UAPI, whereas a signed LOADER allows us to
incrementally build signing for all use-cases without compromising the
security properties.
Your proposal locks us into a UAPI as well. There is no way to make to
do this via UAPI without making a UAPI design choice.
BPF's philosophy is that of flexibility and not locking the users into
a rigid in-kernel implementation and UAPI.
Then why are you locking us into a rigid
only-signing-the-loader-is-allowed implementation?
- KP
quoted
quoted
MAP_EXCLUSIVE is missing and is required which prevents maps from
being accessed by other programs as explained in the proposal.

Please hold off on further iterations, I am working on a series and
will share these patches based on the design that was proposed.
So the premise here seems to be that people should only be allowed to
sign trusted loaders, and that trusted loaders must additionally be
authored by you, correct?

When can we expect to see your patchset posted?
quoted
quoted
for every program.



2. Timing of Signature Check

This patchset moves the signature check to a point before
security_bpf_prog_load is invoked, due to an unresolved discussion
here:
This is fine and what I had in mind, signature verification does not
need to happen in the verifier and the existing hooks are good enough.
I did not reply to Paul's comment since this is a fairly trivial
detail and would be obvious in the implementation that the verifier is
not the right place to check the signature anyways as the instruction
buffer is only stable pre-verification.
quoted
https://lore.kernel.org/linux-security-module/CAHC9VhTj3=ZXgrYMNA+G64zsOyZO+78uDs1g=kh91=GR5KypYg@mail.gmail.com/ (local)
This change allows the LSM subsystem to be informed of the signature
verification result—if it occurred—and the method used, all without
introducing a new hook. It improves visibility and auditability,
reducing the “trust me, friend” aspect of the original design.

On Wed, May 28, 2025 at 11:50 PM Blaise Boscaccy
[off-list ref] wrote:
quoted
As suggested or mandated by KP Singh
https://lore.kernel.org/linux-security-module/CACYkzJ6VQUExfyt0=-FmXz46GHJh3d=FXh5j4KfexcEFbHV-vg@mail.gmail.com/ (local),
this patchset proposes and implements an alternative hash-chain
algorithm for signature verification of BPF programs.

This design diverges in two key ways:

1. Signature Strategy

Two different signature strategies are
implemented. One verifies only the signature of the loader program in
the kernel, as described in the link above. The other verifies the
program’s maps in-kernel via a hash chain.  The original design
required loader programs to be “self-aborting” and embedded the
terminal hash verification logic as metaprogramming code generation
routines inside libbpf. While this patchset supports that scheme, it
is considered undesirable in certain environments due to the potential
for supply-chain attack vectors and the lack of visibility for the LSM
subsystem.  Additionally, it is impossible to verify the code
performing the signature verification, as it is uniquely regenerated
for every program.

2. Timing of Signature Check

This patchset moves the signature check to a point before
security_bpf_prog_load is invoked, due to an unresolved discussion
here:
https://lore.kernel.org/linux-security-module/CAHC9VhTj3=ZXgrYMNA+G64zsOyZO+78uDs1g=kh91=GR5KypYg@mail.gmail.com/ (local)
This change allows the LSM subsystem to be informed of the signature
verification result—if it occurred—and the method used, all without
introducing a new hook. It improves visibility and auditability,
reducing the “trust me, friend” aspect of the original design.


Blaise Boscaccy (3):
  bpf: Add bpf_check_signature
  bpf: Support light-skeleton signatures in autogenerated code
  bpftool: Allow signing of light-skeleton programs

 include/linux/bpf.h            |   2 +
 include/linux/verification.h   |   1 +
 include/uapi/linux/bpf.h       |   4 +
 kernel/bpf/arraymap.c          |  11 +-
 kernel/bpf/syscall.c           | 123 +++++++++++++++++++-
 tools/bpf/bpftool/Makefile     |   4 +-
 tools/bpf/bpftool/common.c     | 204 +++++++++++++++++++++++++++++++++
 tools/bpf/bpftool/gen.c        |  66 ++++++++++-
 tools/bpf/bpftool/main.c       |  24 +++-
 tools/bpf/bpftool/main.h       |  23 ++++
 tools/include/uapi/linux/bpf.h |   4 +
 tools/lib/bpf/libbpf.h         |   4 +
 tools/lib/bpf/skel_internal.h  |  28 ++++-
 13 files changed, 491 insertions(+), 7 deletions(-)

--
2.48.1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help