☰
syz-testbed 完全指南:用 syzkaller 源码自建多版本性能对比与 bug 复现能力测试平台
2026/10/10 1:17:29 网站建设 项目流程
  • 网络安全
  • 开发工具
  • 质量保障

【免费下载链接】syzkaller

syzkaller is an unsupervised coverage-guided kernel fuzzer

项目地址:https://gitcode.com/gh_mirrors/sy/syzkaller
点击查看免费下载

本文基于 docs/translations/zh_CN/syz_testbed.md(英文原版见 docs/syz_testbed.md)及tools/syz-testbed/下的源码编写,介绍如何使用 syzkaller 官方自带的 syz-testbed 工具,自动化完成"检出多个 syzkaller 版本 → 分别构建 → 并行运行 syz-manager → 周期收集并汇总统计数据"的完整对比实验,同时也讲解如何用它验证不同版本对历史 bug 的复现能力。

syz-testbed 是 syzkaller 仓库自带的实验编排工具,它把"性能对比评估"从手工劳动变成一条命令。无论你是想量化某个开发分支对 fuzzing 效率的影响,还是想评估新版本对已知崩溃日志的复现成功率,都可以用它搭建并自动运行整个实验流程。读完本文,你将掌握 syz-testbed 的完整配置语法、实例调度原理、统计文件布局、Web 图表用法,以及 syz-repro 复现测试的配置方法。

一、syz-testbed 是什么

syz-testbed(源码位于 tools/syz-testbed/)是一个用于简化对不同 syzkaller 版本(或配置)进行性能对比评估流程的工具。它会自动完成以下工作:

  1. 检出(checkout)syzkaller 仓库的指定分支;
  2. 构建(build)每个检出版本;
  3. 并行运行多个syz-manager实例;
  4. 收集并汇总这些实例的统计结果,输出为 CSV 表格与 bench 文件。

从 testbed.go 的头部注释可以看到其设计初衷:"自动检出、构建并搭建多个 syzkaller 实例,这在评估新改动对 syzkaller 整体性能的影响时非常有帮助"。也就是说,它的典型场景是把master与某个开发分支放在同一套环境里跑同样的时间,最后对比谁发现的 bug 更多、覆盖率更高、执行速度更快。

二、配置 syz-testbed

syz-testbed 需要一个 JSON 配置文件,通过命令行参数-config传入。以下是一个完整的示例(来自官方文档):

{ "workdir": "/tmp/syz-testbed-workdir/", "corpus": "/tmp/corpus.db", "target": "syz-manager", "max_instances": 5, "run_time": "24h", "http": "0.0.0.0:50000", "checkouts": [ { "name": "first", "repo": "https://github.com/google/syzkaller.git", }, { "name": "second", "repo": "https://github.com/google/syzkaller.git", "branch": "some-dev-branch", } ], "manager_config": { "target": "linux/amd64", "kernel_obj": "/tmp/linux-stable", "image": "/tmp/kernel-image/trixie.img", "sshkey": "/tmp/kernel-image/trixie.id_rsa", "procs": 8, "type": "qemu", "vm": { "count": 2, "kernel": "/tmp/linux-stable/arch/x86/boot/bzImage", "cpu": 2, "mem": 2048 } } }

顶层配置项详解

对照 testbed.go 中的TestbedConfig结构体,各字段含义如下:

配置项JSON 类型说明默认值
namestringtestbed 的名称,会作为 syz-manager 实例名称的前缀"testbed"
targetstring要测试的应用,当前支持syz-manager与syz-repro两种"syz-manager"
max_instancesint同时运行的实例总数上限无(校验要求 ≥ 1)
run_timestring每个实例的运行时长(Go duration 字符串,如"24h"、"1h30m")"24h"
httpstringWeb 界面绑定的 IP 与端口,例如"0.0.0.0:50000"空(不启用)
benchcmpstringsyz-benchcmp可执行文件路径,用于 Web 图表自动从PATH查找
corpusstring初始 corpus 数据库文件路径,会复制到每个实例的 workdir空(不使用初始 corpus)
workdirstring所有检出与运行产物所在的根目录无(必填)
repro_configobjectsyz-repro 测试的配置(见下文第五节)默认crashes_per_bug = 1
manager_configobject基础 syz-manager 配置(与 syz-manager 的 config 字段一致)无
manager_modestring传递给 syz-manager 的-mode参数"fuzzing"
checkoutsarray要对比的版本列表,至少一个无

