Skip to content

Repository files navigation

bpfima

eBPF-based integrity monitoring system with container tracking, Merkle tree verification, TPM integration, and policy-based configuration.

Overview

This system monitors file operations and container events using eBPF LSM and kprobe hooks. Measurements are organized per-container in a Merkle tree structure, with the root hash extended to a configurable TPM PCR (default: PCR 23) for hardware-backed attestation.

NEW: Policy-based configuration system allows fine-grained control over what gets measured, filtered, and how events are processed - configured via BPF maps and enforced at the kernel level.

Directory Structure

bpfima/
├── build/                 # Build output (auto-generated)
├── config/                # Policy configuration files
├── hooks/                 # eBPF hook implementations
│   └── lsm/               # LSM hooks
├── include/               # Header files
├── install/               # Kubernetes deployment manifests
│   └── kubernetes/bpfima/ # The official Helm Chart
├── operator/              # The Go-based Kubernetes Custom Controller
│   └── api/               # Go structs defining the Policy CRD schema
│   └── cmd/               # Entrypoint for the controller manager
│   └── config/crd/basis   # CRD schema
│   └── internal/          # Core reconciliation loop and eBPF map translation
├── src/                   # Kernel module source (modular)
├── scripts/               # Test, automation and initialisation scripts
│   └── init/              # Node bootstrapping and on-the-fly module compilation
├── test/                  # Validation tests
│   └── functional/        # Bash scripts validating the framework module compilation
│   └── performance/       # C binaries and scripts for latency profiling
├── tools/                 # Userspace management tool (bpfima-tool)
├── utils/                 # Utility headers
├── Makefile               # Build system
└── Dockerfile             # Multi-stage build manifest for the container image

Components

eBPF Hooks

  • lsm_container_events.c - Container lifecycle tracking
  • lsm_bprm_check_security.c - Process execution monitoring (policy-enabled)
  • lsm_file_open.c / lsm_file_post_open.c - File access monitoring (policy-enabled)
  • lsm_mmap_file.c - Memory-mapped file monitoring
  • lsm_socket_connect.c - Network connection monitoring

Kernel Module

The module provides custom BPF kfuncs and manages:

  • Container tracking with per-container measurement lists
  • Merkle tree with SHA-256 hashing
  • TPM PCR extensions (configurable index, default: 23)
  • Policy management and enforcement
  • SecurityFS interface at /sys/kernel/security/bpfima/

Management Tool (bpfima-tool)

Unified userspace tool that handles:

  • Loading and attaching eBPF programs (LSM, kprobe, tracepoint, fentry/fexit)
  • Policy initialization and management
  • System status monitoring
  • Daemon mode for background operation

Build

Requirements:

  • Linux kernel 5.8+ with BPF LSM enabled
  • clang, llvm, libbpf-devel, elfutils-libelf-devel, zlib-devel
  • kernel-devel, kernel-debuginfo (for BTF)
# Install dependencies (Fedora)
sudo dnf install kernel-devel libbpf-devel elfutils-libelf-devel zlib-devel clang llvm libyaml-devel
sudo dnf debuginfo-install kernel

# Build
make all

