目录篇历系统漏洞

 人参与 | 时间:2026-10-17 07:05:56

去年秋天,目录我在一台旧服务器上翻出一份2003年的篇历目录备份。文件名全是系统乱码,时间戳却整整齐齐。漏洞点开一看,目录目录结构本身没问题,篇历但每个子目录的系统修改时间都指向同一个秒——1970年1月1日00:00:00。这不是漏洞巧合,是目录漏洞。

目录篇历系统,篇历说白了就是系统文件系统里记录“谁在什么时候改了哪个目录”的那套机制。它不像文件内容那么显眼,漏洞但一旦出问题,目录整个系统的篇历可信度就塌了。我遇到的系统这个案例,根源在ext3文件系统的一个边界条件:当目录项数量超过某个阈值,且同时发生重命名和删除操作,时间戳更新会跳过实际写入,直接回滚到Unix纪元。听起来像天方夜谭,但内核日志里白纸黑字写着“dir timestamp overflow”。

更麻烦的是,这种漏洞不会报错。你ls -l看目录,时间显示正常——因为用户态工具会做一次修正。可一旦你用stat直接读inode,或者拿备份软件去比对,就会看到那个1970年的幽灵。我试过用debugfs手动改回去,结果下一次挂载又变回来。内核在目录项哈希表里缓存了错误值,你改磁盘没用,得先echo 3 > /proc/sys/vm/drop_caches。

这让我想起另一个更常见的坑:NFS上的目录时间戳。客户端和服务器时钟差几秒,目录的mtime就会在两边跳来跳去。你刚touch完一个目录,下一秒ls发现时间倒退了。不是文件系统坏了,是NFSv3的目录属性缓存没有强一致性。解决办法?要么上NFSv4,要么在mount时加noac,但性能掉一半。我选后者,因为那台机器只跑内部备份,慢就慢点。

还有个真事。某次帮朋友恢复数据,他用的是Btrfs。目录篇历里有个叫“transid”的字段,每次事务提交递增。漏洞出在快照上:你删掉一个子卷,再重建同名子卷,transid不会重置,但目录项的生成号会。结果就是find命令偶尔会漏掉新目录里的文件——因为内核认为“这个目录项太老了,不可能属于当前transid”。他丢了三个月的照片。后来我用btrfs check --repair救回来一部分,但目录结构已经乱了,文件夹嵌套错位,像被揉过的纸。

为什么这些漏洞难修?因为目录篇历系统横跨VFS层、具体文件系统层和块设备层。改一个时间戳语义,可能让rsync的增量备份失效,也可能让make突然重编译所有东西。Linux内核社区讨论过用64位时间戳替代,但兼容性包袱太重。你总不能要求所有老硬盘都支持新格式。

我的建议很直接:别信目录时间戳。做备份时,用find -newer配合一个标记文件,或者直接算目录内容的哈希。我现在的脚本里,每个目录的“最后修改”是自己维护的一个文本文件,放在同级目录下,叫.mydir_mtime。土办法,但不会骗我。至于那个1970年的幽灵,我把它写进了监控告警——只要看到目录时间早于2000年,立刻触发全量校验。漏洞还在,但至少我知道它什么时候会咬我。

顶: 77939踩: 87785