跳转至

ADR-0007:Windows 热修客户端复用扩展 LiveUpdate 机器

日期:2026-07-20 状态:已接受

背景(源码核实结论,fabcommon/src)

现有 LiveUpdate 体系(liveupdate.exe + libupdateex + Copy.exe)已实现:三级 URL 链路(JSON 版本查询 → XML 更新信息 → 增量 cfg);按文件 bsdiff 二进制差分BspatchNode,MODIFIED 文件走 bspatch 重建 + MD5 校验,失败置 ERROR_PATCH_FILE 下次强制全量);增量 cfg 命名 {客户端类型}_{当前版本}_{目标版本}.cfg(增量是否存在由服务端决定,客户端拿不到 cfg 自动回退全量);杀进程 → Copy.exe(UAC 提权)替换 → 重启的完整编排。

已确认的短板:无任何非对称验签(唯一内容校验是 patch 重建后 MD5);cfg 与补丁 zip 本身无校验;CURLOPT_SSL_VERIFYPEER=0 TLS 校验关闭;LiveUpdate_CrtFile 是死字段(且来自可篡改的 update_config.xml,不能作信任根);Copy.exe 的"备份"仅为绕文件锁、下轮即删、无回滚、无整体返回值。

决策

Windows 热修客户端不新建,在 LiveUpdate 机器上增加热修模式:

  1. RunModehotfix 模式,Update_HotFix 更新类型,走独立的签名清单(不复用现有明文 cfg 协议的信任模型)。
  2. Ed25519 验签集中两处:清单下载后信任前(StartDownloadUpdateCfgFile/ParseUpdateInfo);文件落盘交给 Copy.exe 前(CheckFileValid choke point)。公钥硬编码进二进制,不用 LiveUpdate_CrtFile
  3. ~~热修包体积用现有 bsdiff 增量机制解决~~ 已作废:CI 侧 force_add_list.txt 已把 StreamFab64.exe 强制排除在 bsdiff 之外(加壳签名二进制差分触发杀软/签名问题),热修主 exe 走全量 zip 投递(见 ADR-0008)。客户端 ADD 类型(PKZIP 全量)投递路径同样是现成的,仍无需新写下载逻辑。
  4. FabUpdateCopy(Copy.exe)改造为可回滚:备份清单、任一步失败回滚已替换文件、替换后复核签名通过才删备份、WinMain 返回整体成败供上层决定重启或回滚;停止无条件删除上轮备份。
  5. 传输加固:热修链路打开 VERIFYPEER/VERIFYHOST、去掉 SetSecure(false)(签名为主、TLS 为辅,两层都要)。

后果

  • 客户端开发量大幅下降(下载/差分/替换/重启编排全部现成),且热修与完整升级共用久经考验的替换代码路径。
  • 增量 cfg 的 {cur}_{new} 命名与"按基线版本定向"(ADR-0002)天然对齐。
  • Copy.exe 改造与验签插入是主要新增工作;macOS 仍需新建模块(协议与清单格式与 Windows 共用)。
  • 热修的杀进程时序需改为优雅退出(urgent 提示用户点击重启后由应用自行退出再触发替换),不沿用 TASKKILL /F