checkout 配置项

checkouts数组中的每个元素(对应 CheckoutConfig):

配置项说明
name该版本在 testbed 中的唯一名称,会用于目录命名(如run-first-0)与统计列名
reposyzkaller 仓库地址,例如https://github.com/google/syzkaller.git
branch要检出的分支;不填时默认为master
manager_config(可选)该 checkout 专属的 manager 配置片段,会与顶层manager_config合并

默认值与配置校验(源码视角)

syz-testbed 在读取配置前会先填充一组默认值,见 testbed.go:target默认"syz-manager"、run_time默认 24 小时、manager_mode默认"fuzzing"、repro_config.crashes_per_bug默认 1,并会尝试通过exec.LookPath("syz-benchcmp")在系统PATH中自动查找syz-benchcmp。

加载配置后执行checkConfig校验(testbed.go),主要规则包括:

  • name必须匹配正则^[0-9a-z\-]{1,20}$;
  • workdir不能为空,且会被自动转换为绝对路径并创建;
  • 若指定了corpus,该文件必须存在;
  • max_instances不能小于 1;
  • 若指定了benchcmp,该路径必须真实存在;
  • target必须是已注册的构造器之一(syz-manager/syz-repro);
  • 每个 checkout 的repo与branch会经vcs.CheckRepoAddress/vcs.CheckBranch校验,branch为空时自动设为master;
  • checkout 的name不能重复。

manager_config 的合并与实例化

顶层manager_config作为"基础配置",每个 checkout 的manager_config作为"补丁"与之合并(config.MergeJSONs),随后 syz-testbed 会把HTTP强制改为:0(避免多个实例端口冲突),见 MakeMgrConfig。

在每个实例启动前,还会对合并后的配置进一步打补丁(instance.go):自动填入name(即槽位名称)、workdir(实例专属目录)、syzkaller(指向该 checkout 的构建产物路径),并将最终配置写入实例目录下的manager.cfg文件。

三、工作流程:从检出到轮转运行

给定第二节的配置,syz-testbed 会执行以下操作(官方文档明确描述):

  1. 将https://github.com/google/syzkaller.git的master分支检出到/tmp/syz-testbed-workdir/checkouts/first/并构建;
  2. 将同一仓库的some-dev-branch分支检出到/tmp/syz-testbed-workdir/checkouts/second/并构建;
  3. 启动 3 个first实例和 2 个second实例(因为max_instances = 5,实例按轮询方式分配);
  4. 24 小时后(run_time为24h),停止这 5 个实例;
  5. 再创建 2 个first实例和 3 个second实例;
  6. 不断重复上述步骤,直到收到停止信号。

底层实现:Slot 与 Loop

从源码看,这个"创建 → 运行 → 归档 → 重来"的循环由两个核心函数实现(testbed.go):

  • Loop:为每个槽位(0 到max_instances-1)启动一个 goroutine,每个槽位固定占用一个实例名额;
  • Slot:在槽位内不断调用Target.NewJob领取新任务——syz-manager目标按**轮询(round-robin)**策略在 checkout 之间分配实例(见 targets.go),syz-repro目标则优先挑选对某个 checkout 执行次数最少的崩溃日志。

每个syz-manager实例实际以如下命令行启动(instance.go):

<workdir>/checkouts/<name>/bin/syz-manager \ -config <实例目录>/manager.cfg \ -mode fuzzing \ -bench <实例目录>/bench.txt

