默认的 seccomp 配置到底挡了什么?怎么区分一个 EPERM 是 seccomp 挡的还是 capability 挡的?这篇在默认和 unconfined 下发同一批系统调用,逐个对比结果。
docker info SecurityOptions:[name=seccomp,profile=builtin name=cgroupns] 默认:/proc/self/status → NoNewPrivs=0 Seccomp=2 Seccomp_filters=1 --security-opt seccomp=unconfined:/proc/self/status → NoNewPrivs=0 Seccomp=0 Seccomp_filters=0
/proc/self/status 里的 Seccomp:2 是 filter 模式;--security-opt seccomp=unconfined 和 --privileged 都是 0。
系统调用 默认 unconfined getpid 成功(返回 1) 成功(返回 1) add_key EPERM 成功(返回 1033774437) keyctl EPERM EINVAL unshare(CLONE_NEWUSER) EPERM 成功(返回 0) userfaultfd EPERM ENOSYS perf_event_open EPERM EFAULT bpf EPERM EINVAL kcmp EPERM ESRCH personality(0xffffffff) EPERM 成功(返回 0) mount EPERM EPERM ptrace(PTRACE_TRACEME) 成功(返回 0) 成功(返回 0) clock_settime EPERM EFAULT swapon EPERM EPERM
默认配置下,add_key、keyctl、unshare(CLONE_NEWUSER)、userfaultfd、perf_event_open、bpf、kcmp、personality、clock_settime 都返回 EPERM;关掉 seccomp 后它们到达内核,返回别的 errno(参数故意给得不合法的会得到 EINVAL、EFAULT 等,这说明过滤器不再拦截)或者成功。mount 和 swapon 在两种配置下都是 EPERM:需要 CAP_SYS_ADMIN,和 seccomp 无关。判断一个 EPERM 来自哪里,最直接的办法就是把 seccomp 关掉再试一次。这批系统调用号是 arm64 的,amd64 不同;只测了这 13 个,不是完整的黑名单。
--privileged:NoNewPrivs=0 Seccomp=0 Seccomp_filters=0 --security-opt no-new-privileges:NoNewPrivs=1 Seccomp=2 Seccomp_filters=1
--privileged 会把 seccomp 一起关掉;no-new-privileges 只设置 NoNewPrivs=1,seccomp 照常启用。