Output: build/bpfima.ko, build/bpfima-tool, build/*.o

Python Dependencies

For running performance tests and generating graphs:

sudo pip3 install matplotlib pandas seaborn

Usage

Testing

# Script helper
./scripts/test.sh --help

# Verbose mode
sudo ./scripts/test.sh -v

# Test specific hook
sudo ./scripts/test.sh lsm_bprm_check_security -v

Run the bounded-input tests with AddressSanitizer and UndefinedBehaviorSanitizer:

make test-security CC=clang

For the kernel module integration suite, build the test fixtures and run on an isolated host with BPF LSM and module BTF:

make modules kernel-tests
./scripts/test_kernel.sh --check --load-module
sudo ./scripts/test_kernel.sh --load-module

# Also exercise concurrent creation, measurements, and deduplication
sudo ./scripts/test_kernel.sh --load-module --stress

The suite checks kfunc contracts, measurements and hashes, namespace policy, SecurityFS, TPM reads/extensions, all five hooks' denial propagation, retained BPF pins and their cleanup, and kernel diagnostics. It unloads the module only if it loaded it. Tests can extend TPM PCRs; use a disposable test system. See Kernel integration tests for requirements, coverage, cleanup behavior, and report locations.

Kfunc interface

Every kfunc memory argument now has an adjacent size argument checked by the BPF verifier. String inputs must be NUL-terminated within the supplied extent. The measurement API accepts a pointer-free struct bpfima_measurement_request and sizeof(request). Its event name is required, an empty namespace selects default, payloads are limited to 255 bytes, and dependency strings require BPFIMA_MEASUREMENT_HAS_DEPENDENCIES. Invalid inputs return -EINVAL; filter functions return false for invalid inputs.

The shared request and policy layouts are declared in include/bpfima_kfunc_types.h. Rebuild the module, BPF programs, and userspace tool together after this API change. Reload the hooks and recreate their pinned maps: the policy value is now 36 bytes and the scratch value has grown to hold the bounded measurement request.

Manual

# 1. Load kernel module
sudo insmod build/bpfima.ko

# Optional: Configure TPM PCR index (default: 23)
# sudo insmod build/bpfima.ko tpm_pcr_index=10

# 2. Load eBPF program (daemon mode)
sudo ./build/bpfima-tool load build/lsm_bprm_check_security.o -d

# 3. Initialize policy maps (REQUIRED!)
sudo ./build/bpfima-tool policy-init

# 4. Check status
sudo ./build/bpfima-tool status

# 5. View measurements
sudo cat /sys/kernel/security/bpfima/status

# Cleanup
sudo ./build/bpfima-tool unload
sudo rmmod bpfima

Note 1: The unified bpfima-tool replaces the old separate loader and policy_init utilities.

Note 2: To install the framework on a Kubernetes cluster in an automated way please refer to docs/KUBERNETES.md.

Module Parameters

The bpfima kernel module supports the following runtime parameters:

TPM PCR Index

Configure which TPM PCR (Platform Configuration Register) to use for measurements:

# Load with custom PCR index
sudo insmod build/bpfima.ko tpm_pcr_index=10

# View current PCR index
cat /sys/module/bpfima/parameters/tpm_pcr_index

# Change at runtime (if module was loaded with writable permissions)
echo 15 | sudo tee /sys/module/bpfima/parameters/tpm_pcr_index

Default: PCR 23 (commonly used for custom measurements) Valid range: 0-23 (most TPMs) Note: PCR 0-15 are typically reserved for BIOS/bootloader. PCR 16-23 are available for OS and application use.

SecurityFS Interface

/sys/kernel/security/bpfima/
├── merkle_root              # Current Merkle tree root hash
├── measurements             # Global measurement list
├── status                   # Module status and configuration
├── container_list           # Tracked containers
└── containers/
    └── <container_id>/
        └── measurements     # Per-container measurements

Read example:

cat /sys/kernel/security/bpfima/merkle_root
cat /sys/kernel/security/bpfima/status
cat /sys/kernel/security/bpfima/containers/*/measurements

Policy Configuration

BPF IMA uses a policy system to control what gets measured and how:

