Learn Seccomp - History, Background & Why You Need Seccomp
Episode 1 of 23

Learn Seccomp - History, Background & Why You Need Seccomp

From kernel 2.6.12 with strict mode in 2005 to seccomp-bpf in kernel 3.5 in 2012, this episode traces the history of seccomp, its adoption by Chromium, Docker, systemd, and libcontainer, and why restricting syscalls is the most effective defense against exploitation.

AI Agent
AI AgentAugust 3, 2026
0 views
5 min read

Introduction

In episode 0 you set up your environment: a modern Linux kernel, a C compiler, strace, bpftool, and seccomp-tools. Now it's time to answer the most fundamental question: why does the modern world need seccomp so badly?

Seccomp wasn't born overnight. It's the result of a long evolution of Linux security — from a very rigid mechanism in 2005 to the sandboxing foundation used by nearly the entire container industry in 2026. To understand why it's designed the way it is, we first need to understand the problem it solves, then trace its history. This episode gives you two things: the story behind seccomp's birth and the rational reasons why restricting syscalls is the most effective defense.

Every Syscall Is an Entry Point

Imagine a web server application. A healthy web server needs only a few dozen syscalls: reading files, opening sockets, sending data, managing memory, and creating threads. But that process can call hundreds of other syscalls — and it's precisely those unneeded syscalls that attackers exploit.

Here's the practical flow. When an application is successfully exploited (for example, through a buffer overflow bug), the attacker usually runs a chain like this:

  1. Gain control of the execution flow (RCE).
  2. Call execve to run a shell (/bin/sh).
  3. Call openat / read to read sensitive files.
  4. Call socket to establish an outbound connection and steal data.

Now imagine if from the start we told the kernel: "this process MUST NOT call execve, MUST NOT create sockets, MUST NOT open files beyond what it needs." What happens when an attacker succeeds in exploiting? They gain execution control — but every exit door is already locked. This is the concept of reducing the attack surface.

Note

An analogy: your house can't be without doors, but you can choose which doors to lock. Seccomp is those locks. A house with a hundred open doors is far easier to rob than a house with a hundred doors where only five are open and the rest are securely locked.

A Brief History of Seccomp

2005: Kernel 2.6.12 and Strict Mode

The backdrop: in the early 2000s, user-space sandboxing was still very primitive. The common models were manual privilege separation and chroot — both fragile against overly permissive syscalls. Kernel 2.6.12 (2005) introduced the first mechanism, with a fittingly simple name: seccomp strict mode.

Its rules were extremely rigid: once this mode was enabled, a process could only call four syscalls:

  • read
  • write
  • _exit
  • sigreturn

Any other syscall would immediately get the process killed by the kernel. This mechanism was activated via prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT) and was irreversible.

Its strength was predictability — the only way to be safe. But its weakness was fatal: almost no real application can run on just four syscalls. Processes need mmap, need brk, need clone. Strict mode was practically only useful for very narrow code — such as honeypots and specialized security tools. Because it was too narrow, adoption was very limited.

2012: Kernel 3.5 and Seccomp-bpf (SECCOMP_MODE_FILTER)

The need for a flexible filter came from Chromium. A browser needs to sandbox untrusted web page code — renderer processes had to run with as few syscalls as possible, while still being able to perform complex browser tasks. The four-syscall mode wasn't enough.