syz-manager实例达到run_time后会被优雅停止:先发送 SIGINT(os.Interrupt),若 1 分钟内没有自行退出则强制 Kill(instance.go)。正常结束的实例会被归档为RunResult并加入该 checkout 的已完成列表(checkout.go),而异常退出的实例会直接终止整个实验(见下文)。

停止条件

该工具在收到 SIGINT(例如按 Ctrl+C)或 SIGTERM 信号后停止,停止时会关闭所有槽位并等待全部实例退出(testbed.go)。此外,如果任意一个实例由于错误退出,也会导致整个实验停止——这是有意设计的保守策略:一旦某个实例异常,说明环境或配置可能有问题,继续跑下去的数据也没有意义。

目录结构

运行期间,workdir下的目录结构如下(来自官方文档):

/tmp/syz-testbed-workdir/ └── checkouts ├── first │ ├── run-first-0 │ │ ├── log.txt │ │ ├── manager.cfg │ │ └── workdir │ ├── run-first-1 │ │ ├── log.txt │ │ ├── manager.cfg │ │ └── workdir │ └── run-first-4 │ ├── log.txt │ ├── manager.cfg │ └── workdir └── second ├── run-second-2 │ ├── log.txt │ ├── manager.cfg │ └── workdir └── run-second-3 ├── log.txt ├── manager.cfg └── workdir

每个run-<checkout>-<编号>目录对应一个实例:log.txt是实例日志,manager.cfg是该实例最终的 syz-manager 配置,workdir是它的数据目录(corpus、crashes 等)。若配置了corpus,初始 corpus 会被复制到每个实例的workdir/corpus.db(instance.go)。此外每个实例目录还包含bench.txt,记录 syz-manager 按固定周期导出的统计快照(JSON 序列)。

四、Web 界面与 syz-benchcmp 图表

syz-testbed 自带一个简单的 Web 界面(源码见 html.go 与模板 templates/testbed.html),用于实时展示实验状态:

  • 当前活动实例与已完成实例的数量(按 checkout 分组);
  • 距实例停止的剩余时间;
  • 从各 syz-manager 收集到的最新统计数据;
  • 按 bug 标题、统计指标展示的各类表格。

要启用该界面,把http参数设置为 syz-testbed 要绑定的 IP 地址与端口,例如"http": "0.0.0.0:50000"。启动后即可在浏览器中访问,页面提供completed与all两个统计视图的切换(对应第四节的两种统计"视图"),以及 Statistics、Bugs、Bug Counts 等表格页签。

如果配置中的benchcmp参数指向syz-benchcmp可执行文件,Web 界面还能生成随时间或执行次数变化的各项参数曲线图。此时页面上的/graph路由会先调用syz-benchcmp(html.go),将其-all -over <x轴变量> -out <临时文件>参数与各 checkout 的平均 bench 文件组合执行,再把生成的图表返回给浏览器。

tools/syz-benchcmp/(benchcmp.go)本身是独立的 syz-manager 基准对比可视化工具,支持以下参数:

参数说明
-all对所有统计变量绘制图形;不指定时仅绘制coverage、corpus、exec total、crash types四项
-over <变量>作为 X 轴的统计变量,默认fuzzing(可理解为以执行次数为横轴)
-out <文件>将图形保存到文件而不是打开浏览器
-skip <秒数>跳过启动后前 N 秒的数据(默认 -30,即跳过前 20%)

五、统计输出:两种视图与文件布局

syz-testbed 提供两种统计"视图"(对应 testbed.go 中的GetStatViews):

  1. complete—— 仅包含已完成实例的数据(即运行满run_time的实例);
  2. all—— 还包含当前正在运行的实例的数据;来自已完成实例的统计会被"回退(对齐)"到与活动实例当前运行时长一致的时间点(stats.go 中的AlignedStatsTable按某个基准字段把各实例样本对齐)。

两种视图的统计每90 秒更新一次(testbed.go 中的周期 goroutine 调用SaveStats)。统计文件的整体布局如下:

$ tree -L 2 /tmp/syz-testbed-workdir/ /tmp/syz-testbed-workdir/ ├── stats_all │ ├── benches │ │ ├── avg_first.txt │ │ ├── avg_second.txt │ ├── bugs.csv │ ├── checkout_stats.csv │ └── instance_stats.csv ├── stats_completed │ ├── benches │ │ ├── avg_first.txt │ │ ├── avg_second.txt │ ├── bugs.csv │ ├── checkout_stats.csv │ └── instance_stats.csv └── testbed.csv

各文件的含义与生成逻辑如下:

  1. bugs.csv:包含所有运行实例发现的所有 bug(stats.go)。若某个 checkout 启动了多个实例(即count> 1),syz-testbed 会对它们发现的 bug 取并集(按 bug 标题去重,summarizeBugs逻辑见 stats.go),其目的是尽可能收集该 syzkaller 版本能够发现的全部 bug。Web 界面上对应的还有一张Bug Counts表,展示每个 bug 被多少实例发现及百分比。

  2. instance_stats.csv:保存各个 syz-manager 独立生成的统计(每行一个实例,按时间对齐后的最新样本)。

  3. checkout_stats.csv:将属于同一 checkout 的实例统计取平均(中位数)后保存(stats.go 的AvgStatRecords,按时间点逐个对齐并计算每个指标的中位数)。

  4. benches/avg_<checkout>.txt:把属于同一 checkout 的所有 syz-manager 的 bench 文件(参见 tools/syz-benchcmp)进行平均,保存为 JSON 行格式,可直接喂给syz-benchcmp绘制对比曲线。为了控制图表体积,长时间运行时采样点会被逐步抽样缩减到约 128~256 个数据点(stats.go 的SaveAvgBenchFile)。

  5. testbed.csv:testbed 级摘要表,包含每个 checkout 的 Running(运行中数量)、Completed(已完成数量)、Last started(最近一次启动距今时间)三列(testbed.go)。

此外,当target = "syz-repro"时,stats_*目录下会额外生成repro_success.csv、crepros_success.csv、repro_attempts.csv、repro_duration.csv等复现统计文件(见 targets.go)。

六、运行 syz-testbed

首先,检出 syzkaller 的最新版本:

$ git clone https://github.com/google/syzkaller.git

然后构建 syz-testbed:

$ cd syzkaller/tools/syz-testbed/ $ go build

编写并保存配置文件(例如保存为config.json),随后运行:

$ ./syz-testbed -config config.json

运行时会看到每个 checkout 的检出、构建、实例启动日志。停止 syz-testbed 进程会同时停止所有 syzkaller 实例,因此可以放心地在实验中途按下 Ctrl+C 结束整个实验。

几点实操提醒:

  • 需要提前准备好被测内核的bzImage、rootfs 镜像与 ssh 私钥(对应manager_config中的kernel_obj、image、sshkey、vm.kernel等字段),可参考 docs/linux/setup.md 与 docs/setup.md 准备 QEMU 虚拟机环境;
  • 若想复用现有语料,可用corpus字段指向一个已有的corpus.db;
  • workdir下已存在的 checkout 目录会导致启动失败(checkout.go 会检查路径是否已存在),换新实验前请清空 workdir 或换一个新目录。

七、测试 syz-repro:评估 bug 复现能力

syz-testbed 也可用于测试 syzkaller 的bug 复现能力。为此,在配置文件中将target属性设置为syz-repro。

此时可以指定崩溃日志文件的来源,二选一:

  • input_logs:指向一个包含崩溃日志的文件夹——syz-testbed 会遍历该目录并把每个文件都作为一个输入;
  • input_workdir:指向一个syzkaller 的 workdir——syz-testbed 会遍历其中发现的所有 bug,按规则挑选崩溃日志作为输入。

对应的配置段示例(官方文档):

"repro_config": { "input_workdir": "/tmp/some-syzkaller-workdir", "crashes_per_bug": 2, "skip_bugs": ["SYZFAIL", "no output", "corrupted", "lost connection"] },

repro_config各字段含义(对应 ReproTestConfig):

