做 Linux 内核 Bug 排查时,最让人头疼的往往不是“没有信息”,而是信息太散。

syzbot 每天都在发现和分类大量 Linux 内核崩溃、死锁和内存安全问题。它给出的材料其实很丰富:崩溃报告、控制台日志、内核配置、C/syz 重现代码、相关讨论链接。但这些材料大多还是原始数据。真正困难的部分,比如根因分析、本地复现、验证补丁、整理邮件、提交修复,仍然需要人一点点把线索串起来。

SyzForge 想解决的,就是这段从“看到一个 syzbot 报告”到“完成一次可追溯工程调查”之间的损耗。

它不是想替代内核开发者的判断,也不是简单把几个脚本包在一起,而是希望把 syzbot/syzkaller 相关的分析链路重新整理成一条清晰、可重复、可审计的流水线:让原始报告变成结构化证据,让复现环境变成确定性工作区,让补丁讨论和发送准备变成可追踪的工程步骤。

换句话说,SyzForge 是一个用于 Linux 内核 Bug 排查的开源多 MCP(Model Context Protocol)系统。它的目标很直接:把无尽的 syzbot 报活,变成可以被 Agent 和工程师共同推进的实际工作。

为什么需要 SyzForge

在真实的内核 Bug 调查里,一个 crash 从 syzbot 上出现,到我们真正理解它,通常要经过很多零散动作:

  • 打开 syzbot 报告,确认目标内核和崩溃类型

  • 下载 crash report、console log、kernel config 和 reproducer

  • 准备本地源码和构建环境

  • 在指定 commit 上编译内核

  • 编译 C reproducer

  • 启动 QEMU 并运行复现程序

  • 对比 before/after 结果

  • 阅读调用栈和相关源码

  • 查找社区里是否已有讨论或补丁

  • 编写、验证、整理并提交修复

这些事情单独看都不陌生,但连在一起,就很容易变成一场注意力消耗战。尤其是当多个 Bug 并行推进,或者一个问题隔了几天再回来继续看时,前后文很容易丢失。

SyzForge 的设计背景就是这个痛点:工具已经不少,但工作流仍然断裂。我们需要的不是更多孤立命令,而是一个能承接完整调查过程的系统。

2026/08/halo_gwwglyo.webp

架构:三个 MCP 服务器,一个目标

2026/08/halo_rsmrxqs.webp

SyzForge 由三个独立的 MCP 服务器组成:

  • SyzLens:负责证据采集

  • KernelLab:负责内核构建与复现

  • KernelMail:负责社区讨论和补丁邮件工作流

它们共享一个本地数据工作空间,但职责边界非常清楚。每个服务器只做自己确定性的工程动作,不越界做主观判断。

这也是 SyzForge 里最重要的一条设计原则:

MCP 工具执行确定性的工程动作并返回可追溯的数据。Agent 负责主观推理。

也就是说,SyzLens 不判断根因,KernelLab 不决定该测试什么,KernelMail 不决定该发什么补丁。真正需要推理的部分,比如阅读崩溃栈、理解源码、评估补丁正确性、决定下一步调查方向,都由上层 Agent 完成。

这个边界让系统更稳,也更容易审计。你可以清楚看到每一步输入是什么、输出是什么、文件从哪里来、日志怎么产生、补丁为什么被提出。

SyzLens:系统的眼睛

2026/08/halo_ikilufp.webp

SyzLens 是 SyzForge 的证据采集层。它负责连接 syzbot 仪表盘,获取 Bug 详情、崩溃报告、控制台日志、内核配置、重现代码以及社区讨论页面。

它不做根因推断,也不做优先级判断。它的职责很纯粹:把事实收集完整,并把这些事实缓存下来。

这件事看起来简单,但非常关键。因为一旦证据被稳定保存到本地,后续调查就不再依赖重复访问 syzbot,也不容易受到限流、页面变化或临时网络问题影响。同一个 Bug 可以被离线审查,也可以被打包带到另一台机器上继续分析。

