bigywater.tech
Docker · 44

seccomp 默认策略:哪些系统调用被禁止了

默认的 seccomp 配置到底挡了什么?怎么区分一个 EPERM 是 seccomp 挡的还是 capability 挡的?这篇在默认和 unconfined 下发同一批系统调用,逐个对比结果。

9 个
13 个系统调用里,默认 seccomp 返回 EPERM 而 unconfined 能进入内核的个数
Seccomp=2
容器进程的 seccomp 模式(filter);unconfined 与 --privileged 为 0
mount 仍 EPERM
关掉 seccomp 之后仍被拒绝,说明那是 capability 的限制

状态

实测 · 本机执行输出
  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 照常启用。

分步演示

默认 seccomp
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Docker Desktop(Engine 29.8.2,容器跑在 Docker Desktop 自带的 Linux 虚拟机里,内核与宿主机的 macOS 不同);镜像为 linux/arm64;需要看虚拟机内部时用特权容器 + nsenter;计时用 time / date +%s%N,数字每次运行会有小幅抖动。系统调用用 Python ctypes 的 syscall(),号码是 linux/arm64 的(getpid 172、add_key 217、keyctl 219、unshare 97、userfaultfd 282、perf_event_open 241、bpf 280、kcmp 272、personality 92、mount 40、ptrace 117、clock_settime 112、swapon 224);参数多数是故意不合法或无害的,只用来看 errno;每种配置运行一次;实验后已删除容器和镜像
    • 没有验证:默认 profile 的完整 JSON 内容、自定义 seccomp profile 的写法与效果、amd64 上的差异、与 capability 同时放开时哪些调用才可用、seccomp 的性能开销、Docker Desktop 以外的内核版本
    京ICP备2026067502号-1京公网安备11010502063487号