seccomp(2)
Set the thread's seccomp state: strict mode or a BPF filter on every syscall.
- Since
- Linux 3.17check your kernel →
- glibc
- none (use syscall(2))
- System
- Linux
- Man page
- seccomp(2)
Synopsis
#include <linux/seccomp.h>
#include <linux/filter.h>
#include <linux/audit.h>
#include <sys/syscall.h>
#include <unistd.h>
int syscall(SYS_seccomp, unsigned int operation, unsigned int flags,
void *args);Rod's take
A typical daemon uses forty-odd syscalls and leaves a few hundred more loaded and pointed at whoever pops your input parser. seccomp is how you unload them. Set no_new_privs first or the load fails with EACCES and you're running naked while thinking you're armored, so check the return. Check arch before the syscall number or the 32-bit ABI walks right past you. The filter compares integers; it can't chase pointers, so paths are Landlock's problem. pledge does the coarse version in one line. This is the two-day precise version, and for untrusted code it earns it.
Flags and arguments that matter
| Name | What it does |
|---|---|
| SECCOMP_SET_MODE_STRICT | Allow only read(2), write(2), _exit(2) and sigreturn(2); anything else kills the caller. |
| SECCOMP_SET_MODE_FILTER | Install a classic BPF program (struct sock_fprog) run on every syscall. Needs no_new_privs or CAP_SYS_ADMIN. |
| SECCOMP_FILTER_FLAG_TSYNC | Synchronize all threads of the process to the new filter tree. |
| SECCOMP_FILTER_FLAG_LOGLinux 4.14 | Log all filter actions except SECCOMP_RET_ALLOW. |
| SECCOMP_FILTER_FLAG_NEW_LISTENERLinux 5.0 | Return a user-space notification fd for SECCOMP_RET_USER_NOTIF. |
| SECCOMP_GET_ACTION_AVAILLinux 4.14 | Test whether the kernel supports a given filter return action. |
| SECCOMP_RET_KILL_PROCESSLinux 4.14 | Filter action: kill the whole process with a core dump; the syscall is not executed. |
| SECCOMP_RET_ERRNO | Filter action: skip the syscall and return the low 16 data bits as errno. |
| SECCOMP_RET_USER_NOTIFLinux 5.0 | Filter action: hand the decision to a user-space supervisor via the listener fd. |
| SECCOMP_RET_LOGLinux 4.14 | Filter action: allow the syscall but log it. |
Errors you will actually hit
| errno | Meaning |
|---|---|
| EACCES | Caller lacks CAP_SYS_ADMIN and hasn't set no_new_privs before SECCOMP_SET_MODE_FILTER. |
| EINVAL | Unknown operation, invalid flags, or an invalid/empty/too-long (>4096 insns) filter. |
| EFAULT | args was not a valid address. |
| EBUSY | NEW_LISTENER requested but a filter with a listener is already installed. |
| ENOMEM | Out of memory, or total filter length on the thread exceeds 32768 instructions. |
Example
prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_ERRNO(EPERM));
if (!ctx)
errx(1, "seccomp_init");
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
if (seccomp_load(ctx) < 0) /* libseccomp calls seccomp(2) */
errx(1, "seccomp_load");
seccomp_release(ctx);Trimmed from the full walkthrough in Your process doesn't need 400 syscalls. seccomp-BPF lets you say so..
BSD equivalent
OpenBSD: pledge(2) (OpenBSD 5.9), coarse promise strings rather than BPF. FreeBSD: Capsicum capability mode via cap_enter(2).
The long version, from the console
Sources
Version numbers are read off the cited man pages, not memory. Spot one that's wrong? Tell Rod.
