## Ghost in the Android Shell: Pragmatic Test-oracle Specification of a Production Hypervisor

> Kayvan Memarian, Ben Simner, David Kaloper-Meršinjak, Thibaut Pérami, Peter Sewell (University of Cambridge)

### 一、背景

在现代操作系统和虚拟化平台中，**hypervisor（虚拟机监控器）** 是实现安全隔离的核心组件。本文的讨论的对象 **pKVM**（protected KVM）是 Google 在 Android 上部署的生产级 hypervisor，用于保护 Android host 与 guest 虚拟机之间的隔离。传统的 hypervisor 开发通常依赖**测试 + 手工推理**；而要实现严格的安全性保障，过去的做法是**形式化验证**，但如 seL4、CertiKOS、IronFleet 等方法对大多数生产环境对开发团队来说成功过高。因此，本文提出了一种更轻量的中间方案：通过“**可执行规范 + 运行时测试**”的方式构建对生产 hypervisor 的信任。

### 二、问题与挑战

要在真实的生产 hypervisor（pKVM）中使用“定义规范 + 运行时测试”方法，存在一系列的挑战：

- pKVM 的行为与底层 Arm 硬件架构（页表、异常处理）密切绑定，规范必须能描述这种隐式行为（如硬件页表 walk）。
- 多个硬件线程可能同时进入 hypervisor；规范需要正确处理锁和状态的所有权。
- 规范需要松弛，例如，pKVM 对 host 内存映射采用按需映射机制，无法精确指定每一步行为；必须在规范中抽象掉不必要的实现细节。
- 运行环境受限，由于 pKVM 运行在 EL2，无常规测试工具（如 coverage、调试器）可用，使用随机的错误输入可能导致整个系统崩溃。
- 规范需要直接在 C 语言中实现（pKVM 所用语言），而不是在 Coq、Lean 之类的形式化语言中；C 缺乏代数数据类型、纯函数子集、pattern matching、泛型等高层特性。

### 三、设计

论文的核心设计是定义“可执行的 test-oracle 规范”，从而能够根据规范：1. 生成符合运行环境规范的随机测试输入，避免纯随机的测试输入导致系统完全 crash；2. 通过 oracle 得到运行测试后 pKVM 的状态，与实际 pKVM 运行后的状态进行比较进行测试。

1. 定义一个抽象状态（Ghost state），作为 hypervisor 真实状态的高层数学模型；ghost state 包含如下的信息。在抽象时过滤掉内存分配、页表内部结构等与外部可观察行为无关的实现细节。
	- pkvm 自身 stage-1 映射
	- host stage-2 映射
	- 每个 VM 的 stage-2 映射与元信息
	- 全局常量（物理 CPU 数、地址偏移等）
	- 每个 CPU 的本地状态
	![[251014-144626.png]]
2. 通过一组抽象函数在运行时从 pKVM 的真实状态生成 ghost state，同时保证抽象与锁的持有状态严格对应（只有在持锁时才能抽象相关状态）。
3. 使用 C 语言实现 hypercall 的“纯函数”规范，在 hypercall 执行前后分别记录 pre/post ghost state，然后比较与规范计算结果是否一致。例如 `host_share_hyp`：
	- 输入：抽象 pre-state + 调用参数 + 环境信息
	- 输出：抽象 post-state
	- 只依赖 ghost state，不依赖真实实现
4. 松弛规范与非确定性：
	- 对于内存不足错误（`ENOMEM`）等不影响核心语义的行为，规范不强制实现；
	- 规范参数化于实现返回值，以支持松弛匹配；
	- 对 host 与 pKVM 共享内存的交互，通过记录实际读取的值来消除非确定性。
5. 检查抽象状态在 hypercall 之间不发生“锁外干扰”；检查页表 footprint 不被越界修改，实现 separation logic 风格的隔离保证。

### 四、测试与评估

本工作通过修改 Linux 内核引入 “hyp-proxy” 接口，使 pKVM 的 hypercall 能在用户态直接调用，并配合自研的覆盖率工具，对实现与规范的行、分支和函数进行监测。测试主要包括三类：
1. 手写测试，共 41 个用例，覆盖所有 hypercall 的正常与错误分支
2. 随机测试，基于 ghost state 生成高质量随机输入以避免系统崩溃
3. 合成 bug 测试，通过注入错误验证测试框架的有效性
实际测试中共发现 5 个 pKVM 的真实 bug，包括 allocator 内存对齐、memcache 越界访问、竞争条件和 IO 映射重叠等问题，其中第 4 个是通过规范对比发现的。此外，规范规模约 8.4K 行，接近实现的 11K 行，在 QEMU 环境下内存占用约 18MB，启动时间增加 3.2 倍，测试时间增加 11.5 倍，测试速率达每小时约 20 万次 hypercall。作为总结，本工作提出并验证了一种用“可执行规范”动态对比实现的轻量级验证方法，在不依赖繁重形式化工具的前提下，对生产级 hypervisor（pKVM）实现了实用、低成本的高可信度保障。