SyzLens 的关键能力包括:

  • 按目标、群组和关键词搜索 syzbot Bug,例如 upstream、android-5-15、linux-6.6,或者 open、fixed、invalid 等状态

  • 下载指定 Bug 的崩溃报告、控制台日志、内核配置和 C/syz 重现代码

  • 将工件存入稳定的 per-bug 目录

  • 获取 Google Groups 和 lore.kernel.org 相关讨论页面

  • 保存完整 HTML,方便后续追溯

  • 生成工件清单,记录来源、时间戳和 SHA256 校验和

  • 将 Bug 证据打包为 ZIP,方便离线传输

当用户要求 SyzForge 调查一个 syzbot Bug 时,SyzLens 通常是第一个被调用的组件。

KernelLab:把复现变成工程工作区

证据收集完之后,真正费力的部分才开始:准备内核、构建镜像、编译 reproducer、启动 QEMU、运行复现并保存日志。

KernelLab 负责这部分工作。

它会为每个 syzbot Bug 准备一个确定性的、自包含的内核复现工作区。这个工作区不是随手跑出来的一堆临时文件,而是一个可重复、可检查、可比较的 case。

KernelLab 做的事情包括:

  • 在指定 commit 上检出 Linux 内核源码

  • 应用 syzbot 提供的内核配置

  • 构建 bzImage

  • 编译 C 重现程序

  • 生成 QEMU 启动脚本

  • 启动 guest 环境并运行 reproducer

  • 捕获串口控制台日志、QEMU 输出和 guest dmesg

  • 支持 before/after 复现结果对比

每一项调查都会形成独立 case,默认放在类似下面的路径中:

data/workspaces/<target>/<case-id>/

case 中会包含源码树、构建输出、证据目录和复现结果。这样做的好处是,调查过程不会散落在机器的各个角落。过一段时间回来继续看,或者交给同事接手,都能找到完整上下文。

KernelLab 同样保持克制:它不会判断修复方案是否正确,也不会决定下一步该测什么。它只负责把复现和验证这部分工程动作做扎实。

KernelMail:把社区协作流程管起来

内核 Bug 的修复并不止于本地验证。真正要进入 Linux 内核社区,还需要处理邮件线程、补丁格式、收件人、主题、回复关系和发送计划。

KernelMail 负责这一段流程中可以确定化的部分。

它不会替 Agent 决定发什么补丁,也不会擅自发送邮件。它做的是记录线程元数据、管理本地草稿、生成 git send-email 计划,并确保这些动作都是可追踪、可检查的。

KernelMail 的关键能力包括:

  • 在 case 工作区下记录社区讨论线程

  • 将线程消息保存为可追溯的 RFC822 对象

  • 创建带有正确 header、收件人、主题和正文的本地回复草稿

  • 验证补丁文件后生成确定性的 git send-email 计划

  • 将发送计划写入脚本,供本地执行和记录输出

  • 读取 SyzLens 导入的讨论 HTML 或文本工件,并返回相关片段和链接

默认情况下,KernelMail 处在安全状态。所有真实邮件发送动作都需要明确确认。

这点很重要。因为在自动化和 Agent 参与越来越多的工作流里,边界必须清楚:工具可以准备,Agent 可以推理,人可以确认,系统不能越权。

Agent:负责把线索连起来

三个 MCP 服务器是执行层,真正理解“为什么这个 Bug 重要”“下一步该怎么做”的,是上层 Agent。

SyzForge 的工作流大致是这样:

  1. 证据分诊
    从一个 syzbot Bug URL 开始,Agent 调用 SyzLens 获取所有证据,验证工件清单,然后导入 KernelLab。

  2. 复现实验室
    KernelLab 构建内核、编译 reproducer、启动 QEMU 并运行复现。Agent 读取 before/after 结果,决定是否继续。

  3. 补丁分析与编写
    Agent 阅读崩溃栈、控制台日志和相关源码,通过 KernelMail 检查社区是否已有补丁。如果已有方案,就评估它;如果没有,就尝试写一个最小修复。

  4. 社区邮件准备
    本地验证通过后,KernelMail 生成 git send-email 计划。Agent 撰写邮件正文,补齐 Fixes:Reported-by:Closes: 等标准标签,再由用户确认发送。

