[PATCH v3 1/4] security: Hornet LSM
Paul Moore
paul at paul-moore.com
Sun May 4 15:02:52 UTC 2025
On Fri, May 2, 2025 at 2:44 PM Blaise Boscaccy
<bboscaccy at 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.starovoitov@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 <bboscaccy at 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
More information about the Linux-security-module-archive
mailing list