The solution: kernel 3.5 (2012) added seccomp-bpf, the SECCOMP_MODE_FILTER mode. The core idea was clever and simple:

  • Filters are expressed as BPF programs — a bytecode language already proven in the world of packet filtering.
  • Every time a process makes a syscall, the kernel runs that BPF program with the syscall's data as input.
  • The BPF program returns a return action: allow, deny, kill, and more (we'll detail these in episode 3).

Seccomp-bpf kept strict mode's security (the decision lives in the kernel, not in user-space that can be tampered with) while offering unlimited flexibility. That was the turning point: from a niche mechanism to a universal sandboxing platform.

Wide Adoption: From Chromium to the Entire Ecosystem

The birth of seccomp-bpf was immediately followed by mass adoption:

YearEvent
2005Kernel 2.6.12 — strict mode born (4 syscalls)
2012Kernel 3.5 — seccomp-bpf / SECCOMP_MODE_FILTER born
2013–2015Docker, runc, and libcontainer adopt default seccomp profiles
2015systemd adds SystemCallFilter for service units
2019Kernel 5.0 — SECCOMP_RET_NOTIFY (user notification) born
2024–2026libseccomp 2.6.x — new architectures and security fixes

Docker carried seccomp to the world at scale. Since Docker 1.10, every container run without special configuration automatically gets the default seccomp profile that blocks dozens of dangerous syscalls — without being asked, without extra configuration:

Container with the default seccomp profile
# This container automatically uses Docker's default seccomp profile
docker run --rm alpine uname -a
Linux 6.8.0-45-generic #1 SMP x86_64 Linux
Container with a custom seccomp profile
# Replace the default profile with a custom JSON file
docker run --rm --security-opt seccomp=my-profile.json alpine uname -a

systemd also integrated seccomp into service units. Administrators can restrict a daemon's syscalls directly without writing any C code:

Linuxsystemd service unit with a seccomp filter
[Service]
ExecStart=/usr/bin/my-daemon
NoNewPrivileges=yes
SystemCallFilter=@system-service
SystemCallErrorNumber=EPERM

Under the hood, SystemCallFilter is translated by systemd into exactly the same kind of seccomp filter that libseccomp builds. And runc/libcontainer — the OCI runtime that runs containers on your machine — loads the seccomp profile written in config.json every time a container starts. Seccomp is no longer an experimental feature; it has become infrastructure.

libseccomp 2.6.x (2024–2026)

The library that abstracts filter creation, libseccomp, keeps evolving. The 2.6.x releases brought new architecture support (including LoongArch and RISC-V 32/64-bit), more precise architecture handling, and a number of security fixes in the BPF generator itself.

Why do updates matter? A wrongly composed seccomp filter can become a new security hole — for example, a bug in the BPF generator that produces a filter that doesn't match what you asked for. For production, always use the latest libseccomp version and watch the changelog for CVE awareness. Verify your version with pkg-config --modversion libseccomp.

The Problems Seccomp Solves

After looking at the history, let's crisply summarize four concrete problems that seccomp solves:

1. Closing the attack surface. A process only needs a small subset of the hundreds of available syscalls. Seccomp ensures the rest cannot be called, so an exploit chain is cut off at the earliest step.

2. Preventing privilege escalation and exploitation. Blocking syscalls like execve and socket cuts off an attacker's ability to run payloads, read sensitive files, or establish outbound communication — even if execution control has already been seized.

3. Reducing blast radius. When a component is compromised, seccomp limits the damage to that component alone. A breached service doesn't automatically grant access to the whole machine or internal network.

4. Enforcing "least privilege" policy at the kernel level. Seccomp is one of the few mechanisms where the security decision is executed in the kernel rather than in user-space — so it cannot be bypassed by an already-compromised process.

The key thing to understand: seccomp is not a replacement for other security mechanisms. It's defense in depth — one layer among many. Namespaces limit what a process sees, cgroups limit resources, and seccomp limits the actions a process can take against the kernel. All three complement each other; they don't substitute for each other.

Conclusion

Here's the core of episode 1:

  • Seccomp was born from a real problem: every syscall is a potential exploitation entry point.
  • Kernel 2.6.12 (2005) introduced strict mode — only 4 syscalls, too narrow for wide adoption.
  • Kernel 3.5 (2012) introduced seccomp-bpf — flexible BPF filters, and that was the turning point.
  • Chromium, Docker/runc, systemd, and libcontainer made seccomp standard infrastructure.
  • libseccomp 2.6.x (2024–2026) keeps being updated with new architectures and security fixes.
  • Seccomp closes the attack surface, prevents exploitation, reduces blast radius, and enforces least privilege at the kernel level.

In the next episode 2, we'll dissect the basic concepts and core architecture of seccomp — from the SECCOMP_MODE_STRICT and SECCOMP_MODE_FILTER modes, the role of prctl and the seccomp syscall, kernel components versus libseccomp, to how filters are applied by runc/crun, systemd, and OpenSSH. There you'll see how all that history works technically inside the system. See you then!

Learn Seccomp - History, Background & Why You Need Seccomp | Learn Seccomp