- 云原生
【免费下载链接】mesos
Apache Mesos
Mesos 的linux/seccomp隔离器允许在 MesosContainerizer 启动的每个容器内安装 Linux Seccomp 过滤器,通过只放行白名单内的系统调用来收缩内核攻击面。本篇结合 官方文档 与仓库源码,覆盖 Agent 端参数配置、兼容 Docker 格式的 Seccomp profile 编写、任务级 profile 覆盖,以及从 profile 解析到seccomp_load落地的完整源码链路,帮助你在集群中为容器启用系统调用级安全加固。
机制概述
Seccomp 是 Linux 内核提供的一种系统调用过滤机制,Seccomp filter 模式要求内核 3.5 或更新版本。过滤器由一个 Seccomp profile 定义,profile 的格式必须与 Docker 的 Seccomp profile JSON 格式兼容,仓库中提供了完整示例 seccomp_default.json。
在 Mesos 中的工作方式可以概括为三个阶段:
- Agent 启动时:
linux/seccomp隔离器被加载,校验 root 权限与内核支持,解析可选的默认 profile; - 容器 prepare 阶段:隔离器根据 Agent 默认 profile 或任务在
LinuxInfo中声明的 profile,把最终选定的 profile 装入ContainerLaunchInfo; - launcher 阶段:launcher 子进程在
exec用户命令之前,基于 profile 构建 libseccomp 过滤器并调用seccomp_load安装到内核。
隔离器在 mesos containerizer 隔离器注册表 中以"linux/seccomp"为键注册,且 声明支持嵌套与 standalone 容器,即对普通任务和 standalone container 均生效。
Agent 端配置
隔离器加载条件与前置检查
只有当linux/seccomp出现在 agent 的--isolation标志中时该隔离器才会被加载。源码 LinuxSeccompIsolatorProcess::create 在隔离器创建时做三项硬性检查:
- 必须 root:
geteuid() != 0直接返回Linux Seccomp isolator requires root permissions。原因是 Seccomp filter 必须由特权进程安装;如果不走 root 路径而依赖no_new_privs位,会禁止容器内非特权用户运行 setuid/setgid 程序(如ping、sudo),副作用太大,因此官方选择要求 root; - 内核支持:通过
prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER)探测,若返回值不是预期的EFAULT错误,说明内核不支持 Seccomp filter; - 必须提供
--seccomp_config_dir:缺失该 flag 会直接报Missing required '--seccomp_config_dir' flag。
配置参数
flag 定义见 src/slave/flags.cpp:
| 参数 | 必填 | 说明 |
|---|---|---|
--isolation | 是 | 需包含linux/seccomp,可与其他 isolation 组件同时启用 |
--seccomp_config_dir | 是 | Seccomp profile 所在目录。若任务指定了 profile 名称,隔离器会在此目录中定位对应 profile 文件 |
--seccomp_profile_name | 否 | 默认 Seccomp profile 的路径,必须相对于--seccomp_config_dir。设置后所有容器默认应用该 profile;省略则默认不应用任何 profile |
启动示例
一个典型的 agent 启动命令:
sudo mesos-agent --master=<master ip> --ip=<agent ip> --work_dir=/var/lib/mesos --isolation=linux/seccomp[,other isolation flags] --seccomp_config_dir=/etc/mesos/seccomp --seccomp_profile_name=default.json注意两点:sudo对应上文提到的 root 前置条件;若同时启用多个 isolation 组件,--isolation使用逗号分隔,例如--isolation=linux/cgroups,linux/seccomp。
Seccomp Profile 格式
Docker 兼容的 JSON 结构
Mesos 的 profile 解析器 parseProfileData 按顺序解析四个必需/约定字段,对应 Docker profile 格式:
{ "defaultAction": "SCMP_ACT_ERRNO", "archMap": [ { "architecture": "SCMP_ARCH_X86_64", "subArchitectures": ["SCMP_ARCH_X86", "SCMP_ARCH_X32"] } ], "syscalls": [ { "names": ["accept", "bind", "clone"], "action": "SCMP_ACT_ALLOW", "args": [], "includes": {}, "excludes": {} } ] }各字段的行为细节(均可在 seccomp_parser.cpp 中验证):
defaultAction:默认动作,必须以SCMP_前缀书写。解析器支持SCMP_ACT_KILL、SCMP_ACT_TRAP、SCMP_ACT_ERRNO(映射为SCMP_ACT_ERRNO(EPERM))、SCMP_ACT_TRACE、SCMP_ACT_ALLOW五种取值,见 resolveAction;archMap:每项含architecture与subArchitectures。解析时会调用SeccompFilter::nativeArch比对宿主原生架构,非本机的条目(含子架构)会被直接忽略,只保留匹配项,见 parseArchMap。支持的架构枚举定义在 seccomp.proto,涵盖 x86、ARM、MIPS、PPC、s390 系列;syscalls:每项定义一组系统调用规则,包含names(系统调用名列表,不可为空)、action、可选的args参数匹配、以及includes/excludes过滤条件;args:对系统调用参数做精细匹配,字段为index、op、value、valueTwo。比较运算符支持SCMP_CMP_NE/LT/LE/EQ/GE/GT/MASKED_EQ,见 resolveArgCmpOperator。例如 seccomp_default.json 中对personality系统调用按参数值分别放行;includes/excludes:支持两类过滤条件——arches(CPU 架构,短名如amd64、arm)与caps(Linux capabilities,CAP_前缀)。架构过滤在解析 profile 时即完成;capability 过滤则被推迟到 launcher 阶段结合进程 bounding set 计算,因为解析时刻尚不知道容器最终的 capability 列表,见 parseSyscalls 中的注释。
解析完成后还会主动构建一次过滤器做校验(seccomp_parser.cpp),因此格式合法但引用了不存在的系统调用(Unrecognized syscall 'xxx')的 profile 会在解析期即被拒绝——默认 profile 在 agent 启动时就会失败,任务级 profile 则在容器 prepare 阶段失败。
必须包含 pivot_root
Mesos containerizer 的 rootfs 切换使用pivot_root系统调用(而不是 Docker 惯用的chroot),所以 profile 中必须放行pivot_root。Docker 的默认 profile 通常只有chroot,需要把它改写为"names": ["chroot", "pivot_root"]。仓库自带的 seccomp_default.json 正是这样处理的,两条系统调用位于同一names数组中。若遗漏该调用,容器将在切换 rootfs 时失败。
任务级覆盖:SeccompInfo
Agent 的默认 profile 只是基线,单个任务可以覆盖它。框架需要在任务的ContainerInfo的LinuxInfo中设置SeccompInfo,其字段定义见 mesos.proto:
message SeccompInfo { // 相对于 --seccomp_config_dir 的 profile 文件名 optional string profile_name = 1; // 设为 true 时,该容器不应用任何 Seccomp filter optional bool unconfined = 2; }两者互斥且至少显式指定其一,隔离器的 prepare 逻辑 严格执行如下规则:
| 情况 | 结果 |
|---|---|
unconfined = true且同时给了profile_name | 失败:Invalid Seccomp configuration: 'profile_name' given even though 'unconfined' Seccomp setting is enabled |
只给profile_name | 从--seccomp_config_dir读取并解析该 profile,覆盖 agent 默认 profile |
只设unconfined = true | 记录Seccomp is not applied to container <id>日志,该容器不装过滤器 |
设置了SeccompInfo但两个字段都为空 | 失败:Missing Seccomp profile name |
未设置SeccompInfo | 沿用 agent 的--seccomp_profile_name默认 profile(若未配置则不应用) |
例如:agent 以默认 profile 启动时,某个需要更多系统调用的任务可以设置unconfined = true单独豁免;反之,agent 未配置默认 profile 时,也可以用profile_name为单个任务启用过滤。选定的 profile 会被写入ContainerLaunchInfo.seccomp_profile字段随启动信息传给 launcher。
源码实现:从 Profile 到内核过滤器
过滤器构建:SeccompFilter::create
launcher 子进程最终通过 SeccompFilter::create 把 proto 形态的 profile 转成 libseccomp 上下文,几个关键实现点值得注意:
- 关闭
no_new_privs自动设置:seccomp_attr_set(ctx, SCMP_FLTATR_CTL_NNP, 0)。这与 Docker daemon 的做法一致——由 root 特权进程安装过滤器,避免给容器进程设置no_new_privs位导致容器内 setuid/setgid 程序(ping、sudo等)不可用,见 seccomp.cpp 的注释; - capability 过滤落地:对带
includes/excludescapabilities 的规则,用进程 bounding set 判定——includes的 caps 必须全部包含在 bounding set 中(否则整条规则跳过),excludes的 caps 与 bounding set 有交集则跳过该规则,见 seccomp.cpp。这使得同一份 profile 可以在不同 capability 配置的容器间自适应; - 规则安装:逐条把系统调用名解析为 syscall 号,带参数匹配的规则走
seccomp_rule_add_array,否则走seccomp_rule_add。任何一步失败都返回明确错误(如Failed to add rule for syscall 'xxx' with action 'yyy')。
launcher 中的安装时机
launch.cpp 显示过滤器安装在容器环境的最后一步:完成 user/group 切换准备、进入 mount namespace、enterChroot切换 rootfs、rlimits 安装之后、exec用户进程之前,调用SeccompFilter::create(...)构建过滤器并load()(底层为seccomp_load)。失败时直接exitWithStatus(EXIT_FAILURE),容器启动失败——这保证了过滤器只约束容器内进程,不波及 agent 自身。
测试与验证
仓库提供了覆盖主要路径的隔离器测试 linux_seccomp_isolator_tests.cpp,可以作为验收 checklist:
ROOT_MissingConfigDir/ROOT_InvalidDefaultProfile:缺--seccomp_config_dir、默认 profile 解析失败时 agent 启动应报错;ROOT_SECCOMP_LaunchWithDefaultProfile:使用id && env && uname && hostname作为命令,验证默认 profile 下容器正常启动且退出码为 0,见 测试实现;ROOT_SECCOMP_LaunchWithUnameDisabled:构造一份禁用uname系统调用的 profile,验证内核确实按 profile kill 掉触法进程;ROOT_SECCOMP_LaunchWithSeccompDisabled:任务通过unconfined豁免 Seccomp 的验证;ROOT_SECCOMP_LaunchWithOverriddenProfile:任务级profile_name覆盖默认 profile 的验证;LinuxSeccompIsolatorWithCapabilitiesTest:带 Linux capabilities 过滤条件(includes/excludescaps)的场景。
适用前提与限制
- 仅 Linux 平台,内核需 3.5+(Seccomp filter 模式);构建时需启用 seccomp 支持(源码中相关逻辑由
ENABLE_SECCOMP_ISOLATOR宏包裹); - Agent 必须以 root 运行该隔离器,且必须显式配置
--seccomp_config_dir; - Profile 文件必须兼容 Docker Seccomp profile 格式,且
pivot_root不可遗漏; defaultAction为SCMP_ACT_ERRNO的白名单模式下,任何未列出的系统调用都会返回EPERM,选型 profile 时建议以 seccomp_default.json 这类经过完整系统调用清单的 profile 为基线按需裁剪,而不是从零编写。
- 云原生
【免费下载链接】mesos
Apache Mesos
相关推荐
Apache Mesos 的 Linux Seccomp 隔离器(linux/seccomp):从 profile 编写到容器隔离实战
Apache Mesos 的 Linux Seccomp 隔离器(linux/seccomp):从 profile 编写到容器隔离实战 Seccomp(Secu
集群管理任务调度后端Apache Mesos Linux Seccomp Isolator:为容器安装系统调用过滤器的完整指南
Apache Mesos Linux Seccomp Isolator:为容器安装系统调用过滤器的完整指南 Apache Mesos 的 linux/secco
云原生集群管理容器编排任务调度终极指南:Apache Mesos容器隔离器详解与实战配置
终极指南:Apache Mesos容器隔离器详解与实战配置 Apache Mesos容器隔离器是Mesos集群资源管理的核心技术,为任务提供安全、高效的运行环境
云原生
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考