AegisBPF is an eBPF-based runtime security agent that monitors and blocks unauthorized file access using Linux Security Modules (LSM). It provides kernel-level enforcement with minimal overhead.
┌───────────────────────────────────────────────────────────────────────────────┐
│ AegisBPF │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ File/Net │ │ Allow │ │ Policy │ │ Metrics │ │
│ │ deny rules │ │ allowlist │ │ + signatures│ │ + health │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ └─────────────────┴─────────────────┴──────────────────┘ │
│ │ │
│ ┌───────┴────────┐ │
│ │ Pinned BPF Maps│ │
│ │ + Ring Buffer │ │
│ └───────┬────────┘ │
│ │ │
├──────────────────────────────────────┼────────────────────────────────────────┤
│ KERNEL │ │
│ ┌────────────┴──────────────┐ │
│ │ LSM hooks (enforce/audit) │ │
│ │ file_open/inode_permission│ │
│ │ socket_connect/socket_bind│ │
│ └────────────┬──────────────┘ │
│ ┌────────────┴─────────────┐ │
│ │ Tracepoint fallback │ │
│ │ openat/exec/fork/exit │ │
│ └──────────────────────────┘ │
└───────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────┐
│ User Space │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ aegisbpf daemon │ │
│ │ │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ CLI │ │ Policy │ │ Event │ │ Metrics │ │ Logging │ │ │
│ │ │ Dispatch │ │ + Sign │ │ Handler │ │ + Health │ │ (JSON) │ │ │
│ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │
│ │ │ │ │ │ │ │ │
│ │ └─────────────┴─────────────┴─────────────┴─────────────┘ │ │
│ │ │ │ │
│ │ ┌───────┴───────┐ │ │
│ │ │ libbpf │ │ │
│ │ └───────┬───────┘ │ │
│ └───────────────────────────────────┼─────────────────────────────────────┘ │
│ │ │
│ bpf() syscall │
│ │ │
├──────────────────────────────────────┼───────────────────────────────────────┤
│ Kernel Space │
│ │ │
│ ┌───────────────────────────────────┴───────────────────────────────────┐ │
│ │ BPF Subsystem │ │
│ │ │ │
│ │ ┌───────────────────────────────┐ ┌───────────────────────────────┐ │ │
│ │ │ LSM Hooks │ │ Tracepoint Fallback │ │ │
│ │ │ file_open / inode_permission │ │ openat / exec / fork / exit │ │ │
│ │ │ socket_connect / socket_bind │ │ (audit path when no BPF LSM) │ │ │
│ │ └───────────────┬───────────────┘ └──────────────┬────────────────┘ │ │
│ │ └───────────────┬─────────────────┘ │ │
│ │ ▼ │ │
│ │ ┌──────────────────────┐ │ │
│ │ │ BPF Maps │ │ │
│ │ │ deny_* / allow_* │ │ │
│ │ │ net_* / survival_* │ │ │
│ │ │ agent_meta / stats │ │ │
│ │ │ events ring buffer │ │ │
│ │ └──────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ file/network ops allowed, audited, or blocked │
└──────────────────────────────────────────────────────────────────────────────┘
cat /sys/kernel/security/lsm | grep bpf)/sys/fs/cgroupOptional environment check:
scripts/verify_env.sh --strict
sudo apt-get update
sudo apt-get install -y clang llvm bpftool libbpf-dev libsystemd-dev \
pkg-config cmake ninja-build python3-jsonschema
cmake -S . -B build -G Ninja
cmake --build build
# Audit mode (observe without blocking)
sudo ./build/aegisbpf run --audit
# Enforce mode (block matching file opens)
sudo ./build/aegisbpf run --enforce
# Enforce mode with explicit signal policy (default is SIGTERM)
sudo ./build/aegisbpf run --enforce --enforce-signal=term
# SIGKILL mode escalates: TERM first, KILL only after repeated denies
sudo ./build/aegisbpf run --enforce --enforce-signal=kill
# Tune SIGKILL escalation policy (used only with --enforce-signal=kill)
sudo ./build/aegisbpf run --enforce --enforce-signal=kill \
--kill-escalation-threshold=8 \
--kill-escalation-window-seconds=60
# With JSON logging
sudo ./build/aegisbpf run --log-format=json
# Select LSM hook (default: file_open)
sudo ./build/aegisbpf run --enforce --lsm-hook=both
# Increase ring buffer and sample events to reduce drops under heavy load
sudo ./build/aegisbpf run --audit --ringbuf-bytes=67108864 --event-sample-rate=10
┌─────────────────────────────────────────────────────────────────────────────┐
│ File Access Blocking Flow │
└─────────────────────────────────────────────────────────────────────────────┘
User Process Kernel AegisBPF
│ │ │
│ open("/etc/shadow") │ │
│ ──────────────────────────►│ │
│ │ │
│ │ LSM: file_open / inode_permission
│ │ ──────────────────────────►│
│ │ │
│ │ allow_cgroup? ----------► allow
│ │ │
│ │ ▼
│ │ deny_inode?
│ │ │
│ │ ▼
│ │ survival_allowlist? ---> allow
│ │ │
│ │ ▼
│ │ audit mode -> emit event, allow
│ │ enforce -> optional signal + -EPERM
│ │ │
│ Success / EPERM │ │
│ ◄──────────────────────────│ │
│ │ │
# Choose LSM hook (default: file_open)
sudo aegisbpf run --enforce --lsm-hook=file
sudo aegisbpf run --enforce --lsm-hook=inode
sudo aegisbpf run --enforce --lsm-hook=both
# Choose enforce signal action (default: term)
sudo aegisbpf run --enforce --enforce-signal=term
sudo aegisbpf run --enforce --enforce-signal=none
# 'kill' escalates to SIGKILL only after repeated denies in a short window
sudo aegisbpf run --enforce --enforce-signal=kill
# Tune escalation policy for kill mode
sudo aegisbpf run --enforce --enforce-signal=kill \
--kill-escalation-threshold=8 \
--kill-escalation-window-seconds=60
# Increase ring buffer size (bytes) to reduce ringbuf drops
sudo aegisbpf run --audit --ringbuf-bytes=67108864
# Sample block events (1 = all events, 10 = 1 out of 10)
sudo aegisbpf run --audit --event-sample-rate=10
Results vary by host and workload. The following example was measured on February 2, 2026:
# perf_compare.sh (1,000,000 ops)
baseline_us_per_op=1.94
with_agent_us_per_op=1.98
delta_pct=2.06
# perf_compare.sh with both hooks (LSM_HOOK=both)
baseline_us_per_op=1.93
with_agent_us_per_op=1.97
delta_pct=2.07
# Soak (200,000 denied opens, audit mode)
ringbuf_drops_delta=0
# Add file to deny list
sudo aegisbpf block add /usr/bin/malware
# List all blocked entries
sudo aegisbpf block list
# Remove from deny list
sudo aegisbpf block del /usr/bin/malware
# Clear all rules and statistics
sudo aegisbpf block clear
# Allow cgroup (processes bypass deny rules)
sudo aegisbpf allow add /sys/fs/cgroup/system.slice
# List allowed cgroups
sudo aegisbpf allow list
# Remove from allowlist
sudo aegisbpf allow del /sys/fs/cgroup/system.slice
# /etc/aegisbpf/policy.conf
version=1
[deny_path]
/usr/bin/dangerous
/opt/malware/binary
[deny_inode]
259:12345
[allow_cgroup]
/sys/fs/cgroup/system.slice
cgid:123456
# Validate policy
sudo aegisbpf policy lint /etc/aegisbpf/policy.conf
# Apply with SHA256 verification
sudo aegisbpf policy apply /etc/aegisbpf/policy.conf --sha256 abc123...
# Apply signed bundle (recommended for production)
sudo aegisbpf policy apply /etc/aegisbpf/policy.signed --require-signature
# Export current rules
sudo aegisbpf policy export /tmp/current.conf
# Rollback to previous policy
sudo aegisbpf policy rollback
# View statistics
sudo aegisbpf stats
# View detailed high-cardinality debug breakdowns
sudo aegisbpf stats --detailed
# Export Prometheus metrics
sudo aegisbpf metrics --out /var/lib/prometheus/aegisbpf.prom
# Export high-cardinality metrics for short-lived debugging
sudo aegisbpf metrics --detailed --out /tmp/aegisbpf.debug.prom
# Health check
sudo aegisbpf health
# Enable OTel-style policy spans in logs (for troubleshooting)
AEGIS_OTEL_SPANS=1 sudo aegisbpf policy apply /etc/aegisbpf/policy.conf
Events are emitted as newline-delimited JSON:
{
"type": "block",
"pid": 12345,
"ppid": 1000,
"start_time": 123456789,
"exec_id": "12345:123456789",
"trace_id": "12345:123456789",
"parent_start_time": 123400000,
"parent_exec_id": "1000:123400000",
"parent_trace_id": "1000:123400000",
"cgid": 5678,
"cgroup_path": "/sys/fs/cgroup/user.slice",
"comm": "bash",
"path": "/usr/bin/malware",
"ino": 123456,
"dev": 259,
"action": "TERM"
}
docker build -t aegisbpf .
docker run --privileged --pid=host \
-v /sys/fs/bpf:/sys/fs/bpf \
-v /sys/fs/cgroup:/sys/fs/cgroup:ro \
-v /sys/kernel/btf:/sys/kernel/btf:ro \
aegisbpf run --audit
helm install aegisbpf ./helm/aegisbpf \
--set agent.auditMode=false \
--set agent.logFormat=json
sudo cmake --install build
sudo systemctl daemon-reload
sudo systemctl enable --now aegisbpf
/etc/default/aegisbpf defaults to:
AEGIS_REQUIRE_SIGNATURE=1AEGIS_POLICY= (empty, service starts without applying a startup policy)For production, set AEGIS_POLICY to a signed policy bundle path (for example
/etc/aegisbpf/policy.signed) and keep signature enforcement enabled.
┌─────────────────────────────────────────────────────────────────────────────┐
│ Data Flow │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────┐
│ Policy bundle/rules │
│ /etc/aegisbpf/policy.signed │
└───────────────┬─────────────────┘
│
▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ CLI │ │ aegisbpf │ │ journald │
│ Commands │──────────►│ daemon │──────────►│ / stdout │
│ │ │ │ │ │
└───────────────┘ └───────┬───────┘ └───────────────┘
│
│ bpf() syscall
▼
┌────────────────────────────────┐
│ BPF Maps │
│ /sys/fs/bpf/aegis/ │
│ │
│ ┌──────────────────────────┐ │
│ │ deny_* / allow_cgroup │ │
│ │ deny_ipv4/deny_ipv6 │ │
│ │ deny_cidr_v4/v6 + port │ │
│ │ net_* stats + block_stats│ │
│ │ survival_allowlist/meta │ │
│ │ events (ring buf) │ │
│ └──────────────────────────┘ │
└───────────────┬────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ BPF hooks (kernel) │
│ - file_open/inode_permission │
│ - socket_connect/socket_bind │
│ - openat/exec/fork/exit tracepoints fallback │
└──────────────────────────────────────────────┘
AegisBPF exports Prometheus-compatible metrics:
| Metric | Type | Description |
|---|---|---|
aegisbpf_blocks_total |
counter | Total blocked file opens |
aegisbpf_ringbuf_drops_total |
counter | Events dropped due to buffer overflow |
aegisbpf_deny_inode_entries |
gauge | Number of inode deny rules |
aegisbpf_deny_path_entries |
gauge | Number of path deny rules |
aegisbpf_allow_cgroup_entries |
gauge | Number of allowed cgroups |
aegisbpf_net_blocks_total |
counter | Blocked network operations by type (connect/bind) |
aegisbpf_net_ringbuf_drops_total |
counter | Dropped network events |
aegisbpf_net_rules_total |
gauge | Active network deny rules by type (ip/cidr/port) |
High-cardinality debug metrics are available with aegisbpf metrics --detailed:
aegisbpf_blocks_by_cgroup_total, aegisbpf_blocks_by_inode_total,
aegisbpf_blocks_by_path_total, aegisbpf_net_blocks_by_ip_total,
aegisbpf_net_blocks_by_port_total.
┌─────────────────────────────────────────────────────────────────────────────┐
│ Security Layers │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ Layer 4: Code Signing │
│ Sigstore/Cosign + SBOM │
└─────────────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────────────┐
│ Layer 3: MAC Policies │
│ AppArmor / SELinux │
└─────────────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────────────┐
│ Layer 2: Seccomp │
│ Syscall allowlist (--seccomp) │
└─────────────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────────────┐
│ Layer 1: Capabilities │
│ CAP_SYS_ADMIN, CAP_BPF, CAP_PERFMON │
└─────────────────────────────────────────────────────────────────────┘
Enable all hardening layers:
sudo aegisbpf run --enforce --seccomp
See SECURITY.md for vulnerability reporting and hardening details.
| Document | Description |
|---|---|
| ARCHITECTURE.md | System design and internals |
| API_REFERENCE.md | API reference for types, functions, and BPF maps |
| DEVELOPER_GUIDE.md | Development setup, coding standards, and contribution guide |
| POLICY.md | Policy file format and semantics |
| NETWORK_LAYER_DESIGN.md | Network blocking architecture |
| Document | Description |
|---|---|
| PRODUCTION_READINESS.md | Production gates and evidence checklist |
| GO_LIVE_CHECKLIST.md | Final go/no-go checklist for release candidates |
| CANARY_RUNBOOK.md | Staging canary and soak validation workflow |
| RELEASE_DRILL.md | Pre-release packaging and upgrade drill |
| KEY_MANAGEMENT.md | Policy signing key rotation and revocation runbook |
| INCIDENT_RESPONSE.md | Incident handling procedures |
| runbooks/ | Alert/incident/maintenance operational runbooks |
| VENDORED_DEPENDENCIES.md | Vendored dependency inventory and review cadence |
| TROUBLESHOOTING.md | Common issues and solutions |
| SIEM_INTEGRATION.md | Splunk, ELK, QRadar integration |
| Document | Description |
|---|---|
| SUPPORT_POLICY.md | Supported versions, compatibility, and deprecation guarantees |
| COMPATIBILITY.md | Kernel and version compatibility matrix |
| PERF.md | Performance tuning and benchmarking |
| BRANCH_PROTECTION.md | Protected-branch baseline and required checks |
| QUALITY_GATES.md | CI gate policy and coverage ratchet expectations |
| repo_labels.json | Repository label source of truth for triage/release policy |
| CHANGELOG.md | Version history |
| CONTRIBUTING.md | Contributor workflow and local quality checks |
| GOVERNANCE.md | Project decision model and maintainer roles |
| SUPPORT.md | Support channels and version support scope |
| aegisbpf.1.md | Man page |
CONFIG_BPF=yCONFIG_BPF_SYSCALL=yCONFIG_BPF_JIT=yCONFIG_BPF_LSM=y (for enforce mode)CONFIG_DEBUG_INFO_BTF=yCAP_SYS_ADMIN, CAP_BPF, CAP_PERFMONIf bpf is missing from /sys/kernel/security/lsm:
# Edit GRUB configuration
sudo vim /etc/default/grub
GRUB_CMDLINE_LINUX="lsm=lockdown,capability,landlock,yama,bpf"
# Update and reboot
sudo update-grub
sudo reboot
BPF LSM overhead is minimal:
Run the benchmark:
ITERATIONS=200000 FILE=/etc/hosts scripts/perf_open_bench.sh
CONTRIBUTING.md for workflow and quality expectationsscripts/dev_check.sh plus static/security checks in CONTRIBUTING.mdMIT License See LICENSE for details.