如何在宿主机记录Docker容器触发的seccomp系统调用违规行为
你说得对——seccomp本身确实支持记录被拦截的系统调用,完全不需要额外工具(比如Sysdig)。下面我会一步步教你怎么配置Docker的seccomp规则,让它把容器里被阻止的系统调用(比如chown)记录到宿主机的内核日志里。
Docker自带一个默认的seccomp配置,覆盖了大部分安全场景,我们基于它修改比从零写要高效得多。执行以下命令把默认配置导出到本地:
docker run --rm debian:latest cat /etc/seccomp.json > default-seccomp.json
打开导出的default-seccomp.json,找到你要拦截并记录的系统调用条目(比如chown、fchown、lchown)。默认情况下,这些调用的动作可能是SCMP_ACT_ERRNO(返回错误码阻止调用),我们需要把它改成记录日志+阻止的复合行为。
seccomp支持通过动作的按位或实现多重效果:
SCMP_ACT_ERRNO:阻止调用,返回指定错误码(比如EPERM,对应errno=1)SCMP_ACT_LOG:把系统调用的细节写入内核日志
在JSON配置里,我们可以直接用数值表示复合动作:SCMP_ACT_ERRNO | SCMP_ACT_LOG对应的数值是0x7ffd0000。修改后的规则示例:
{ "names": ["chown", "fchown", "lchown"], "action": 0x7ffd0000, "errno": 1 }
如果你只是想记录调用但不阻止(比如调试场景),直接把action改成"SCMP_ACT_LOG"即可,这样系统调用会被允许,但日志会被留存。
启动容器时,通过--security-opt参数指定我们修改后的配置文件:
docker run --security-opt seccomp=./default-seccomp.json your-container-image
被拦截并记录的系统调用会输出到宿主机的内核日志里,你可以用以下方式查看:
- 实时监控日志:
journalctl -k -f
- 或者筛选历史seccomp日志:
dmesg | grep seccomp
日志条目大概长这样:
seccomp: chown(12345, 0, 0) pid=6789 comm="bash" error=1
里面包含了系统调用名称、参数、容器内进程ID、命令名,以及我们设置的错误码(error=1对应EPERM)。
- 如果需要让所有新容器默认使用这个配置,可以修改Docker daemon的配置文件(比如
/etc/docker/daemon.json),添加"seccomp-profile": "/path/to/your/custom-seccomp.json",然后重启Docker daemon即可。 - 注意:这些日志是宿主机层面的,不会出现在容器自身的日志流里,必须在宿主机上查看。
内容的提问来源于stack exchange,提问作者MajorasKid