Architecture

  • BPF Maps: Store policy configuration in pinned BPF maps at /sys/fs/bpf/
  • Kernel Enforcement: Policies enforced in eBPF hooks (secure, fast, kernel-level)
  • Userspace Management: bpfima-tool manages policies (init defaults or load from YAML)
  • YAML Configuration: Policies can be defined in config/*.yaml files

Default Policy

What Gets Measured:

  • Executable binaries
  • Scripts and interpreted code
  • Container workloads (Docker, Podman)
  • User processes (user.slice)
  • System services (system.slice)
  • Files in /dev/, /tmp/
  • Shared libraries (.so)
  • Everything except the minimal filters below

What Gets Filtered (minimal - only truly noisy system internals):

  • Root cgroup / (exact match only)
  • init.scope processes

Optional Filters (disabled by default, can be enabled via policy):

  • Files in /proc/ (enable with POLICY_FILTER_PROC_SYS)
  • Files in /sys/ (enable with POLICY_FILTER_PROC_SYS)
  • System cgroups (enable with POLICY_FILTER_SYSTEM_CGROUPS)
  • /dev/ files (enable with POLICY_FILTER_DEV)
  • Small files (enable with POLICY_FILTER_SMALL_FILES)
  • Libraries (enable with POLICY_FILTER_LIBRARIES)
  • /tmp/ files (enable with POLICY_FILTER_TMP_FILES)

Actions Enabled:

  • TPM PCR 23 extension
  • SecurityFS logging
  • Kernel log output
  • Per-container tracking
  • Dependency chain building

Policy Configuration Options

The policy system supports:

  1. Filter Flags - Control what to skip/ignore:

    POLICY_FILTER_SYSTEM_CGROUPS   // Skip /, init.scope (already minimal by default)
    POLICY_FILTER_PROC_SYS         // Skip /proc/, /sys/ (disabled by default)
    POLICY_FILTER_DEV              // Skip /dev/ (disabled by default)
    POLICY_FILTER_READONLY_FILES   // Skip readonly opens (disabled by default)
    POLICY_FILTER_SMALL_FILES      // Skip files below min size (disabled by default)
    POLICY_FILTER_NON_EXECUTABLE   // Skip non-executable files (disabled by default)
    POLICY_FILTER_LIBRARIES        // Skip .so files (disabled by default)
    POLICY_FILTER_TMP_FILES        // Skip /tmp/ files (disabled by default)

    Default: ALL filters disabled (0x0) - tracks everything except / and init.scope

  2. Action Flags - Control what actions to take:

    POLICY_ACTION_EXTEND_TPM       // Extend measurements to TPM
    POLICY_ACTION_LOG_SECURITYFS   // Log to securityfs
    POLICY_ACTION_LOG_KERNEL       // Log to kernel (printk)
    POLICY_ACTION_ALERT_SUSPICIOUS // Alert on suspicious activity
    POLICY_ACTION_BLOCK            // Block operations (future)
    POLICY_ACTION_TRACK_CONTAINER  // Track per-container
    POLICY_ACTION_BUILD_DEPS       // Build dependency chains
  3. Pattern Matching - Ignore specific cgroups or paths:

    • Cgroup patterns: Exact match on cgroup names
    • Path patterns: Prefix match on file paths
  4. Per-Hook Configuration:

    • Enable/disable individual hooks
    • Track containers per-hook
    • Enable/disable hash calculation
  5. Runtime Settings:

    • Log level (0=none, 1=errors, 2=info, 3=debug)
    • Minimum file size threshold
    • Maximum path depth

Customizing Policy

There are three ways to customize the policy:

1. Use YAML Configuration Files (Recommended)

Edit config/policy.yaml or config/policy-minimal.yaml:

policy:
  enabled: true
  log_level: 2
  measure_enabled: true
  appraise_enabled: false
  enforce_enabled: false
  container_tracking: true

filters:
  cgroup_patterns:
    - "/system.slice/"
    - "/docker/"
  path_patterns:
    - "/usr/bin/"
    - "/usr/sbin/"

hooks:
  - name: "lsm_bprm_check_security"
    enabled: true
    measure: true

Load the policy:

sudo ./build/bpfima-tool policy-update config/policy.yaml

2. Use SecurityFS Interface (Runtime)

Update policy through the securityfs interface:

# View current policy
cat /sys/kernel/security/bpfima/policy

# Update individual settings
echo "log_level=3" | sudo tee /sys/kernel/security/bpfima/policy
echo "filter_flags=0x7" | sudo tee /sys/kernel/security/bpfima/policy
echo "action_flags=0x1F" | sudo tee /sys/kernel/security/bpfima/policy
echo "min_file_size=4096" | sudo tee /sys/kernel/security/bpfima/policy

3. Use bpftool (Advanced)

Directly update BPF maps at runtime (advanced users):

# View current policy
sudo bpftool map dump pinned /sys/fs/bpf/bpfima_policy_map

# Update with bpftool (requires knowledge of struct layout)
sudo bpftool map update pinned /sys/fs/bpf/bpfima_policy_map \
    key 0 0 0 0 value 1 6 0 0 ...

Verifying Policy

Check current policy status:

# View policy configuration
sudo bpftool map dump pinned /sys/fs/bpf/bpfima_policy_map

# Check which hooks are enabled
sudo bpftool map dump pinned /sys/fs/bpf/bpfima_hook_config_map

# View measurements (verify things are being recorded)
sudo cat /sys/kernel/security/bpfima/status

# Check kernel logs for policy messages
sudo dmesg | grep -i bpfima | grep -i policy

Architecture

The system uses 6 communication channels between eBPF and kernel:

  1. Kfunc: bpf_container_create_or_get() - Container registration
  2. Kfunc: bpf_container_add_measurement() - Add measurement entry
  3. Kfunc: bpf_get_merkle_root() - Read current root hash
  4. BPF Map: Statistics counters
  5. BPF Map: Active container LRU cache
  6. Ring Buffer: Asynchronous event notifications

Merkle tree structure:

        Root Hash (PCR 23)
        /      |      \
   Leaf1    Leaf2    Leaf3
     /         |         \
[Container1][Container2][Container3]

Each leaf hash is computed from a container's measurement list. Root hash updates extend TPM PCR 23.

Measurement Flow

When an event is detected by an eBPF hook:

  1. Get namespace - Extract container ID from task's cgroup namespace
  2. Measure - Compute hash of the event data (file path, process, etc.)
  3. Record in list - Add measurement entry to container's measurement list
  4. Extend leaf - Recompute container's leaf hash from updated measurement list
  5. Add to history - Store measurement in global history list
  6. Extend root - Recompute Merkle root hash from all leaf hashes
  7. Extend PCR - Extend TPM PCR 23 with new root hash

This ensures each measurement is both container-specific and contributes to the global integrity state backed by hardware.

Troubleshooting

Missing BTF: Install kernel-debuginfo and create vmlinux symlink

sudo dnf debuginfo-install kernel
sudo ln -sf $(find /usr/lib/debug -name vmlinux -type f | head -1) /lib/modules/$(uname -r)/build/vmlinux

Module load fails: Check dmesg for errors

sudo dmesg | tail -20

No trace output: Verify program attachment

sudo bpftool prog list
sudo cat /sys/kernel/debug/tracing/trace

License

This project is open-source software distributed under the terms of the GNU General Public License version 2 (GPLv2).

About

No description, website, or topics provided.

Resources

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages