Kubernetes 里策略变成进程状态只有一处,就是创建。检查点恢复是通往运行进程的第二条路,而这条路上没有任何环节决定:当保存的状态与目标策略冲突时,谁说了算。
正常路径下,进程由声明构建:Pod spec 通过准入,kubelet 把容器配置交给运行时,运行时再把它翻译成内核状态——用户与组、capability 集合、no_new_privs 标志、seccomp 过滤器。spec 里的字段是请求,进程上的标志才是执行。
检查点恢复不构建进程,而是重建进程。CRIU 记录运行中进程的凭据、capabilities、no_new_privs 和 seccomp 状态,恢复时直接回放。在 containerd 暴露的路径上,恢复由普通容器创建调用触发,来源是检查点归档或带注解的镜像。Kubernetes 目前只支持通过镜像注解恢复容器,所以从准入侧看,这就是一次带镜像引用的 Pod 创建;是否属于恢复,由运行时根据镜像内容在更晚的阶段决定。
containerd 9 月 1 日的公告直接给出结果:从不可信检查点恢复的容器,可以以 root 运行、拥有完整 capabilities、没有 seccomp 过滤器,尽管编排器请求的是限制性策略。受影响范围从 2.1.0 起(不含 2.2.7),以及从 2.3.0 起(不含 2.3.4);这两个版本默认禁用该路径。同一路径在 6 月已产生三个信任失败:CVE-2026-50195 未校验检查点导入中的镜像引用,CVE-2026-53492 检查点元数据携带的 CDI 注解绕过资源分配与设备插件,CVE-2026-53489 符号链接日志路径未校验导致任意主机文件读取。CRI-O 的 CVE-2026-92574 记录了同样的结果。
这些不是四个属性上的四个 bug,而是同一个事件:制品提供的状态在恢复时生效,目标策略没有被覆盖上去。运行时没有拿保存的凭据与请求的用户做比较,本该替换它们的翻译步骤根本没运行。
containerd 的处理说明了问题形状。6 月的问题用点版本修复,CDI 那个在 2.1.9、2.2.5 和 2.3.2 修掉,恢复路径保留。9 月的问题无法这样修:按公告自己的说法,containerd 在恢复进程时「无法强制执行目标安全策略」。于是 2.2.7 和 2.3.4 默认禁用该路径,2.4 移除它。移除早已排期:2.3 起弃用 CRI create 期间的恢复,2.4 目标移除,替代方案是 KEP-5823 的 RestorePod API。
另一个问题是状态报告。containerd 的 CRI 状态反映的是请求的配置,不是恢复后进程的实际状态,编排器读状态看到目标策略,进程跑的却是保存的策略。要拿证据只能从进程读:节点上 /proc/<pid>/status 里的 NoNewPrivs、Seccomp、CapEff 字段,可与 Pod 请求的安全上下文比对。
缓解措施是否可用取决于发布线。containerd 文档列出 2.1 于 2026 年 7 月 3 日结束生命周期,9 月公告的受影响范围从 2.1.0 起,修复版本只有 2.2.7 和 2.3.4,没有列出修复的 2.1 版本;未打补丁的版本上,公告称 containerd 不提供禁用 create 调用恢复的选项。2.2 支持到 2026 年 11 月 6 日,2.3 是 LTS 到 2028 年 4 月,2.4 已移除该路径。
如果恢复是第二条实例化路径,它就需要自己的证明,因为准入给不了。要证明三件事:恢复是被有权限的人有意请求的;制品来自平台信任的来源;回来的进程持有目标策略规定的属性。第三点状态给不了。KEP-5823 把前两点显式化:恢复在 Pod spec 上声明,通过专用 restore 动词授权,且仅当 Pod spec 等于 kubelet 在打检查点时所记录的模板才被准入。但按 KEP 的写法,它不校验恢复后的进程本身,运行时检查点归档对 Kubernetes 是不透明的。