2.2 加固:gVisor 与微 VM


2.2 加固:gVisor 与微 VM

本节摘要:2.1 节的四道边界挡得住文件系统、网络与资源攻击,挡不住第四类——内核漏洞:容器与宿主共享同一个内核,runc 历史上出现过真实逃逸漏洞(CVE-2019-5736、CVE-2024-21626,均为官方 CVE 记录),而任意执行型 Agent 恰恰是最有动机利用它们的那类负载。本节给出两条补丁路线:gVisor(runsc)在用户态实现一个 Sentry 内核拦截并重新实现系统调用,Docker 换个 runtime 参数即可接入,代价是系统调用密集型负载的性能损耗;Firecracker 干脆给每个 microVM 一个独立内核,隔离最彻底、启动不超过 125 毫秒(官方数据),但要自管内核镜像、rootfs 与网络。最后用一张三路线选择表收束,并以 E2B 展示「Firecracker + 快照池」的产品化形态。

学习目标

  • 说清共享内核风险的具体含义,能举出两个 runc 历史 CVE。
  • 完成 runsc 的接入与验证(Linux 环境),知道它与普通容器的差异在哪。
  • 描述 Firecracker microVM 的工作方式、官方性能数字与运维代价。
  • 用选择表在「加固容器 / runsc / Firecracker」之间做最终决定。

一、共享内核:加固容器的天花板

容器的所有进程最终都运行在宿主内核上。这意味着:内核暴露给容器内代码的每一个攻击面,都是你的攻击面。这不是理论担忧——

  • CVE-2019-5736(官方记录):runc 逃逸漏洞,容器内进程可覆盖宿主上的 runc 二进制,下一次宿主执行容器操作时以 root 运行攻击者代码。
  • CVE-2024-21626(官方记录):runc 文件描述符泄漏,容器内进程借泄漏的 fd 访问宿主文件系统,实现逃逸。
(文字流程图)容器逃逸的共性 容器内恶意代码 ──▶ 利用 runc / 内核漏洞 ──▶ 在宿主以高权限执行 ──▶ 沙箱整体失守 ▲ 这一步发生在「共享内核 / 共享运行时」地带, 2.1 节的四道边界管不到这里 ​

⚠️ 校准风险感:这类漏洞的利用有条件、有窗口期,普通后端容器长期未升级也未必被打穿。但 Agent 沙箱的负载是「刻意尝试越狱的自动化代码」,威胁模型不同——第 1 章选了微 VM 级别的读者,这一节就是你的落地路径。

二、gVisor(runsc):换 runtime 即接入

原理:runsc 提供一个用户态内核 Sentry。容器内应用发出的系统调用被 Sentry 截获、在用户态重新实现,再以受控的最小接口与宿主打交道。内核漏洞攻击打到的是 Sentry 的重新实现,宿主内核不直接暴露。数字:典型容器启动延迟约 50~100 毫秒(社区资料,2026);GKE Sandbox 以 runsc 跑不可信负载(官方资料)。

接入三步(写法示意,以 gVisor 官方快速上手为准):

# install_runsc.sh —— runsc 接入 Docker(写法示意,具体版本与路径以官方文档为准) # 1) 从官方 GitHub Releases 下载对应架构的 runsc 压缩包并解压到 /usr/local/bin # 2) 注册 runtime:执行 runsc install 会改写容器运行时配置;等价的手工写法如下 # 在 /etc/docker/daemon.json 中加入: # { "runtimes": { "runsc": { "path": "/usr/local/bin/runsc" } } } sudo systemctl restart docker # 3) 验证:用 runsc 跑一个断网容器 docker run --rm --runtime=runsc --network none agent-sandbox:py3.12 python -c "print('inside runsc')" ​

开销与兼容性:系统调用密集型任务(高频文件操作、网络系统调用)有感变慢,计算密集型接近原生(社区实测,量级与负载强相关);多数常用系统调用已支持,冷门 ioctl、ptrace 类仍有缺口(官方兼容性文档)——所以接入后要重跑 2.1 节的四组验证实验,确认你的负载不掉坑。

💡 成本收益一句话:runsc 的接入成本约等于「改一行配置」,换来的是把「内核漏洞」这一类攻击面从暴露变为收敛——单租户、内部使用的任意执行型 Agent,这是性价比最高的升级。

三、Firecracker:每个 VM 一个独立内核

