A lightweight example, I wrote to experiment with Seccomp and learn how to sandbox untrusted, dynamically loaded plug-ins using Linux Seccomp (Secure Computing Mode). This provides a template for quickly testing different scenarios and verifying various filter rule sets.
Disclaimer: Just in case it isn't obvious. This repository is for testing and tinkering only. It's an experimental project for learning and playing with Seccomp. It is NOT intended to be completely secure, reliable, or production-ready.
- Why Use Seccomp?
- Goals of This Project
- Key Components 3.1 Seccomp Filter 3.2 Plug-in Interface
- How to Build & Run 4.1 Requirements 4.2 Build Steps 4.3 Running the Demo
Seccomp is a Linux kernel feature that lets you limit which system calls a program can make. In its strictest form, it only allows four syscalls: read, write, exit, and sigreturn.
With seccomp-BPF, you can define much more granular rules—like allowing openat() only for read-only access. Writing raw BPF is a pain, so this project uses libseccomp, a C library that simplifies policy creation.
Recommended Reading:
- Intro to seccomp-BPF
- libseccomp Wiki
- Docker Security and Seccomp - HackTricks
- Seccomp: Unsafe at Any Speed - habets.se
- Why and How to Implement Seccomp - Latio Pulse
- Disassemble Seccomp BPF Rules with seccomp-tools - Medium
- Provide a minimal example using libseccomp to set up syscall filtering.
- Include a self-testing plug-in that deliberately breaks the rules to test if the filter works as intended.
- Provides two modes:
- Debug: blocked calls return
EPERM - Production: blocked calls instantly kill the process with
SIGSYS
- Debug: blocked calls return
File: syscall_filter.cpp
-
Uses a whitelist approach: only essential syscalls are allowed.
-
Blocks risky calls like
execve,memfd_create, andshmget. -
Behavior depends on build mode:
- Production:
SECCOMP_RET_KILL_PROCESSkills the process on violation. - Debug:
SECCOMP_RET_ERRNO(EPERM)returns a standard error, so you can debug.
- Production:
Each plug-in must expose the following C-compatible functions:
extern "C" const char* plugin_version();
extern "C" int plugin_init(const char* json_cfg);
extern "C" int plugin_compute(const char* data);
extern "C" const char* plugin_get_json();This small API allows the host app to load, configure, and run plug-ins without needing to know their internal logic.
- Linux kernel 3.5 or newer with seccomp-BPF support
libseccompdevelopment headers (libseccomp-devon Debian/Ubuntu)- CMake 3.16 or newer
- A C++17-capable compiler
| Build Type | Command |
|---|---|
| Release | mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Release .. && make |
| Debug | mkdir build-debug && cd build-debug && cmake -DCMAKE_BUILD_TYPE=Debug .. && make |
# Run a safe plug-in
./seccomp_poc ./libsafe.so "1,2,3,4,5"
# Run a violating plug-in (crashes in Release mode)
./seccomp_poc ./libviolate.so "1,2,3,4,5"You can tweak syscall_filter.cpp to adjust which syscalls are allowed, or build your own plug-ins to explore how the sandbox reacts.