bpflock - eBPF driven security for locking and auditing Linux machines.
Note: bpflock is currently in experimental stage, it may break, options and security semantics may change, some BPF programs will be updated to use Cilium ebpf library.
bpflock uses eBPF to strength Linux security. By restricting access to a various range of Linux features, bpflock is able to reduce the attack surface and block some well known attack techniques.
Only programs like container managers, systemd and other containers/programs that run in the host pid
namespace may be able to access those features, containers
that run on their own namespace will be restricted. If bpflock bpf programs run under a restricted
profile then all
programs/containers will be denied access even privileged ones. The filtering model will be augmented soon to include
per cgroupv2 filetring.
bpflock protects Linux machines by taking advantage of multiple security features including Linux Security Modules + BPF.
Architecture and Security design notes:
- bpflock is not a mandatory access control labeling solution, and it does not intent to replace AppArmor, SELinux, and other MAC solutions. bpflock uses a simple declarative security profile.
- bpflock offers multiple small bpf programs that can be reused in multiple contexts from Cloud Native deployments to Linux IoT devices.
- bpflock is able to restrict root to access certain Linux features, however it does not protect against evil root users that can disable it.
bpflock offer multiple security protections that can be classified as:
-
System and Application tracing
- Trace privileged system operations
- Trace applications at runtime
-
Filesystem Protections
- Read-only root filesystem protection
- sysfs protection
-
Linux Namespaces Protections
-
Network protections
- bpflock may include in future a simple network protection that can be used in single machine workload or Linux-IoT, but will not include a Cloud Native protection. Cilium and other kubernetes CNI related solutions are by far better.
bpflock keeps the security semantics simple. It support three declarative profiles models to broadly cover the security sepctrum, and restrict access to specific Linux features.
-
profile
:allow|none|privileged
: they are the same, they define the least secure profile. In this profile access is logged and allowed for all processes, useful for security events.baseline
: minimal restricive profile, only programs in the initial pid namespace are allowed access.restricted
: heavily restricted profile where access is denied for all processes.
-
Allowed
orblocked
operations/commands:Under the
baseline
profile, a list of allowed or blocked commands can be specified that will be applied to the type of security protection.--protection-allow
: comma-separated list of allowed operations. Valid underbaseline
profile, this is useful for applications that are too specific and require privileged operations, it will reduce the use of theallow | privileged
profile and offer a case-by-case definitions.--protection-block
: comma-separated list of blocked operations. Valid underbaseline
profile, useful to achieve a morerestricted
profile. The other way fromrestricted
tobaseline
is not supported.
For bpf security examples check bpflock configuration examples
bpflock needs the following:
-
Linux kernel version >= 5.15 with the following configuration:
CONFIG_BPF_SYSCALL=y CONFIG_DEBUG_INFO=y CONFIG_DEBUG_INFO_BTF=y CONFIG_KPROBES=y CONFIG_LSM="...,bpf" CONFIG_BPF_LSM=y
-
Obviously a BTF enabled kernel.
To run using the default allow
or privileged
profile (the least secure profile):
docker run --name bpflock -it --rm --cgroupns=host \
--pid=host --privileged \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
Then in another terminal read from the tracing pipe to see logs:
sudo cat /sys/kernel/debug/tracing/trace_pipe
Note: this is a temporary testing solution, bpflock will soon display all logs directly.
To apply Kernel Modules Protection
run with environment variable BPFLOCK_KMODLOCK_PROFILE=baseline
or BPFLOCK_KMODLOCK_PROFILE=restricted
:
docker run --name bpflock -it --rm --cgroupns=host --pid=host --privileged \
-e "BPFLOCK_KMODLOCK_PROFILE=baseline" \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
Example:
$ sudo unshare -f -p bash
# modprobe xfs
modprobe: ERROR: could not insert 'xfs': Operation not permitted
modprobe-399022 [002] d...1 427205.192790: bpf_trace_printk: bpflock bpf=kmodlock pid=399022 event=module load from non init pid namespace status=denied (baseline)
To apply Kernel Image Lock-down run with environment variable BPFLOCK_KIMGLOCK_PROFILE=baseline
or BPFLOCK_KIMGLOCK_PROFILE=restricted
:
docker run --name bpflock -it --rm --cgroupns=host --pid=host --privileged \
-e "BPFLOCK_KIMGLOCK_PROFILE=baseline" \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
To apply bpf restriction run with environment variable BPFLOCK_BPFRESTRICT_PROFILE=baseline
or BPFLOCK_BPFRESTRICT_PROFILE=restricted
:
docker run --name bpflock -it --rm --cgroupns=host --pid=host --privileged \
-e "BPFLOCK_BPFRESTRICT_PROFILE=baseline" \
-v /sys/kernel/:/sys/kernel/ \
-v /sys/fs/bpf:/sys/fs/bpf linuxlock/bpflock
Example:
$ sudo unshare -f -p bash
# bpftool prog
Error: can't get next program: Operation not permitted
bpftool-399330 [002] d...1 427673.628475: bpf_trace_printk: bpflock bpf=bpfrestrict pid=399330 comm=bpftool event=bpf() from non init pid namespace
bpftool-399330 [002] d...1 427673.628522: bpf_trace_printk: bpflock bpf=bpfrestrict pid=399330 event=bpf() from non init pid namespace status=denied (baseline)
Documentation files can be found here.
bpflock uses docker BuildKit to build and Golang to make some checks and run tests. bpflock is built inside Ubuntu container that downloads the standard golang package.
Run the following to build the bpflock docker container:
git submodule update --init --recursive
make
Bpf programs are built using libbpf. The docker image used is Ubuntu.
If you want to only build the bpf programs directly without using docker, then on Ubuntu:
sudo apt install -y pkg-config bison binutils-dev build-essential \
flex libc6-dev clang-12 libllvm12 llvm-12-dev libclang-12-dev \
zlib1g-dev libelf-dev libfl-dev gcc-multilib zlib1g-dev \
libcap-dev libiberty-dev libbfd-dev
Then run:
make bpf-programs
In this case the generated programs will be inside the ./bpf/build/... directory.
bpflock uses lot of resources including source code from the Cilium and bcc projects.
The bpflock user space components are licensed under the Apache License, Version 2.0. The BPF code where it is noted is licensed under the General Public License, Version 2.0.