这里的分工是 SyzForge 的核心:MCP 工具处理确定性的工程动作,Agent 处理主观推理和代码理解。

我觉得这是一个很自然也很重要的边界。内核 Bug 调查不是简单的自动化任务,它需要经验、判断和取舍。SyzForge 不应该把这些判断藏进工具里,而应该把证据和过程摆清楚,让 Agent 和工程师能更好地判断。

为什么采用多 MCP

从实现角度看,SyzLens、KernelLab 和 KernelMail 完全可以被塞进一个大工具里。但 SyzForge 选择拆成三个 MCP 服务器,是有意为之。

首先是职责单一。SyzLens 专注证据采集,KernelLab 专注构建和复现,KernelMail 专注邮件工作流。每个组件都知道自己该做什么,也知道自己不该做什么。

其次是独立演进。SyzLens 可以继续增加新的证据源,而不用影响 KernelLab 的构建管线。KernelLab 可以支持新的 QEMU 配置或更多目标架构,而不用理解 syzbot 页面解析。KernelMail 可以改进邮件线程管理,而不碰复现逻辑。

第三是选择性部署。最小化使用时,你可以只运行 SyzLens,在本地工作站做离线 Bug 分诊。完整调查时,再接入 KernelLab 和 KernelMail。不同场景不需要背负同样的复杂度。

最后是安全性。MCP 边界天然限制了每个服务器的能力。KernelMail 不会因为 Agent 想发邮件就直接发出去;KernelLab 不会因为日志里有线索就推断根因;SyzLens 也不会把原始证据包装成未经验证的结论。

这种设计让系统更像一组可靠的工程模块,而不是一个什么都想管的大型黑盒。

一个具体例子

假设我们收到一个 syzbot Bug:

syzbot: null ptr deref in vmxnet3_dev_xmit

在 SyzForge 中,一次调查可能会这样展开:

  1. Agent 指示 SyzLens 获取该 Bug,并下载全部相关工件。

  2. SyzLens 拉取 Bug 详情、崩溃报告、控制台日志、内核配置、C reproducer 和社区讨论页面,缓存到本地 data/artifacts/,同时生成工件清单。

  3. Agent 将 SyzLens 清单导入 KernelLab,在 upstream 目标下创建一个 case。

  4. KernelLab 从 Linux 仓库检出 syzbot 指定 commit,应用内核配置,构建 bzImage,编译 C reproducer,搭建 QEMU 环境,并运行复现程序。

  5. Agent 读取复现日志,确认 crash 可以稳定触发。

  6. Agent 继续阅读崩溃栈和相关源码,定位到 vmxnet3_dev_xmit 中可能的空指针解引用路径。

  7. KernelMail 展示已有社区讨论,比如有人提出过修复方案,也有人指出了另一个可能方向。

  8. Agent 对比这些讨论,决定写一个更小、更直接的补丁。

  9. KernelLab 重新构建并运行 after 复现,确认问题不再触发。

  10. KernelMail 生成 git send-email 计划,Agent 准备带有 Fixes:Reported-by:Closes: 标签的邮件正文。

  11. 用户确认后,再执行邮件发送流程。

这一整套过程里,每一步都有记录,每个工件都能追溯,每个判断也能回到原始证据中重新检查。

这就是 SyzForge 想带来的改变:不是让 Bug 分析变得“神奇”,而是让它变得更稳、更顺、更能复盘。

实例验证

目前此系统已经成功验证一笔patch,并推送patch被linux-usb的维护人员同意,下面是邮件回复:

On Fri, Aug 21, 2026 at 05:04:16PM +0800, Liu Qi wrote:  
> ene_ub6250_probe() calls usb_stor_probe2(), which starts the usb-storage  
> infrastructure and schedules the delayed scan work.  The driver then  
> calls ene_get_card_type(), which sends an ENE command through  
> ene_send_scsi_cmd() and the usb-storage bulk transfer helpers.  
>   
> Both the delayed scan work, through usb_stor_Bulk_max_lun(), and  
> ene_get_card_type() use us->current_urb.  The scan work serializes this  
> access with us->dev_mutex, but the ENE card-type probe does not.  If the  
> scan work runs while ene_get_card_type() is still using us->current_urb,  
> usb_submit_urb() warns that the URB is already active.  
>   
> Serialize ene_get_card_type() with us->dev_mutex, matching the locking  
> used by the scan path.  
>   
> Reported-by: syzbot+22ea20ef3afb6785b122@syzkaller.appspotmail.com  
> Closes: [https://syzkaller.appspot.com/bug?extid=22ea20ef3afb6785b122](https://syzkaller.appspot.com/bug?extid=22ea20ef3afb6785b122)  
> Assisted-by: Qwen:Qwen3.6  
> Signed-off-by: Liu Qi <liuqi@longcheer.com>  
> ---  
  
Acked-by: Alan Stern <stern@rowland.harvard.edu>
  
>  drivers/usb/storage/ene_ub6250.c | 2 ++  
>  1 file changed, 2 insertions(+)  
>   
> diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c  
> index 2cffc559a..13b332d1d 100644  
> --- a/drivers/usb/storage/ene_ub6250.c  
> +++ b/drivers/usb/storage/ene_ub6250.c  
> @@ -2358,7 +2358,9 @@ static int ene_ub6250_probe(struct usb_interface *intf,  
>                  return result;  
>    
>          /* probe card type */  
> +        mutex_lock(&us->dev_mutex);  
>          result = ene_get_card_type(us, REG_CARD_STATUS, info->bbuf);  
> +        mutex_unlock(&us->dev_mutex);  
>          if (result != USB_STOR_XFER_GOOD) {  
>                  usb_stor_disconnect(intf);  
>                  return USB_STOR_TRANSPORT_ERROR;  
> --   
> 2.43.0

整个流程没有我个人的参与,完全靠这套系统进行探索以及与社区交流 - -!

设计理念:清晰、可控、可生长

如果要用三个词概括 SyzForge 的设计理念,我会选:清晰、可控、可生长。

清晰,是因为内核问题本身已经足够复杂,工具不应该再增加理解成本。一个功能为什么存在,当前处在哪一步,下一步可以做什么,系统都应该尽量直接地呈现出来。

可控,是因为自动化不是为了替人做所有决定。SyzForge 更像是把重复、繁琐、容易出错的部分托住,让人的判断力用在真正重要的位置上。复现是否可靠,日志说明了什么,补丁是否合理,这些仍然需要 Agent 和工程师一起判断。

可生长,是因为这个项目不会停在第一版。真实的漏洞分析流程会不断变化,新的目标、新的架构、新的证据源、新的协作方式都会出现。SyzForge 的模块化设计,就是为了让它能随着真实使用继续扩展,而不是被早期形态锁死。

我希望未来的 SyzForge 不是一个“看起来很全”的平台,而是一个大家愿意一直用的工作台。它不抢人的判断力,也不制造额外复杂度,而是把任务从模糊推向清楚,把线索从零散推向成形。

结语

SyzForge 这个名字里的 Forge 有锻造的意思,我觉得它很贴合这个项目的气质。

它要锻造的不是某一个单点工具,而是一条从 syzbot 原始报告到本地复现、补丁验证、社区提交的工程链路。崩溃报告、日志、配置、源码、讨论、补丁,这些原本散落在不同地方的东西,会在 SyzForge 里被重新组织起来,成为一次可以继续推进、可以交接、可以复盘的调查。

对我们来说,SyzForge 不只是一个多 MCP 项目,也是一种工作方式上的尝试:把内核 Bug 排查中重复的部分沉淀下来,把经验留下来,把复杂流程摆放得更有秩序。

如果你也经常面对 syzbot/syzkaller 带来的 Linux 内核 Bug,或者对 Agent 参与真实工程调查的方式感兴趣,SyzForge 会是一个值得一看的项目。