weltling/virtio-villain
GitHub: weltling/virtio-villain
一个从客户机侧对 VMM 的 virtio 设备模型进行协议级故障注入与合规性测试的框架,用于发现宿主机在处理不符合规范的输入时出现的崩溃和状态损坏问题。
Stars: 3 | Forks: 0
# Virtio Villain
一个系统化的测试框架,它启动一个最小化的 initramfs 客户机,并
从客户机端执行 virtio 共享内存接口,
旨在发现当客户机违反协议不变量时 VMM 中出现的 bug。
Virtio Villain 在对抗性驱动程序威胁模型(有时被称为恶意客户机或
不受信任的客户机模型)下,通过来自客户机端的格式错误且
不符合规范的输入,对宿主机 virtio 设备模型进行测试。每个测试
都是一个客户机端的协议级故障注入,违反了
规范中的“driver MUST”规则,并断言设备在处理它时
不会崩溃或损坏状态。一部分测试是严格意义上的一致性测试,用于断言规范强制要求的
寄存器能正确运行。这包括本文档后面描述的宿主机 sidecar
测试。通过在多个 VMM 上运行相同的测试套件并比较结果,该框架还可以作为
差异化测试的基础。
## 它的功能
- 证明 VMM 未能验证客户机提供的 virtqueue 输入
(描述符地址、长度、索引、标志、环形缓冲区条目)
- 触发逻辑 bug:由描述符链循环引起的无限循环,
由越界索引引起的 panic,由违反
内部不变量引起的断言失败
- 当在 VMM 上结合 ASAN 使用时:暴露仅在
协议违规时才会出现的内存安全问题
(UAF、堆缓冲区溢出、double free)
- 端到端测试整个设备模型栈(PCI 传输、队列
处理、设备特定的请求解析)
- 在 CI 中确定性地运行:相同的二进制文件、相同的内核、相同的结果
## 它做不到的事情
- 证明可利用性 - 触发崩溃并不能证明存在
可用的漏洞利用
- 覆盖 hypervisor 级别的 bug(KVM/MSHV、VFIO、IOMMU)
- 保证没有 bug - 测试通过仅意味着这些特定的违规
已被处理,未测试的输入仍是未知的
## 目标 VMM
目前支持 Cloud Hypervisor 和 QEMU,两者均作为 PCI 宿主机。
QEMU 还在 microvm 模式下被驱动以进行 MMIO 传输测试。
该框架与 VMM 无关,任何暴露 virtio PCI 或
MMIO 设备的 VMM 都可以通过在 `run` 中实现后端来添加。
## 架构
```
virtio-villain/
Makefile
run # launch VMM, collect results per test
bin/
init.c # harness: boot, discover, run tests, report, exit
lib/
virtio_pci.c/.h # modern virtio PCI transport
virtio_mmio.c/.h # virtio MMIO transport (microvm, ARM virt)
vring.c/.h # split vring setup and manipulation
vring_packed.c/.h # packed virtqueue support (VIRTIO_F_RING_PACKED)
pci.c/.h # PCI config space read/write via sysfs
util.h # mmap helpers, virt_to_phys, logging
tests/
test.h # test registration macros, result types
vring/ # T - split vring descriptor and ring violations
packed/ # P - packed virtqueue violations
pci/ # PCI - PCI transport specific violations
mmio/ # M - MMIO transport violations
state/ # S - state machine and multistep scenarios
admin/ # A - admin virtqueue commands
blk/ # B,Z - block and zoned block device violations
net/ # N - net device violations
console/ # C - console device violations
rng/ # RNG - entropy device violations
vsock/ # V - vsock device violations
balloon/ # L - memory balloon device violations
pmem/ # E - persistent memory device violations
mem/ # R - virtio-mem device violations
watchdog/ # D - watchdog device violations
iommu/ # I - virtio-iommu device violations
rtc/ # RTC - RTC / clock device violations
fs/ # F - virtio-fs device violations
```
测试二进制文件是一个静态的 C 可执行文件,在
最小化的 initramfs 内作为 PID 1 运行。它会发现 virtio PCI 设备,重置并
初始化传输,运行每个注册的测试,并
以通过/失败代码退出。
## 测试覆盖范围
测试用例源自 virtio 规范 v1.4 规范性
声明(OASIS 委员会规范 01,2026 年 4 月 8 日)。每个
测试都违反了特定的“driver MUST”要求,并检查
VMM 是否安全地处理了它。
### 传输和交叉切面
| 前缀 | 类别 | 规范 | 涵盖范围 |
|--------|----------|------|--------|
| T | 传输 (split vring) | 2.7 | 描述符链操作、OOB 索引、超大长度、avail/used ring 滥用、通知抑制、通知数据、间接表违规、生命周期违规、特性协商、按序完成 |
| P | 传输 (packed vring) | 2.8 | AVAIL/USED 标志操作、wrap counter 混淆、链长度溢出、间接表滥用、无效缓冲区 ID、事件抑制、单槽队列、packed 按序完成 |
| PCI | PCI 传输 | 4.1 | 队列配置违规、MSI-X OOB 向量、在禁用的队列上通知、cfg_data 能力读/写、配置生成竞争、BAR 边界、ISR 操作、共享内存能力探测、通知乘数 |
| M | MMIO 传输 | 4.2 | 错误宽度的寄存器访问、未定义的偏移量、缺少 QueueSel、保留的状态位、跳过 magic check、缺少 InterruptACK、只读和只写寄存器、重置、FeaturesSel、QueueNum、ConfigGeneration、SHMRegion 访问 |
| S | 状态机 / 生命周期 | 2.1-3.3 | 多步协商、部分重置恢复、无配置的队列重新启用、split 到 packed 重新初始化、背靠背重置、状态位操作、FEATURES_OK 拒绝、VERSION_1 协商、NEEDS_RESET |
| A | 管理命令 | 2.13 | 不带 LIST_USE 的命令、保留的状态码、截断的 payload、空的组列表、重置后的命令、响应溢出、零长度命令 |
旧版接口(规范 3.2)故意不在范围内。该
框架仅针对现代(1.0+)接口。
### 设备
状态图例:**yes** = 该框架中存在测试,**no** = 尚无
测试(在该框架中未实现,无论受测的
VMM 是否暴露该设备)。
| 前缀 | 规范 | 设备 | 已测试 |
|--------|------|--------|--------|
| N | 5.1 | 网络 | yes |
| B, Z | 5.2 | 块设备(包含 zoned 5.2.6.6) | yes |
| C | 5.3 | 控制台 | yes |
| RNG | 5.4 | 熵 (virtio-rng) | yes |
| L | 5.5 | 传统内存气球 | yes |
| K | 5.6 | SCSI host | reserved |
| U | 5.7 | GPU | reserved |
| - | 5.8 | 输入 | no |
| - | 5.9 | 加密 | no |
| V | 5.10 | Socket (vsock) | yes |
| F | 5.11 | 文件系统 (virtio-fs) | yes |
| - | 5.12 | RPMB | no |
| I | 5.13 | IOMMU | yes |
| O | 5.14 | 声音 | reserved |
| R | 5.15 | 内存 (virtio-mem) | yes |
| H | 5.16 | I2C | reserved |
| W | 5.17 | SCMI | reserved |
| Q | 5.18 | GPIO | reserved |
| E | 5.19 | 持久内存 (virtio-pmem) | yes |
| Y | 5.20 | CAN | reserved |
| - | 5.21 | SPI 控制器 | no |
| - | 5.22 | 媒体 | no |
| RTC | 5.23 | RTC / 时钟 | yes |
| D | 仅 ID 35 | Watchdog | yes |
| J | 仅 ID 40 | Bluetooth | reserved |
| - | 仅 ID 38 | Parameter Server | no |
| - | 仅 ID 39 | Audio Policy | no |
预留图例:**yes** = 存在测试;**reserved** = 为该设备预留了字母,但尚无测试;**no** = 尚未分配字母。字母 `X` 故意未使用,因为它在 PCI 能力讨论中与 MSI-X 在视觉上会发生冲突。所有未列出的单字母(目前没有)均可供未来使用。
上面的规范章节号追踪的是 v1.4 版本(CS01,2026 年 4 月 8 日)。v1.4 设备类型表预留了 ID 1 到 48,但只有 23 个
拥有规范性章节(5.1 到 5.23)。其余的,包括
Watchdog (ID 35)、Bluetooth (ID 40)、Parameter Server (ID 38)、
Audio Policy (ID 39),以及其他几个(9P、pstore、GPU 视频
编解码器、NitroSecureModule、RDMA、Camera、ISM、TEE、CPU balloon),
是为了互操作性而分配的,但其规范文本位于
单独的 OASIS 草案中或尚未落地。针对此类设备的 virtio-villain 测试
遵循受测 VMM 的既定行为。
### 超出范围
virtio-villain 故意不涵盖以下层面:
- **旧版 virtio (1.0-)** - 规范 3.2 - 仅关注现代版本
- **VFIO PCI passthrough** - 内核框架,客户机通过
KVM 与真实硬件通信,而不是与 VMM 模拟的设备通信
- **vfio-user** - 通过 UNIX socket 进行的用户空间设备仿真。
这是一个独立的协议,需要不同的测试环境,因为
VMM 是 socket 的*客户端*,而不是服务器
## 构建
```
make # produces ./init (static binary, all tests linked in)
make initramfs # packages init into initramfs.cpio.gz
```
initramfs 包含单个 `init` 二进制文件,并编译进了所有测试。要运行的测试通过内核命令行选择:
- `vv.test=T01` - 运行单个测试
- `vv.test=all` - 顺序运行所有测试(在 VMM 预期
不会崩溃时很有用)
- `vv.test=list` - 打印所有可用的测试 ID 并退出
由于成功的测试也可能会导致 VMM 崩溃,`run` 会为每个测试生成一个全新的 VM,并收集跨调用的结果。对于 MMIO 传输
测试(M 前缀),使用 `--mmio` 配合 QEMU 二进制文件以针对
microvm 机器类型运行。
列出宿主机上可用的测试(输出会自适应终端宽度,
使用 `~` 截断过长的描述):
```
./init --list
```
列:测试 ID、描述、规范版本、规范章节。
该二进制文件使用 musl 构建,并为 initramfs 进行了剥离。每个测试
会增加大约 200-500 字节的代码,因此即使有 300 多个测试,镜像也能保持在
4MB 以下。对于调试,请在宿主机上保留未剥离的二进制文件并
针对 VMM 崩溃地址使用 `addr2line`。
## 测试结果
每个测试报告五种结果之一:
- **PASS** - 设备消耗了请求并推进了 used ring。
对于格式错误的输入,这意味着 VMM 处理了它而没有崩溃
- **FAIL** - 设备做了明显错误的事情。仅由
带有自定义验证逻辑的测试发出
- **REJECT** - 设备正确地保持静默,没有推进
used ring,但保持存活且响应。这是无效输入应被静默丢弃时的理想结果
- **WEDGED** - 设备停止响应且不再健康。
device_status 报告 DEVICE_NEEDS_RESET 或零,或者随后的
格式正确的请求被忽略。通常 VMM 队列工作
线程由于格式错误的输入而死亡。恢复需要
拆除设备并通过驱动程序 unbind 和
rebind 重新创建它,或者热拔和热插。通过
device_status 进行的普通 virtio 重置不能保证复活已经退出的线程
- **SKIP** - 缺少所需的设备或无法满足前提
条件,例如未提供 packed 队列
PASS 和 REJECT 是可接受的结果。WEDGED 表示 VMM
处理违规时不优雅,从
那时起如果没有操作员干预,设备将无法使用。FAIL 表示存在 VMM bug,
例如崩溃或核心转储。如果
有任何 FAIL 或 WEDGED,`run` 脚本将以非零状态退出。
## 宿主机端 sidecar
一些测试需要在 **宿主机** 端执行某些操作,同时
客户机正在运行。热插、热拔、保存和恢复、快照、
设备暂停、实时配置更改。这些动作根据定义
存在于客户机之外。该框架通过放置在 C 测试旁边的可选
Python 文件支持它们,该文件以相同的数字
ID 命名。当 `run` 启动测试时,它会寻找 `tests//*.py`。如果
存在,则导入该文件,并在后台线程中为该测试的生命周期
调用其 `run(ctx)` 函数。
sidecar 接收一个上下文对象,其中包含 VMM 后端名称、
VMM PID、一个私有临时目录、API socket 路径、磁盘路径、
一个 logger、一个共享输出缓冲区读取器、一个 stop event,以及一个
与 Cloud Hypervisor 的 `ch-remote` 及 QEMU 的 QMP 通信的
`vm_api(command, args)` 助手。sidecar 可以使用 `ctx.wait_text("[vv]")` 等待客户机输出,
在 `ctx.tmpdir` 中生成文件,
并通过 `ctx.vm_api("add-disk", [...])` 驱动宿主机。当后端
不支持该操作或 API socket 被禁用时,sidecar
会干净地退出,在这种情况下,客户机报告的是 SKIP 不是
FAIL。
### 为什么这与 VMM 集成测试不同
VMM 已经拥有涵盖热插、
保存和恢复以及类似的宿主机驱动场景的集成测试套件。这些套件使用
**内核的** `virtio_pci` 和特定于设备的驱动程序来验证
结果。内核驱动程序在设计上是宽容的。它会重试,会忽略
可选功能,会应用特定于设备的变通方法,会接受
一个可用的寄存器子集,并且只要
文件系统挂载且链路通过数据包,它就认为设备是健康的。一大
类设备端的 bug 能在这种测试中存活。格式错误的能力链、
热添加功能上错误的 `notify_off_multiplier`、从先前实例
遗留下来的陈旧 `device_status`、被忽略的
`queue_enable`、不能完整往返的 `FEATURES_OK` 回显、新设备上损坏的
`device_feature_select` 多路复用器。
Virtio Villain 完全绕过了内核驱动程序。init 二进制文件
以 `initcall_blacklist=virtio__init` 运行,自己遍历 PCI
能力列表,对于受测设备,根据
`notify_bar_base + notify_cap.offset + queue_notify_off *
notify_off_multiplier` 推导出 doorbell 地址,写入完整的重置
和特性协商序列,手动编程每个队列的 GPA,
并对确切的规范规定值进行断言。Sidecar 测试将同样的从零开始的驱动程序
应用于 **在启动时不存在** 的设备,而这是最有趣的 VMM 回归问题隐藏的地方。Sidecar
测试回答了与集成测试不同的问题。集成测试问
的是“内核在热插后能挂载磁盘吗”。Sidecar 问的是
“当从零开始的驱动程序去探测时,热添加功能上每一个规范规定的 virtio 寄存器
行为是否正确”。
对于结合了宿主机操作和内核无法做出的精确客户机级断言的测试,Sidecar 也是
理想之地。
应该保持 `queue_notify_off` 不变的保存和恢复,应该
在热拔之后进行热插且不留残余
`device_status` 位的操作,在传输中的 I/O 期间拍摄快照
且应确定性耗尽 used ring。其中的每一个都是位于
同一目录下的一个 C 测试加上一个 Python sidecar。
## 快速开始
```
make initramfs
./run -m ./cloud-hypervisor # all tests
./run -m ./cloud-hypervisor T01 # single test
./run -m ./cloud-hypervisor T01 T03 B01 # subset
./run -m ./cloud-hypervisor -j4 # 4 parallel VMs
```
`-m` 接受 VMM 二进制文件的路径。你需要自行构建或安装
它。如果省略 `-k`,内核会自动获取到 `target/` 中,这会使用来自 GitHub
发布的 Cloud Hypervisor 客户机内核。传递 `-k /path/to/vmlinux` 以使用你自己的内核。
写入终端时输出是彩色的:
- $\textcolor{green}{\textsf{PASS}}$ 绿色
- $\textcolor{red}{\textsf{FAIL}}$ 红色
- $\textcolor{magenta}{\textsf{REJECT}}$ 洋红色
- $\textcolor{orange}{\textsf{WEDGED}}$ 黄色
- $\textcolor{cyan}{\textsf{SKIP}}$ 青色
底部的进度条显示当前测试和运行总计。
通过管道输出到文件或通过 `| cat` 来抑制颜色。
### 常见变体
```
./run -m ./cloud-hypervisor -k /path/to/vmlinux # custom kernel
./run -m ./cloud-hypervisor -d qcow2 # use qcow2 backing
./run -m ./cloud-hypervisor M01 # MMIO test, auto launches QEMU microvm if needed
./run -m ./qemu-system-x86_64 # QEMU backend
./run -m ./cloud-hypervisor -v T01 # verbose, full test output
./run -m ./cloud-hypervisor -c T01 # forward guest console to stdout
```
### 依赖项
构建:
- 能够生成静态 x86_64 二进制文件的 C 编译器(gcc、
clang 或 musl-gcc 均可)
- `make`
- `cpio`、`gzip`(用于 initramfs 目标)
运行:
- Python 3(无 pip 依赖)
模糊测试(可选,仅在需要 `run-fuzz minimize` 和 `cov-report` 时需要):
- 与用于构建覆盖插桩 VMM 的工具链相匹配的 `llvm-profdata` 和 `llvm-cov`
### VMM 设置
测试框架可以针对任何暴露 virtio PCI 设备的 VMM 运行。
你唯一必须提供的是 VMM 二进制文件本身,通过
`-m` 传递给 `run`。为了获得更深层次的 bug 覆盖,请使用 ASAN 构建它(Rust
VMM:`RUSTFLAGS="-Zsanitizer=address"`,C/C++ VMM:
`-fsanitize=address`)。
其他所有内容 `run` 都会在首次调用时自动安排:
- 客户机内核。如果未指定 `--kernel`,`run` 会从最新的 Cloud Hypervisor 内核发布版中下载
`vmlinux-x86_64` 并将其缓存在
`target/` 下。要使用你自己的内核,请传递
`--kernel /path/to/vmlinux` 并确保它使用
`initcall_blacklist=virtio_blk_init` 引导,以便客户机不会
在测试工具之前声明 virtio 块设备。`run`
脚本会为你追加此参数。
- initramfs。由 `make initramfs` 构建一次,并在测试中重复使用。
- 每个测试的 backing 文件。一个全新的磁盘镜像、pmem 区域,以及
适用的 vsock socket 和 virtiofs 共享会在
每个测试的临时目录中创建,然后删除。磁盘格式
可通过 `--disk-format` 选择,默认为 raw,raw 镜像
使用 `truncate`,qcow2、vhd 和 vhdx 使用
`qemu-img`,因此如果你想使用非 raw 格式,请安装 `qemu-utils`。
- 可选助手。如果 `virtiofsd` 在 `PATH` 中,则会自动为
virtio-fs 测试启动它,否则将跳过那些测试。
为了手动连接所有这些,例如在集成到
自定义的测试框架时,等效步骤是:构建 VMM,获取
内核,运行一次 `make initramfs`,每个测试分配一个 16 MiB 的磁盘镜像和
128 MiB 的 pmem 文件,并将内核、initramfs、磁盘、pmem
和 `vv.test=NAME` cmdline 参数传递给 VMM。阅读
你针对的后端的 `run.build_cmd` 是获取确切命令行的最快捷径。
## 模糊测试
除了确定性测试套件外,该存储库还包含一个
覆盖率引导的变异模糊测试器,它生成随机的 virtqueue 输入
并针对 VMM 启动它们以寻找崩溃。
### 组件
- `bin/fuzz.c` - 最小化客户机(PID 1),从其 `.fuzz_input` ELF 节读取一个 4096 字节的 blob,
根据编码的描述符链构建 vring,唤醒
队列,然后重启
- `lib/fuzz_input.h` - blob 格式:紧凑的头部(queue_size、
num_descs、avail_idx、avail_count)、描述符结构(len、flags、
next)、avail ring 条目和原始 payload 字节
- `run-fuzz` - Python3 编排器,它变异 blob,将它们
修补进模糊测试客户机 ELF 中,启动 VMM,并对结果进行分类
### 用法
```
make fuzz # build the fuzz guest ELF
make fuzz-initramfs # package into initramfs
./run-fuzz fuzz --vmm ./cloud-hypervisor # auto downloads kernel into target/
./run-fuzz fuzz --vmm ./cloud-hypervisor --kernel path/to/vmlinux
./run-fuzz fuzz --vmm ./cloud-hypervisor -n 1000 # 1000 iterations
./run-fuzz fuzz --vmm ./cloud-hypervisor -j 8 --cpus 1 # 8 parallel VMs
./run-fuzz fuzz --vmm ./cloud-hypervisor --no-coverage # skip llvm-cov
```
默认值为 10000 次迭代、1 个作业、1 个 vCPU、128M 客户机 RAM,以及
3 秒的 VMM 启动超时。语料库输入位于 `target/corpus/` 中,
崩溃 blob 位于 `target/crashes/` 中。这两个目录都被 gitignored 并且
在多次运行之间持久存在。
其他子命令。
```
./run-fuzz seed # seed corpus from existing tests
./run-fuzz decode target/crashes/crash_*.bin # print blob contents
./run-fuzz replay --vmm ./cloud-hypervisor target/crashes/... # reproduce one or more crashes
./run-fuzz triage --vmm ./cloud-hypervisor # group crashes by error class
./run-fuzz minimize --vmm ./cloud-hypervisor # drop corpus entries with redundant coverage
./run-fuzz cov-report --vmm ./cloud-hypervisor # summarize edges hit by the corpus
```
`minimize` 和 `cov-report` 需要一个带有覆盖率插桩的 VMM 以及
“依赖项”下列出的 `llvm-profdata` 和 `llvm-cov` 工具。
### 变异策略
`run-fuzz` 从以下集合中均匀随机地
在每次迭代中选择一种策略。
blob 格式(`lib/fuzz_input.h`)是一个
4096 字节的记录,包含头部、描述符表、avail ring
和原始 payload 区域。
- `bit_flip`, `byte_arith`, `interesting_16` - 通用的字节和字
级别的变异
- `endian_swap`, `zero_fill_region`, `payload_noise` - 对 payload 区域的结构性
噪声
- `header_corrupt`, `queue_size_mutate` - 重写 blob 头部,使得
客户机构建一个格式错误的队列
- `desc_flags`, `desc_addr_mutate`, `grow_desc`, `shrink_desc`,
`duplicate_desc`, `chain_shuffle` - 变异描述符表
(标志、地址、长度、顺序、多重性)
- `avail_corrupt`, `avail_ring_replay` - 损坏或重放 avail
ring 条目
- `indirect_inject` - 将常规描述符转换为间接
表引用
- `splice_corpus` - 将另一个语料库 blob 的字节拼接到
当前 blob 中
- `multi_strategy` - 按顺序应用上述 2 或 3 种策略
### 覆盖率引导
当 VMM 使用覆盖率插桩构建时,`run-fuzz`
在每次运行后收集 `llvm-profdata` / `llvm-cov` 输出,以
识别到达新代码路径的输入。这些输入会被添加到
语料库中以供进一步变异。在没有插桩的情况下,模糊测试器以盲目变异模式运行。
#### 为模糊测试构建 Cloud Hypervisor
仅在使用稳定版工具链时支持覆盖率。
```
cd cloud-hypervisor
RUSTFLAGS="-C instrument-coverage" cargo build
```
仅在 nightly 版本上支持 AddressSanitizer。捕获 unsafe 代码中的
内存安全 bug、UAF、OOB 和 use after poison。
```
RUSTFLAGS="-Zsanitizer=address" \
cargo +nightly build -Zbuild-std --target x86_64-unknown-linux-gnu
```
单个二进制文件不能同时携带覆盖率插桩和
AddressSanitizer。它们共享 LLVM 运行时钩子并会发生冲突。
推荐的方法是进行两次单独的构建,每个信号一次,作为单独的活动
运行。SanitizerCoverage 是 `-C
instrument-coverage` 的替代方案,它可以在单个二进制文件中与 ASan 一起使用。
```
RUSTFLAGS="-Zsanitizer=address -C passes=sancov-module" \
cargo +nightly build -Zbuild-std --target x86_64-unknown-linux-gnu
```
确保 `rust-src` 可用。
```
rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
```
| 构建 | 捕获内容 | 开销 |
|-------|----------------|----------|
| `-C instrument-coverage` | panic、断言、逻辑 bug | ~3x |
| `-Zsanitizer=address` | unsafe 块中的内存安全 | ~10x |
`run-fuzz` 脚本会自动向
VMM 传递 `--seccomp false`,因为覆盖率分析在退出时会生成文件,这需要
默认 seccomp 白名单中不存在的系统调用。
确保 `llvm-profdata` 和 `llvm-cov` 与 `rustc` 使用的 LLVM 版本匹配。
```
rustup component add llvm-tools-preview
```
如果版本匹配,也可以使用系统 LLVM。
### 崩溃分类
`target/crashes/` 中的每个文件都是一个原始的 4096 字节 blob。要进行调查:
```
./run-fuzz decode target/crashes/crash_*.bin # print blob contents
./run-fuzz replay --vmm ./cloud-hypervisor target/crashes/crash_XXXX.bin # reproduce
./run-fuzz triage --vmm ./cloud-hypervisor # group all by error class
```
`decode` 打印每个 blob 的队列配置、描述符链(长度、标志、
next 指针)、avail ring 条目和 payload 统计信息。
`replay` 将每个 blob 修补进模糊测试客户机,启动 VMM,并
报告它是崩溃了还是干净地退出了。对于慢速的 VMM,请使用 `--timeout 10`。
`triage` 会重放 `target/crashes/` 中的每个 blob,并根据
观察到的 panic 消息或信号对它们进行分组,这会将数十个
触及相同根本原因的输入合并到一个桶中。
在修复了 VMM bug 之后,重放所有崩溃以确认哪些不再复现,
许多 blob 通常会触发相同的底层问题。
## 发现的 Bug
由该工具发现的 Cloud Hypervisor 上游修复子集:
- [#8388](https://github.com/cloud-hypervisor/cloud-hypervisor/pull/8388) block: 修复 WriteZeroes 扇区算术溢出
- [#8295](https://github.com/cloud-hypervisor/cloud-hypervisor/pull/8295) virtio-devices: 发出 NEEDS_RESET 信号
- [#8272](https://github.com/cloud-hypervisor/cloud-hypervisor/pull/8272) virtio-devices: 遵守 BAR 访问的 PCI CFG cap.length
- [#8238](https://github.com/cloud-hypervisor/cloud-hypervisor/pull/8238) virtio-devices: 修复 VIRTIO_PCI_CAP_PCI_CFG 的 cap_len
- [#8232](https://github.com/cloud-hypervisor/cloud-hypervisor/pull/8232) vm-virtio: 添加集中式描述符范围验证
- [#8190](https://github.com/cloud-hypervisor/cloud-hypervisor/pull/8190) virtio-devices: 激活时要求至少有一个就绪队列
- [#8185](https://github.com/cloud-hypervisor/cloud-hypervisor/pull/8185) virtio-devices: 在设备特定配置读取时增加 config_generation
- [#8177](https://github.com/cloud-hypervisor/cloud-hypervisor/pull/8177) virtio-devices: balloon: 限制 inflate 和 deflate 描述符长度
- [#8166](https://github.com/cloud-hypervisor/cloud-hypervisor/pull/8166) virtio-devices: net, block: 移除每个处理程序的 NEEDS_RESET 簿记
- [#8142](https://github.com/cloud-hypervisor/cloud-hypervisor/pull/8142) net: 防止工作线程在格式错误的客户机描述符上死亡
- [#8138](https://github.com/cloud-hypervisor/cloud-hypervisor/pull/8138) virtio-devices: 在表访问前检查 MSI-X 向量边界
- [#8131](https://github.com/cloud-hypervisor/cloud-hypervisor/pull/8131) pci: msix: 用优雅的错误替换无效表写入时的 panic
- [#7949https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7949) virtio-devices: block: 修复 writeback 模式更新流程
- [#7921](https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7921) virtio-devices: block: 在同步回退路径中使用特定于错误的状态
- [#7858](https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7858) virtio-devices: block: 从拓扑导出 discard 对齐方式
- [#7852](https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7852) virtio-devices: block: 填充 discard 和 write zeroes 配置
- [#7805](https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7805) virtio: 规范合规性修复
全部位于 cloud-hypervisor/cloud-hypervisor,全部已合并。
## 致谢
测试开发得到了 GitHub Copilot 的加速,它协助
生成规范驱动的故障注入案例、搭建新设备
类别的脚手架,并在 virtio 规范
范围内保持覆盖率。
## 维护者
Anatol Belski
这是一个个人开源项目。它不隶属于、
不受认可或受赞助于任何雇主,且贡献和
发布不代表任何组织。
## 许可证
Apache-2.0
标签:Cloud Hypervisor, Fuzz测试, QEMU, Virtio, 内联执行, 客户端加密, 测试框架, 虚拟化, 身份验证强制