seccomp是linux内核原生的进程级系统调用限制机制,通过默认拒绝+显式白名单(如default_action设为scmp_act_errno)实现最小权限控制,需精准放行openat、read、mmap、clone等基础设施级调用,并严格遵循json字段名、架构声明和路径权限规范。

Seccomp 是 Linux 内核原生的安全机制,专用于在进程级限制系统调用(syscall),它不依赖容器或外部工具,直接在内核拦截非法调用,是缩小攻击面最底层、最有效的手段之一。
明确目标:不是“禁掉所有危险调用”,而是“只放行必需的”
盲目禁止 ptrace、mount、reboot 等高危调用看似安全,但若未保留基础运行所需调用(如 openat、statx、brk、mmap),程序会立即崩溃——连启动都失败。关键逻辑是白名单思维:
- 默认拒绝所有系统调用(default_action 设为 SCMP_ACT_ERRNO 或 SCMP_ACT_KILL)
- 仅显式允许进程真实需要的调用,一个都不能少,也一个都不能多
- 先观察再裁剪:用 strace 或 audit-seccomp 捕获实际调用链,而非凭经验猜测
正确编写与加载 Seccomp JSON 配置
Docker 和 containerd 只接受标准 JSON 格式的 seccomp profile,且字段名严格区分大小写。常见错误会导致容器启动失败:
- 字段必须是 default_action(不是 defaultAction)、architectures(不是 arch)、syscalls(不是 syscall)
- architectures 必须包含宿主机架构,例如 ["SCMP_ARCH_X86_64"];漏掉则报 “no matching architecture”
- 文件路径必须是 daemon 可读的绝对路径,如 /etc/docker/restrict.json;不能用 ./profile.json 或 ~/profile.json
- 确保权限:sudo chmod 644 /etc/docker/restrict.json,且 docker daemon 运行用户(通常是 root)有读取权
哪些系统调用通常不可省略?
即使追求最小权限,以下调用对绝大多数程序(包括 Go/Node.js/C++)属于“基础设施级”依赖,禁用即失效:
- openat:打开文件、加载动态库、读取 /proc、解析环境变量的基础
- read / write / close / lseek:I/O 操作主干
- statx / fstat / newfstatat:检查文件元数据,Go runtime 和 libc 广泛使用
- mmap / mprotect / munmap / brk:内存分配与管理,禁用后 malloc 失败、程序 panic
- rt_sigreturn / sigaltstack / sigprocmask:信号处理,影响异常捕获和线程调度
- clone / epoll_wait / epoll_ctl / getrandom:Go 和 Node.js 运行时高频调用,禁用将导致服务无法响应请求
进阶控制:用 args 实现参数级过滤
seccomp 支持对系统调用参数做条件判断,实现更精细的防护。例如:
- 只允许 write 写入 stdout(fd=1)和 stderr(fd=2),拒绝写入其他 fd:
"action": "SCMP_ACT_ALLOW", "args": [{"index":0,"value":1,"op":"=="}] - 禁止 execve 执行以 /tmp/ 开头的路径:
需结合 seccomp-bpf 规则(非纯 JSON 支持),推荐用 libseccomp 编程实现或 seccompiler 工具生成 - 注意:args 过滤无法检查路径字符串内容(因参数是指针),只能比对指针地址或整数参数,真正路径限制应由 AppArmor/mount --ro 等机制补充











