From: KP Singh <kpsingh@xxxxxxxxxx> # Motivation Signaling and mitigation are two key aspects of security which go hand-in-hand. Signals provide the necessary context to narrow down a malicious actor and are key to creating effective MAC policies to mitigate/prevent the malicious actor. One can obtain signals from the kernel by using the audit infrastructure. System-wide MAC is done separately as a part of the LSMs (eg. SELinux, AppArmor). Augmenting the signal information provided by audit requires kernel changes to audit, its policy language and user-space components. Furthermore, building a MAC policy based on the newly added signal requires changes to various LSMs and their own respective policy languages. KRSI attempts to solve this problem by providing a common policy API in the form of security focussed eBPF helpers and a common surface for creating dynamic (not requiring re-compilation of the kernel) MAC and Audit policies by attaching eBPF programs to the various LSM hooks. # Why an LSM? Linux Security Modules target security behaviours rather than the API. For example, it's easy to miss out a newly added system call for executing processes (eg. execve, execveat etc.) while the LSM framework ensures that all process executions trigger the relevant hooks irrespective of how the process was executed. Allowing users to attach eBPF programs to LSM hooks also benefits the LSM eco-system by enabling feedback from the security community about the kind of behaviours that the LSM should be targeting. # How does it work? NOTE: The cover letter will be assimilated into the documentation (Documentation/security/) as a part of the patch series. ## SecurityFS Interface KRSI hooks create a file in securityfs to which eBPF programs can be attached. This file maps to a single LSM hook but adds a layer of indirection thus shielding the user-space from any changes to the underlying hook. This includes changes like renaming of the underlying hook or replacing the hook with another that maps better to the security behaviour represented. For Example: /sys/kernel/security/krsi/process_execution -> bprm_check_security ## eBPF Program / Helpers In order to keep things simple for the user, KRSI intends to provide one eBPF program type. Since, there is only one type of context for a given eBPF program type, the members of the KRSI context are selectively populated depending on the hook. KRSI is conservative about the access into the context and expects users to use the helpers as an API for getting the required information. This helps limit the internals of the LSM exposed to the user and maintain backward compatibility. It also allows the maintainers to update the structure of the context without worrying about breaking user-space. The intention is to keep the helpers precise and not depend on kernel headers or internals strengthening the backward compatibility and usability across a large and diverse fleet. Precise helpers also help in tackling seemingly intractable problems. For example, a helper to dump all environment variables is hard because the environment variables can be 32 pages long. While a helper to only extract certain relevant environment variables (e.g. LD_PRELOAD, HISTFILESIZE) helps in building a more reliable and precise signal with lower overhead. ## Attachment A privileged (CAP_SYS_ADMIN for loading / attaching eBPF programs) user-space program opens the securityfs file and the eBPF program (BPF_PROG_LOAD) and attaches (BPF_PROG_ATTACH) the eBPF program to the hook. hook_fd = open("/sys/kernel/security/krsi/process_execution", O_RDWR) prog_fd = bpf(BPF_PROG_LOAD, ...) bpf(BPF_PROG_ATTACH, hook_fd, prog_fd) There can be more than one program attached to a hook and attaching a program with the same name replaces the existing program. The user can see the programs attached to the hook as follows: cat /sys/kernel/security/krsi/process_execution env_dumper my_auditor ## Audit / MAC Policy The userspace controls the policy by installing eBPF programs to the LSM hook. If any of the attached eBPF programs return an error (-ENOPERM), the action represented by the hook is denied. The audit logs are written using a format chosen by the eBPF program to the perf events buffer (using bpf_perf_event_output) and can be further processed in user-space. # Current Status The RFC provides a proto-type implementation with a few helpers and a sample program samples/bpf/krsi_kern.c that hooks into process execution and logs specific environment variables to the perf events buffer. The user-space program samples/bpf/krsi_user.c loads the eBPF program, configures the environment variable that needs to be audited and listens for perf events. KP Singh (14): krsi: Add a skeleton and config options for the KRSI LSM krsi: Introduce types for KRSI eBPF bpf: krsi: sync BPF UAPI header with tools krsi: Add support in libbpf for BPF_PROG_TYPE_KRSI krsi: Initialize KRSI hooks and create files in securityfs krsi: Implement eBPF operations, attachment and execution krsi: Check for premissions on eBPF attachment krsi: Show attached program names in hook read handler. krsi: Add a helper function for bpf_perf_event_output krsi: Handle attachment of the same program krsi: Pin argument pages in bprm_check_security hook krsi: Add an eBPF helper function to get the value of an env variable krsi: Provide an example to read and log environment variables krsi: Pin arg pages only when needed MAINTAINERS | 8 + include/linux/bpf_types.h | 3 + include/linux/krsi.h | 19 ++ include/uapi/linux/bpf.h | 44 ++- kernel/bpf/syscall.c | 7 + samples/bpf/.gitignore | 1 + samples/bpf/Makefile | 3 + samples/bpf/krsi_helpers.h | 31 ++ samples/bpf/krsi_kern.c | 52 ++++ samples/bpf/krsi_user.c | 202 +++++++++++++ security/Kconfig | 1 + security/Makefile | 2 + security/krsi/Kconfig | 22 ++ security/krsi/Makefile | 3 + security/krsi/include/hooks.h | 22 ++ security/krsi/include/krsi_fs.h | 19 ++ security/krsi/include/krsi_init.h | 106 +++++++ security/krsi/krsi.c | 157 ++++++++++ security/krsi/krsi_fs.c | 190 ++++++++++++ security/krsi/ops.c | 342 ++++++++++++++++++++++ tools/include/uapi/linux/bpf.h | 44 ++- tools/lib/bpf/libbpf.c | 4 + tools/lib/bpf/libbpf.h | 2 + tools/lib/bpf/libbpf.map | 2 + tools/lib/bpf/libbpf_probes.c | 1 + tools/testing/selftests/bpf/bpf_helpers.h | 3 + 26 files changed, 1288 insertions(+), 2 deletions(-) create mode 100644 include/linux/krsi.h create mode 100644 samples/bpf/krsi_helpers.h create mode 100644 samples/bpf/krsi_kern.c create mode 100644 samples/bpf/krsi_user.c create mode 100644 security/krsi/Kconfig create mode 100644 security/krsi/Makefile create mode 100644 security/krsi/include/hooks.h create mode 100644 security/krsi/include/krsi_fs.h create mode 100644 security/krsi/include/krsi_init.h create mode 100644 security/krsi/krsi.c create mode 100644 security/krsi/krsi_fs.c create mode 100644 security/krsi/ops.c -- 2.20.1