一个数据库漏洞,藏了16年没人发现。揪出它的不是数据库厂商,而是一家做VPN和网络连接服务的公司——Tailscale。
这家公司花了几个月时间调查自家服务为什么不稳定,最后发现问题出在SQLite身上。他们把整个过程写进了官方博客:问题是什么、怎么应对、又是怎么帮SQLite找到这个陈年漏洞的。
![]()
从备份损坏开始
![]()
Tailscale从2022年起把SQLite当作主要数据库。用户访问Tailscale的端点时会连上「控制平面」,控制平面由多个「分片」组成。安全的私有网络「Tailnet」落在其中某个分片上,必要时可以在分片之间无缝迁移。每个分片都有一套SQLite数据库,存放自己管理的Tailnet的全部信息,由单个Go进程独占访问。
备份机制是每隔几分钟给数据库拍一次完整快照,把整个SQLite文件上传到Amazon S3的存储桶。这套配置从2023年初开始一直运行正常,直到2025年8月,S3备份里报告了数据库损坏。
损坏在6个月里发生了19起,影响范围只限于控制平面的配置数据。但每次损坏都得停掉控制平面进程去修复或恢复数据库,承载该分片的控制平面因此出现停机。
查不到触发条件
团队先排查最近的改动,没找到可疑项。跟SQLite打交道的底层代码都是几年前写的,因为一直没出问题,也没改过。把代码翻了个遍,也没发现能导致数据损坏的写法。
触发条件不明,漏洞就复现不了,只能靠生产环境里的取证遥测。更麻烦的是,事故有时隔几小时就发生一次,有时几周都风平浪静。判断这不是能轻松修好的问题后,Tailscale和SQLite的开发者签了专业支持合同,一起验证问题。
调查期间平台照常运行,为了自动恢复、缩短停机时间,他们做了几件事:
- 把分片配置成数据库一损坏就立即硬停止
- 引入自动备份
- 改进运维手册和值班培训
这些措施把响应时间压到了1小时以内,也意外成了发现问题的线索来源。
事务日志带来的转机
为了在不丢数据、不冒风险的前提下恢复服务,Tailscale搭了一条事务日志管道,把所有修改数据库的SQL语句流式写入日志文件。拿最新的正常备份重放这些事务,就能把数据库恢复到最新状态,从而安全绕开损坏。
这条管道不仅按预期工作,还提供了线索。有2起事故中事务日志重放失败,细查后发现:某个事务写入并已提交的数据,在后续事务里却看不到。
![]()
情况逐渐指向SQLite检查点流程的某个环节。SQLite数据库由一系列「页」组成,也就是信息的小块。更新数据库时,需要用包含新信息的页替换掉部分页。为了提升性能和并发性,SQLite会启用「预写式日志」(WAL):新页不直接写进数据库文件,而是先写进WAL。
新页不能无限往WAL里写,到某个时间点必须复制回主数据库文件,这个过程就叫「检查点」。通常终端用户和开发者不需要手动执行检查点,SQLite会自动完成。但控制平面为了做快速且一致的备份,手动控制检查点流程——这是一种非标准做法。
另一条线索是:数据库损坏时,指标显示SQLite从WAL复制的页数超过了实际可用的页数。SQLite由多层构成,最上层是解析器和代码生成器,把SQL语句转成内部数据结构;这些结构交给分页器,由它拆成写入磁盘的单个页;真正落盘由操作系统接口,也就是「虚拟文件系统」处理。这种分层让不同层可以换成不同实现,也能包住已有层来获取更多信息。
一个调试垫片锁定真凶
为协助诊断,SQLite开发者写了一个虚拟文件系统包装层,用来输出额外追踪信息和数据库变更日志。这个包装层里包含一个调试诊断用的VFS垫片「tmstmpvfs shim」,它扩展并包装了SQLite的虚拟文件系统(VFS)层。
包装层部署到生产环境后,紧接着发生的一次数据库损坏中,tmstmpvfs shim留下的额外日志终于让SQLite开发团队找到并修复了漏洞。原因是检查点与写事务之间偶发的数据竞争:检查点处理过程中如果发生写事务,检查点流程就会混乱,导致数据丢失。
SQLite开发者把这个漏洞命名为「WAL-Reset漏洞」,并推断它至少在SQLite里潜伏了16年。它极少发生,Tailscale却屡屡撞上,原因在于Tailscale手动控制检查点创建流程,而且创建得极其频繁。
SQLite开发者发布了修复WAL-Reset漏洞的SQLite 3.52.0,但因为出现另一个问题撤回了3.52.0,改为只包含WAL-Reset修复的3.51.3,最终发布所有问题都已解决的SQLite 3.53.0。
修复应用后还有最后一步:确认即使触发漏洞的「写事务与WAL重置冲突」再次发生,数据库也不会损坏。大约2个月后,那个「期待已久」的告警终于出现,确认数据库不再损坏。
最终Tailscale确认WAL-Reset漏洞的修复有效,此后已连续4个月没有发生数据库事故。这段经历凸显了用非标准方式使用「常见技术」的风险,也让人重新认识到标准配置与路径的可靠性。问题的解决是Tailscale与SQLite开发者双方的大规模协作,既修好了SQLite多年的老漏洞,也改进了Tailscale的备份与恢复流程。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.