seccomp vs Landlock
seccomp and Landlock are both Linux sandboxing mechanisms designed to enforce unprivileged process isolation, but they operate at different abstraction layers and target distinct resource types.
- seccomp (SECure COMPuting mode) filters system calls based on ABI syscall numbers and raw argument values before the kernel executes them.
- Landlock is an LSM (Linux Security Module) that restricts access to kernel objects (such as filesystem paths, IPC mechanisms, and network ports) dynamically using file descriptors and object-level permissions.
Key difference
seccomp: "Can I execute this system call?"
- What it sees: The syscall number (e.g.,
SYS_openat,SYS_connect) and scalar register arguments (integers, flags, pointers as raw memory addresses). - What it decides: Whether the CPU is allowed to transition into that kernel entry point at all.
- The limitation: It cannot safely inspect what pointers point to (due to TOCTOU memory race conditions). It knows you called
openat(), but it doesn't know which file you are opening.
Landlock: "Can I access this kernel object?"
- What it sees: Resolved kernel structures (inodes, path hierarchies, socket endpoints) passed via file descriptors during rule setup.
- What it decides: Whether the process has rights to perform a specific action (e.g.,
READ_FILE,MAKE_DIR,NET_BIND_TCP) on a target object. - Scope:
- Filesystem: Uses directory/file descriptors as topological "anchors" to grant or restrict access to entire directory subtrees (
LANDLOCK_RULE_PATH_BENEATH). - Networking (added in Linux 6.7+): Restricts TCP socket binding and connecting to specific port ranges (
LANDLOCK_RULE_NET_PORT).
- Filesystem: Uses directory/file descriptors as topological "anchors" to grant or restrict access to entire directory subtrees (
In Short
Process Call: openat(AT_FDCWD, "/etc/shadow", O_RDONLY)
│
▼
[ seccomp ] ➜ "Are openat() syscalls allowed?"
│ YES
▼
[ Kernel ] ➜ Resolves path string "/etc/shadow" to kernel inode/path object
│
▼
[ Landlock ] ➜ "Is reading this path hierarchy permitted for this thread?"
│ NO -> EACCES
▼
Execute file open
In summary:
- seccomp protects the kernel entry points (reducing kernel exploit attack surface).
- Landlock protects the system resources/objects (enforcing file and network access rules).
Core Architectural Comparison
| Feature | seccomp-BPF | Landlock LSM |
|---|---|---|
| Layer / Enforcement Point | Syscall entry boundary (prctl / cBPF filter) |
LSM hooks inside subsystem logic |
| Primary Target | System call numbers & scalar arguments | Kernel objects (Paths, Sockets, IPC) |
| Path Awareness | No (Cannot dereference pointers safely in cBPF) | Yes (Restrict access by file descriptors / path hierarchy) |
| Privileges Required | NO_NEW_PRIVS or CAP_SYS_ADMIN |
Unprivileged (requires NO_NEW_PRIVS to self-sandbox) |
| Network Control | Course-grained (allow/block socket, connect, bind) |
Fine-grained TCP port binding and connection rules |
| Filter Evaluation | Evaluated on every syscall made by the thread | Evaluated at LSM hook execution points |
| Kernel Version | Mainline since Linux 3.5 | Mainline since Linux 5.13 |
Architectural Differences
Why seccomp struggles with Filesystem and Object Control
seccomp-BPF operates at the system call boundary before arguments are dereferenced. Because user-space memory pointers (like string paths passed to openat(2)) can suffer from Time-of-Check to Time-of-Use (TOCTOU) race conditions, seccomp filters cannot safely inspect path strings or dereference pointers.
For instance, seccomp can block the openat syscall entirely, but it cannot restrict a process to *only read from /usr/share while blocking /etc*.
How Landlock Solves Path and Object Restrictions
Landlock works at the LSM level inside the kernel where data structures (like struct path or file descriptors) are already resolved.
Instead of filtering system call numbers, Landlock creates explicit access-rights rules tied to file descriptors opened by the application prior to dropping privileges:
// Example concept: Restricting filesystem access via Landlock
int ruleset_fd = landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
// Grant read-only access to /usr and /lib
int path_fd = open("/usr", O_PATH | O_CLOEXEC);
struct landlock_path_beneath_attr path_attr = {
.allowed_access = LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_READ_DIR,
.parent_fd = path_fd,
};
landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH, &path_attr, 0);
// Restrict current thread and future children
landlock_restrict_self(ruleset_fd, 0);
How They Complement Each Other
Rather than competing, seccomp and Landlock are typically layered together to create robust Defense-in-Depth for modern application sandboxing (e.g., systemd service isolation, container runtimes, web browsers, and CLI utilities):
- seccomp reduces kernel attack surface by blocking unused or dangerous system calls (e.g., disabling
kexec_load,ptrace,unshare, or obsolete 32-bit entry points). - Landlock enforces fine-grained access control on allowed calls (e.g., allowing
openatvia seccomp, but using Landlock to ensure it can only access specific directory trees or bind to designated local network ports).