seccompiler

Compiles Rust and JSON seccomp filter definitions into loadable BPF programs for Linux syscall jailing.

Library
Cargo
v0.5.0
127stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
57/100Fair
Development Activity56
Maintenance24
Community72
Maturity56
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
78/100Good
Architecture85
Code Quality82
Innovation78
Learning Curve68

Seccompiler is a rust-vmm library that provides easy-to-use Linux seccomp-bpf jailing. It lets applications define syscall filtering policies — either as Rust structs or as JSON configuration files — and compiles them into loadable BPF (Berkeley Packet Filter) programs that the kernel evaluates before every system call, so untrusted or high-risk code paths can be restricted to a minimal allow-list of syscalls.

Originally extracted from Firecracker, it is now a shared building block across the rust-vmm ecosystem (used by Firecracker, Cloud Hypervisor, and other VMMs) for reducing a process’s kernel attack surface without hand-writing raw BPF bytecode. It supports little-endian x86_64, aarch64, and riscv64.

What You Get

  • A typed Rust API (SeccompFilter, SeccompRule, SeccompCondition, SeccompAction) for building syscall allow/deny policies without writing raw BPF
  • An optional JSON frontend (behind the json feature) that compiles declarative filter files into the same BPF backend, documented in docs/json_format.md
  • Multi-architecture BPF codegen for little-endian x86_64, aarch64, and riscv64 targets
  • Runtime installation helpers (apply_filter, apply_filter_all_threads with TSYNC) that set PR_SET_NO_NEW_PRIVS and invoke the seccomp syscall directly
  • Support for both runtime and build-time filter compilation, so compiled BPF can be embedded via include_bytes! to shave filter-compile time off app startup

Common Use Cases

  • Sandboxing a VMM’s vCPU or I/O threads (as in Firecracker and Cloud Hypervisor) to the minimal syscall set they need after initialization
  • Jailing worker processes or threads that parse untrusted input, limiting the syscalls available if the parser is compromised
  • Compiling a shared JSON-defined syscall policy across multiple binaries or thread categories using a single BpfMap
  • Precompiling seccomp filters at build time to remove filter-compilation latency from hot-path process startup

Under The Hood

Architecture — The crate is split into a backend module (always compiled) and an optional frontend/syscall_table pair gated behind the json feature. The backend, in src/backend/{filter,rule,condition,bpf}.rs, defines the intermediate representation: SeccompCondition (single argument comparison), SeccompRule (and-bound conditions), and SeccompFilter (a BTreeMap<i64, Vec<SeccompRule>> keyed by syscall number, plus match/mismatch SeccompActions). filter.rs’s TryFrom<SeccompFilter> for BpfProgram walks this map and emits a Vec<sock_filter> — literal Linux BPF instructions validated against libc::SECCOMP_RET_* codes and an architecture-specific AUDIT_ARCH_* constant from bpf.rs. The JSON path (frontend/json.rs, 844 lines) deserializes a documented schema (docs/json_format.md) into the same SeccompFilter IR via serde, so both entry points converge on one BPF backend — a deliberate frontend/backend split for extensibility. lib.rs exposes apply_filter/apply_filter_all_threads, which call prctl(PR_SET_NO_NEW_PRIVS) then the raw seccomp syscall via libc::syscall, using unsafe blocks with documented safety justifications. Tech Stack — Minimal dependency footprint: libc (^0.2.153) for syscall/constant bindings is the only mandatory dependency; serde and serde_json are pulled in only under the optional json Cargo feature. Edition 2021, no async runtime, no allocator tricks — this is deliberately a thin, low-level crate with almost no third-party surface area, appropriate for a security-sensitive library that VMMs like Firecracker link into privileged processes. Architecture-specific syscall number tables are hand-maintained per target (syscall_table/{x86_64,aarch64,riscv64}.rs, ~300-390 lines each). Code Quality#![deny(missing_docs)] at the crate root enforces doc coverage on every public item. Test coverage is substantial relative to source size: 1,313 lines of tests (tests/integration_tests.rs at 791 lines plus tests/json.rs and tests/multi_thread.rs) against 3,418 lines of source, plus embedded unit tests in condition.rs, rule.rs, filter.rs, bpf.rs, and json.rs covering edge cases like empty rules, identical match/mismatch actions, and oversized filters. Errors are modeled as explicit enums (backend::Error, top-level Error) with Display/std::error::Error impls rather than panics or opaque strings, and every unsafe block carries an inline // SAFETY: comment. API Design — The public surface (SeccompFilter::new, SeccompRule::new, SeccompCondition::new, TryInto<BpfProgram>, compile_from_json) mirrors the seccomp mental model closely (filter → rules → conditions), which keeps the Rust and JSON representations semantically interchangeable and documented side by side. The crate-level doc comment on lib.rs includes two complete, compiling examples (Rust-native and JSON) with a companion syscall diagram in docs/, giving a working end-to-end reference before a user needs to consult per-type docs — though the security-domain vocabulary (BPF, TSYNC, audit arch) still demands seccomp familiarity to use correctly.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search