Enforcement
Tyr enforces at the kernel via eBPF LSM (Linux Security Modules) hooks and tracepoints. This page documents what’s hooked, the verdict model, and bypass considerations.
Kernel version requirements
- Minimum: kernel 5.15 with
CONFIG_BPF_LSM=ybuilt in. - Recommended: kernel 6.1+ for the full feature set.
- BTF / CO-RE required (
/sys/kernel/btf/vmlinuxmust exist).
Most modern distros ship with LSM BPF enabled:
- Ubuntu 22.04+, Debian 12+, Fedora 36+, Amazon Linux 2023 — yes out of the box.
- RHEL 9 — yes (kernel 5.14 backports LSM BPF).
- Older kernels fall back to tracepoint-only mode where available (observe but limited enforce).
Verify on your host:
cat /sys/kernel/security/lsm # should include "bpf"ls /sys/kernel/btf/vmlinux # should existHook points
| Kernel hook | Type | What it covers |
|---|---|---|
lsm/file_open | LSM | open(), openat(), indirectly read() |
lsm/bprm_check_security | LSM | execve() before the binary is loaded |
lsm/socket_connect | LSM | outbound connect() for TCP/UDP |
tp/syscalls/sys_enter_openat | tracepoint | supplemental path tracking |
tp/sched/sched_process_exec | tracepoint | successful exec for logging |
uprobe on SSL_write / rustls send | uprobe | TLS SNI extraction (when --tls-capture) |
The two-layer verdict pipeline
flowchart TD Start(["syscall entry"]) --> L1 subgraph L1["Layer 1: BPF map lookup (kernel, nanoseconds)"] Trie["file_deny_prefixes (trie)"] Hash["exec_deny_exact (hash)"] Lpm["net_deny_cidrs (lpm_trie)"] end L1 --> Decision{match?} Decision -- "yes" --> Deny["return EPERM<br/>emit event (DENY)"] Decision -- "no" --> Allow["emit event (ALLOW or ALERT)"] Allow --> L2 subgraph L2["Layer 2: userspace (when needed)"] RB["tyrd reads ring buffer"] Cedar["evaluate Cedar rules<br/>(principal / context)"] Audit["if deny \u2192 event.verdict = DENY<br/>(audit after-the-fact)"] RB --> Cedar --> Audit endGood policies keep the deny rules in Layer 1 (kernel) so they actually prevent the syscall. Use Cedar for conditional allow / alert rules.
Processes exempt from enforcement
Some processes must never be blocked — tyrd itself, systemd-journald, the kernel worker queue. These are identified by:
- Cgroup membership of
tyr.service. - PID 1.
- Kernel threads (PPID == 2).
Fine-grained exemptions via policy (exempt_pids: or exempt_binaries:) can be added but should be minimal.
Enforce vs audit-only
The tyrd --enforce flag is the master switch:
| Flag | File deny/write | Exec deny | Net deny |
|---|---|---|---|
--enforce (on) | syscall → EPERM | syscall → EACCES | connect() → ECONNREFUSED |
| (off, default) | emits event only | emits event only | emits event only |
Start in audit-only mode for your first week of deployment. Confirm your policies don’t false-positive on legitimate work, then flip --enforce on.
Bypass considerations
What Tyr catches that LD_PRELOAD / ptrace miss:
- Statically-linked binaries.
setuidexecutions.- Processes that unset
LD_PRELOADin their environment. - Kernel-path code paths that don’t go through libc.
What Tyr doesn’t catch today:
- Privileged processes that can unload LSM BPF programs (root,
CAP_BPF) — if your attacker is already root-on-host withCAP_BPF, you’ve lost. Mitigation: runtyrdwith its programs pinned and run kmem-lockdown. - Direct kernel module insertion — no userspace security tool can.
- Workloads that never enter a governed syscall (e.g. a pure compute loop).
Next
See the TLS capture guide for how outbound HTTPS traffic is tagged with SNI, and the ADR on kernel enforcement for deeper design rationale.