Linux seccomp-bpf 的默认 profile 与 Docker/Kubernetes 自定义过滤器编写

1次阅读

linux seccomp-bpf 无内核默认策略,进程默认禁用;docker/k8s 的“默认”是各自预定义的白名单策略,自定义需基于实际系统调用行为和最小权限原则裁剪。

Linux seccomp-bpf 的默认 profile 与 Docker/Kubernetes 自定义过滤器编写

Linux seccomp-bpf 没有全局“默认 profile”,其行为完全取决于应用是否显式启用 seccomp 并加载 BPF 过滤器。Docker 和 kubernetes 的所谓“默认”实为各自预定义的白名单策略,而非内核内置规则;自定义过滤器需基于系统调用语义、容器最小权限原则和实际 workload 行为来编写,不能套用通用模板。

seccomp 在内核中无默认策略

内核本身不提供任何 seccomp 默认配置。进程默认处于 seccomp-disabled 状态(SECCOMP_MODE_DISABLED)。只有当进程调用 prctl(PR_SET_SECCOMP, ...) 或通过 clone/execve 继承已启用的 seccomp 状态时,才进入受限模式。这意味着:

  • 裸机上运行的普通进程不受 seccomp 限制
  • 未显式配置 seccomp 的容器(如直接用 runC 启动且未传入 --seccomp)也不会自动启用
  • “默认”一词在 seccomp 上下文中仅指 Docker/K8s 工具链的预设策略,非内核行为

Docker 的默认 seccomp profile 是白名单 + 安全裁剪

Docker 20.10+ 内置的默认 profile(default.json)允许约 60–70 个常用系统调用,拒绝其余所有调用(SCMP_ACT_errno),并禁用高风险调用如 ptracemountsetuidsyslog 等。关键特点包括:

  • 基于 syscall 白名单,而非黑名单 —— 显式列出允许项,其余一律拒绝
  • personalitycapsetkeyctl 等能力相关调用默认禁止
  • 允许 openat 但限制 open(因后者更易绕过路径约束)
  • socket 调用按 domain/type/protocol 做细粒度放行(如只允 AF_INET, SOCK_STREAM

可通过 docker run --seccomp-default(显式启用)或 --seccomp ./profile.json 加载自定义文件;禁用则用 --seccomp=unconfined

Kubernetes 的 seccomp 配置依赖 Pod 安全策略与运行时支持

K8s 本身不解析或执行 seccomp 规则,而是将策略透传给容器运行时(如 containerd 或 CRI-O)。seccomp 配置通过 Pod 或 Container 的 securityContext.seccompProfile 字段声明:

  • type: RuntimeDefault:交由运行时决定(containerd 默认使用与 Docker 相同的 default.json)
  • type: Localhost + localhostProfile: "profiles/my-policy.json":从节点本地路径加载 JSON 文件(需提前部署到每个节点的 /var/lib/kubelet/seccomp/ 下)
  • type: Unconfined:跳过 seccomp 限制(不推荐)

注意:K8s v1.19+ 才正式支持该字段(GA),且要求 kubelet 启用 SeccompDefault 特性门控(v1.25+ 默认开启)。

编写自定义 seccomp 过滤器的关键实践

有效的自定义 profile 不是靠“加功能”,而是靠“减攻击面”。推荐步骤如下:

  • 先观测再限制:用 strace -f -e trace=raw_syscallauditd + ausearch -m avc -ts recent 记录容器真实 syscall 流量,识别必需调用
  • 继承 default.json 再裁剪:以 Docker 默认 profile 为起点,用 jq 删除明确不需要的条目(如移除 chmod 若容器只读文件系统)
  • 慎用 SCMP_ACT_TRACE:在调试阶段可设为 trace 并配合 seccomp-tools dumpbpftrace 分析被拦截行为,避免误杀
  • 按 syscall 参数过滤:例如限制 socket 仅允许 TCP/IPv4:
    "action": "SCMP_ACT_ALLOW", "args": [{"index":0,"value":2,"valueMask":4294967295},{"index":1,"value":1,"valueMask":4294967295}]

    (domain=AF_INET=2, type=SOCK_STREAM=1)

  • 避免硬编码 errno:用 SCMP_ACT_ERRNO 时指定标准错误码(如 "errnoRet": 1 对应 EPERM),而非随意返回值

工具链建议:用 docker-seccomp CLI 生成初始 profile;用 jqgit diff 管理 profile 版本;CI 中集成 check-seccomp 验证 JSON 结构与 syscall 存在性。

text=ZqhQzanResources