On Fri, May 2, 2025 at 2:44 PM Blaise Boscaccy <bbosca...@linux.microsoft.com> wrote: > > This adds the Hornet Linux Security Module which provides signature > verification of eBPF programs. This allows users to continue to > maintain an invariant that all code running inside of the kernel has > been signed. > > The primary target for signature verification is light-skeleton based > eBPF programs which was introduced here: > https://lore.kernel.org/bpf/20220209054315.73833-1-alexei.starovoi...@gmail.com/ > > eBPF programs, before loading, undergo a complex set of operations > which transform pseudo-values within the immediate operands of > instructions into concrete values based on the running > system. Typically, this is done by libbpf in > userspace. Light-skeletons were introduced in order to support > preloading of bpf programs and user-mode-drivers by removing the > dependency on libbpf and userspace-based operations. > > Userpace modifications, which may change every time a program gets > loaded or runs on a slightly different kernel, break known signature > verification algorithms. A method is needed for passing unadulterated > binary buffers into the kernel in-order to use existing signature > verification algorithms. Light-skeleton loaders with their support of > only in-kernel relocations fit that constraint. > > Hornet employs a signature verification scheme similar to that of > kernel modules. A signature is appended to the end of an > executable file. During an invocation of the BPF_PROG_LOAD subcommand, > a signature is extracted from the current task's executable file. That > signature is used to verify the integrity of the bpf instructions and > maps which were passed into the kernel. Additionally, Hornet > implicitly trusts any programs which were loaded from inside kernel > rather than userspace, which allows BPF_PRELOAD programs along with > outputs for BPF_SYSCALL programs to run. > > The validation check consists of checking a PKCS#7 formatted signature > against a data buffer containing the raw instructions of an eBPF > program, followed by the initial values of any maps used by the > program. Maps are verified to be frozen before signature verification > checking to stop TOCTOU attacks. > > Signed-off-by: Blaise Boscaccy <bbosca...@linux.microsoft.com> > --- > Documentation/admin-guide/LSM/Hornet.rst | 65 ++++++ > Documentation/admin-guide/LSM/index.rst | 1 + > MAINTAINERS | 9 + > crypto/asymmetric_keys/pkcs7_verify.c | 10 + > include/linux/kernel_read_file.h | 1 + > include/linux/verification.h | 1 + > include/uapi/linux/lsm.h | 1 + > security/Kconfig | 3 +- > security/Makefile | 1 + > security/hornet/Kconfig | 24 +++ > security/hornet/Makefile | 4 + > security/hornet/hornet_lsm.c | 250 +++++++++++++++++++++++ > security/selinux/hooks.c | 12 +- > security/selinux/include/classmap.h | 2 +- > 14 files changed, 380 insertions(+), 4 deletions(-) > create mode 100644 Documentation/admin-guide/LSM/Hornet.rst > create mode 100644 security/hornet/Kconfig > create mode 100644 security/hornet/Makefile > create mode 100644 security/hornet/hornet_lsm.c
... > +Configuration Options > +===================== > + > +Hornet provides a kconfig knob > +CONFIG_SECURITY_HORNET_WHITELIST_PID_ONE. Enabling this will allow > +bpf programs to be loaded from pid 1 without undergoing a signature > +verification check. This option is not recommened for production > +systems. ... > +config SECURITY_HORNET_WHITELIST_PID_ONE > + bool "Whiltelist unsigned eBPF programs from PID 1" > + depends on SECURITY_HORNET > + default n > + help > + Selecting this will configure Hornet to allow eBPF loaded from pid 1 > + to load without a verification check. > + Further information can be found in > + Documentation/admin-guide/LSM/Hornet.rst. > + > + If you are unsure how to answer this question, answer N. ... > +static int hornet_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr, > + struct bpf_token *token, bool is_kernel) > +{ > + if (is_kernel) > + return 0; > +#ifdef CONFIG_SECURITY_HORNET_WHITELIST_PID_ONE > + if (current->pid == 1) > + return 0; > +#endif Two quick comments on the build-time conditional above. First, unless there is some subtle reason why you only want the exception above to apply to a single thread in the init process, I would suggest using task_tgid_nr() instead of current->pid as I believe you want the init exception to apply to all threads running within the init process. Second, I think it would be helpful to rename the Kconfig knob to CONFIG_SECURITY_HORNET_PIDONE_TRANSITION, or similar, to help indicate that this is a transitional configuration option designed to make it easier for developers to move to a system with signed BPF programs without excessive warnings/errors from systemd in the beginning. I would highlight the transitory intent of this Kconfig knob both in the Kconfig description as well as the Hornet.rst doc, a brief explanation of the drawback for enabling this long term or on "production" systems in the Hornet.rst section would also be a good idea. -- paul-moore.com