原理:AWS 开源的极简 microVM:最小设备模型 + KVM 虚拟化,每个 VM 拥有独立内核,隔离边界是硬件虚拟化,不再依赖「共享内核上的约定」。官方规格:启动不超过 125 毫秒、每 VM 内存开销小于 5 MiB、每秒可创建约 150 个 microVM(官方数据)。AWS Lambda 与 Fargate 基于它运行(公开资料)。

运维代价:不接入 Docker,需要自备——

  • 内核镜像与 rootfs:每个 VM 启动都要挂载,镜像内容与更新策略自己管理;
  • 虚拟网络:tap 设备、桥接与地址管理,Agent 沙箱通常还要配出站白名单网关;
  • 宿主侧隔离:配套 jailer 工具做 chroot / seccomp / cgroup 收紧(其演进方向以官方仓库讨论为准);
  • 快照管理:要做「预热池」压冷启动,就得管理快照的生命周期与安全基线。

这些是一次性平台工程投入,适合多租户平台,不适合单团队快速起步。

💡 平台工程判断:Firecracker 的投入是一次性的(镜像、网络、快照池),产出是每租户独立内核——团队规模与租户数量决定这笔投入值不值。

产品化参照 E2B(公开设计资料):开源 Agent 沙箱基础设施,每个沙箱是一个 Firecracker microVM,用快照池把冷启动压到约 150 毫秒(官方宣称),支持暂停恢复与长会话,对外提供 SDK 与 MCP 接入。它验证了两件事:Firecracker 路线在 Agent 场景可行;「每会话一个 VM」正在成为多租户 Agent 执行的产业默认。

(文字流程图)从容器到 microVM 的职责变化 你负责:应用镜像 ──────────────────▶ 你负责:应用镜像 + 内核镜像 + rootfs + 网络 + 快照 运行时负责:共享内核(漏洞共享) 运行时负责:每 VM 独立内核(漏洞不共享) ​

四、三路线最终选择表

维度 加固容器(2.1) + runsc(本节) Firecracker microVM(本节)
内核漏洞攻击面 暴露于宿主内核 收敛(Sentry 拦截) 基本消除(独立内核)
接入成本 低(Docker 即用) 极低(换 runtime 参数) 高(内核 / rootfs / 网络 / 快照自管)
启动速度 数百毫秒(示意) 约 50~100 毫秒(社区) 不超过 125 毫秒(官方)
运行开销 接近原生 系统调用密集型有感 原生级 + 虚拟化少量开销
多租户 不建议 可用(谨慎) 推荐(产业默认)
适用 单租户读写型 Agent 单租户任意执行型 多租户 / 面向外部 / 平台化

决策快查:沿用第 1.2 节的三行隔离决定——选了「加固容器」的读本节了解升级路径即可;选了 runsc 的照第二节接入并重跑验证;选 Firecracker 的先把 2.3 节网关搭好(VM 池由网关调度),再投入镜像与网络工程。原理层的完整论述见《Harness 工程:从零打造智能体运行环境》第 6 章《沙箱与执行隔离》。

(文字流程图)升级路径可进可退:加固容器 ──▶ 加 runsc ──▶ 多租户需求出现再上 Firecracker;反向降级则必须重做一遍威胁模型,不能简单摘参数。

本节要点回顾

  • 共享内核是加固容器的结构性天花板,runc 两个官方 CVE 是真实注脚;Agent 负载是最有动机利用它的负载。
  • runsc:用户态内核拦截系统调用,换 runtime 即接入,系统调用密集负载有性能代价——接入后重跑四组验证实验。
  • Firecracker:独立内核 + 官方 125 毫秒启动,隔离最彻底,运维投入适合多租户平台;E2B 验证了「每会话一 VM」的产业路线。
  • 选择表收束:单租户读写型用加固容器,单租户任意执行型加 runsc,多租户平台上 Firecracker。

沙箱本体与隔离层都已就位,还剩最后一个架构问题:执行权放在谁手里?如果 Agent 直接调用 docker,白名单、审计、结果截断就都无从谈起。下一节把执行权收进网关,搭出 Agent → 网关 → 沙箱的三段式底座。


作者与出处
原作者: 灏天文库
整理: 灏天文库整理
本站整理收录,版权归原作者/开源协议所有;欢迎通过原文链接访问源仓库。
发布者: 作者: 灏天文库 转发
评论区 (0)
U