MIT 6.1810 · 第 21 课 · nz

容器与虚拟机

如何隔离不受信任的代码?本节课以 Firecracker 和 gVisor 为案例,探讨从 chroot 到容器的隔离技术。

授课教师:nz

年份:2025 秋季

难度:中等

论文:Blending Containers and Virtual Machines (VEE 2020)

目标:隔离不受信任的代码

操作系统隔离基于内核 + 进程 + 虚拟内存。但:

动机:无服务器计算 (Serverless)

隔离方法概览

方法攻击面启动时间开销
Linux 进程 + chroot大快低
容器 (LXC/Docker)大(350+ syscalls)快低
gVisor中(53-68 syscalls)快中
Firecracker VM小(36 syscalls)中低

Linux 进程与 chroot

Unix/Linux 机制:chroot

chroot /new/root /bin/bash
// / 现在指向 /new/root

命名空间 (Namespaces)

命名空间提供了一种作用域机制,限制系统调用中可以命名的资源:

比 chroot 更好的隔离,适用于不同类型的资源。

Linux 容器

容器镜像 (OCI 格式)

cgroups

为什么命名空间/容器可能不够?

额外安全机制:seccomp-bpf

过滤进程可以调用的系统调用:

虚拟机 (VMs)

什么是虚拟机?

<代码>┌─────────────────────────────────┐
│  硬件                            │
│  ┌───────────────────────────┐  │
│  │  VMM (虚拟机监视器)        │  │
│  │  ┌─────────────────────┐  │  │
│  │  │  Guest Linux + 应用  │  │  │
│  │  └─────────────────────┘  │  │
│  └───────────────────────────┘  │
└─────────────────────────────────�代码>

虚拟机历史

为什么 VM 比容器更安全?

慢虚拟机:模拟硬件

快虚拟机:直接在 CPU 上执行

关键洞察:客户 OS 和应用使用相同的指令集(x86/RISC-V)

这称为 "trap-and-emulate"。

示例:RISC-V trap and emulate

Guest 用户代码执行 ecall 进行系统调用
CPU trap 到 VMM(ecall 总是产生 trap)
硬件保存 Guest 的 PC 在(真实)sepc 中

VMM trap 处理器:
  检查 guest 指令
  virtual sepc <- real sepc
  virtual mode <- supervisor
  virtual scause <- 8 "system call"
  real sepc <- virtual stvec
  sret:从 trap 返回(设置真实模式为用户)

VT-x/VMX/SVM:硬件支持的虚拟化

现代 Intel(和 AMD)CPU 在硬件中支持虚拟化:

术语

术语含义
Root mode运行主机
Non-root mode运行客户(内核 + 用户进程)
VMCSVM 控制结构:配置、保存/恢复客户特权状态
VMLAUNCH/VMRESUME主机 → 客户
VMCALL客户 → 主机

VT-x 的 EPT(扩展页表)

Guest VA ──(Guest PT)──→ Guest PA ──(EPT)──→ Host PA

第一层:Guest 页表映射 VA → Guest PA(通常)
第二层:EPT 映射 Guest PA → Host PA
VMM 设置 EPT 只有客户自己内存的映射
客户看不到也不能更改 EPT

客户可以自由更改页表,VMM 仍然通过 EPT 提供隔离。

Linux KVM

VM 的缺点

Firecracker 设计

Firecracker 实现:Rust

Firecracker VMM 运行在"监禁"进程中

gVisor 方案

在独立用户进程中重新实现 OS 系统调用接口:

gVisor 的缺点

安全对比:可访问的系统调用

平台允许的系统调用数
LXC (Docker)300+(阻止 44 个)
Firecracker36
gVisor53-68

各平台优缺点

平台优点缺点
Linux最简单,最少代码,最低开销 隔离弱
LXC隔离和容器抽象,灵活共享,近原生性能 共享内核,宽攻击面
gVisor强隔离,灵活共享和资源分配 性能开销
Firecracker强隔离,比 gVisor 更好的性能 粗粒度

要点总结

隔离是分层构建的

从 chroot 到命名空间到 seccomp 到 VM,每层增加安全性但增加开销。

VM 提供最强隔离

硬件支持的虚拟化(VT-x)让客户直接执行,EPT 提供内存隔离。

Firecracker 平衡安全与性能

最小设备集、Rust 实现、50K 行代码——比 QEMU 更安全。

gVisor 提供灵活隔离

用户空间内核实现,Go 编写,更细粒度的共享和资源分配。

测验

Q1:为什么容器比 VM 更容易被攻击?

Q2:VT-x 的 EPT(扩展页表)如何工作?

Q3:为什么 Firecracker 使用块设备而不是文件系统?

延伸阅读