配置项说明
input_logs崩溃日志所在文件夹路径(与input_workdir互斥)
input_workdirsyzkaller workdir 路径,从中读取所有 bug 及其崩溃日志
crashes_per_bug每个 bug 随机选取多少份崩溃日志进行处理,不能小于 1,默认 1
skip_bugs需要跳过的 bug 标题正则表达式列表(skip_bugs是正则,不只是字面匹配)

以上述配置为例,syz-testbed 的处理流程为(targets.go):

  1. 遍历该 syzkaller workdir 发现的所有 bug(通过collectBugs读取 crash 存储);
  2. 跳过标题匹配SYZFAIL、no output、corrupted或lost connection这些正则的 bug;
  3. 对每个剩余 bug 随机选取 2 份崩溃日志(crashes_per_bug = 2),且同一 bug 的日志不会被重复选取;
  4. 检出并编译配置中指定的各 syzkaller 实例;
  5. 在每个被选中的崩溃日志上持续运行其syz-repro,直到工具被停止。

每个syz-repro实例以如下方式启动(instance.go):

<workdir>/checkouts/<name>/bin/syz-repro \ -config <实例目录>/manager.cfg \ -output <实例目录>/repro.txt \ -crepro <实例目录>/crepro.txt \ -title <实例目录>/title.txt \ <实例目录>/execution-log.txt

复现结果判定有一个值得注意的细节(instance.go):实例结束时会比对title.txt中解析出的 bug 标题与原始崩溃日志的标题,如果复现出的 bug 标题与原 bug 不一致,则该次复现视为失败(ReproFound与CReproFound均置为 false),避免"复现出了另一个 bug 却算作成功"的误判。若input_logs目录中某份日志解析不出崩溃报告,该日志也会被标记跳过(targets.go)。

syz-repro 模式下 Web 界面提供四类表格:Repros(各 bug 的复现成功率)、C Repros(已复现 bug 中能进一步生成 C 程序的比例)、All Repros(逐条列出每次复现尝试及其时长)、Duration(复现耗时分布),对应的 CSV 也会写入stats_*目录。

八、数据可信度与统计方法补充

syz-testbed 的统计表格并非简单的"最后一刻快照"对比,而是在源码层面做了较多严谨处理:

  • 样本聚合:同一时刻各实例的同一指标会聚合为一个样本集,表格单元格存的是样本对象而非单个数值(table.go 的ValueCell),展示时取中位数(sample.Median());
  • 对齐回退:all视图把已完成实例的统计回退到与运行中实例一致的时长(AlignedStatsTable),保证可比性;
  • 相对变化与显著性:Web 界面的统计表可指定base_column基准列,把其他 checkout 的数值表示为相对基准列的百分比变化(PercentChange),并尝试用 Mann–Whitney U 检验计算 p 值(sample.UTest),见 table.go 的SetRelativeValues及其单元测试 table_test.go。

九、总结

syz-testbed 把"多版本 syzkaller 对比实验"标准化为一个配置文件加一条命令:syz-manager目标负责自动化对比各版本的 fuzzing 产出(bug 集合、统计指标、bench 曲线),syz-repro目标负责自动化对比各版本的 bug 复现能力。配合其 Web 界面与syz-benchcmp图表,你可以在一个页面里同时看到实验进度、统计表格和性能曲线。

如果你的日常工作涉及 syzkaller 的性能回归检测、开发分支效果评估或复现能力验证,直接使用 tools/syz-testbed/ 即可——它省去的正是最容易出错且最耗时的部分:手工检出、构建、编排实例与汇总结果。

  • 网络安全
  • 开发工具
  • 质量保障

【免费下载链接】syzkaller

syzkaller is an unsupervised coverage-guided kernel fuzzer

项目地址:https://gitcode.com/gh_mirrors/sy/syzkaller
点击查看免费下载
上一篇:QtScrcpy:免费开源的安卓投屏控制,一插 USB 就能用
下一篇:5分钟快速掌握ViMax:AI智能代理视频生成的终极指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询