Stage 3 · Build
Namespaces, cgroups & Security
seccomp-BPF Profiles
Default Docker profiles, syscall allowlists, audit mode, and libseccomp filters.
seccomp-BPF Overview
seccomp-BPF extends seccomp with eBPF programs that filter syscalls per-process. Each program receives the syscall number and arguments, then returns ALLOW, KILL, ERRNO, or LOG. Docker, systemd, and Chrome all use seccomp-BPF for sandboxing.
# Check if seccomp is enabled
grep CONFIG_SECCOMP /boot/config-$(uname -r)
# CONFIG_SECCOMP=y
# CONFIG_SECCOMP_FILTER=y
# Check process seccomp status
grep Seccomp /proc/self/status
# Seccomp: 0 (disabled)
# Seccomp_filters: 0
# Docker container
docker run --rm alpine grep Seccomp /proc/1/status
# Seccomp: 2 (filter mode)
# Seccomp_filters: 1seccomp mode 0 is disabled, 1 is strict, and 2 is filter mode. Docker uses filter mode with a default profile.
Docker Default Profile
# The default Docker profile blocks ~44 syscalls
# Key blocked syscalls:
# - reboot, kexec_load, kexec_file_load
# - mount, umount2, umount
# - ptrace (process tracing)
# - keyctl, add_key, request_key
# - bpf, perf_event_open (unless privileged)
# - userfaultfd, clone3
# - io_uring_setup, io_uring_enter, io_uring_register
# Run with default profile
docker run --rm alpine echo test
# Run without seccomp (DANGEROUS)
docker run --rm --security-opt seccomp=unconfined alpine sh
# Use a custom profile
docker run --rm --security-opt seccomp=/path/to/profile.json alpine sh
# Inspect container security options
docker inspect --format '{{.HostConfig.SecurityOpt}}' <container>The default Docker profile is conservative. Most applications run without issues. Some workloads (e.g., networking, performance monitoring) need specific syscalls unblocked.
Custom Profiles
# Start with default profile as base
wget https://raw.githubusercontent.com/moby/moby/master/profiles/seccomp/default.json
# Add a custom syscall
cat > custom-profile.json << 'EOF'
{
"defaultAction": "SCMP_ACT_ERRNO",
"architectures": ["SCMP_ARCH_X86_64"],
"syscalls": [
{
"names": ["read", "write", "open", "close", "stat", "fstat",
"mmap", "mprotect", "munmap", "brk", "exit_group",
"futex", "epoll_wait", "accept", "socket", "connect"],
"action": "SCMP_ACT_ALLOW"
},
{
"names": ["bpf", "perf_event_open"],
"action": "SCMP_ACT_ALLOW",
"args": [
{ "index": 0, "value": 0, "op": "SCMP_CMP_EQ" }
]
}
]
}
EOF
# Test the profile
docker run --rm --security-opt seccomp=custom-profile.json alpine shCustom profiles start with defaultAction SCMP_ACT_ERRNO (deny all) and explicitly allow needed syscalls. This is the most secure approach.
Audit Mode
# strace shows seccomp denials
strace -e trace=open,openat cat /etc/hostname
# openat(AT_FDCWD, "/etc/hostname", O_RDONLY|O_CLOEXEC) = 3
# (If blocked: EPERM)
# Check kernel log for seccomp denials
dmesg | grep -i seccomp
# audit: type=1326 audit(1234567890.123:456): auid=4294967295
# uid=0 pid=1234 comm="cat" exe="/usr/bin/cat"
# sig=0 seccomp=1 a0=257 a1=ffffff9c a2=7ffc1234
# Use auditd to capture seccomp events
sudo auditctl -a always,exit -F arch=b64 -S openat -k seccomp_testWhen a syscall is blocked by seccomp, the kernel logs an audit event. Use dmesg or auditd to identify which syscalls your application needs.
libseccomp
# libseccomp provides a C library for building seccomp filters
# Used by Docker, systemd, Chrome, and many others
# Check libseccomp version
dpkg -l libseccomp2
# strace with seccomp syscall names
strace -e trace=seccomp -f docker run --rm alpine echo test
# Build a custom filter with libseccomp
# (Requires C programming with libseccomp2-dev)libseccomp simplifies building seccomp filters. It provides syscall name mappings and a high-level API for creating filter rules.
Best Practices
- Start with deny-all, then allow specific syscalls
- Use Docker's default profile as a starting point
- Test profiles in audit mode before enforcing
- Monitor strace output to identify needed syscalls
- Never use --security-opt seccomp=unconfined in production
- Version control your seccomp profiles
- Combine with capabilities and namespaces for defense in depth
Run your application with strace to see all syscalls it uses. Start with a restrictive profile and add syscalls as needed based on strace output.
When seccomp blocks a syscall, the application gets an error (usually EPERM). This can cause silent failures. Always test seccomp profiles thoroughly before deploying to production.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.