微澜SONG LI
《何以为人:她》

第七章 共享缓冲区

7 / 12

四月的第二次提取我是一个人去的。

梁渡在杭州出差,给我开了临时门禁,语音里全是风声:周末整层没人,你自己弄,弄完把总闸推上去,别忘了。

那天上海下雨,张江那条路两边的梧桐刚发新叶,被雨压得低。六层的走廊灯是感应的,我走过去它才亮,走过了它就灭,一路上身后一段一段地暗下去,像有个人跟在后面,一盏一盏把灯收走。

实验室的空调没关,二十四小时恒温。导电膏从冰箱里拿出来是凉的,抹在太阳穴上,那股很淡的杏仁味又出来了。二十分钟。屏幕上的波形我看不懂,也懒得看。

结束以后我按流程导出了日志,本来是想看一眼信噪比——职业病,任何数据到我手里都得先看质量。日志四千多行,我在地铁上翻,翻到中间一段,停住了。

一条写入记录。时间戳落在提取过程的第十一分钟。

那台设备对外只有一个read接口。我全程没有碰过键盘。


回家以后我先做了一件很蠢的事。

我把jl.log从头拉到尾,一万四千行,一行一行看时间戳。所有的更新都在我记得的位置上,一条不多,一条不少。

这什么都不说明。一个被改过的人不会记得自己被改过。

我在电脑前坐到三点,中间起来喝了两次水。第二次的时候我站在厨房里想,我现在这个念头本身是不是也是被写进去的。想到这里就停下了,因为再往下想没有底。

后半夜我开始干活。

固件的版本号是第一处不对。文档上写的是2.3.1,设备里跑的是2.3.1-rc4。

rc4。一个候选版本,跑在往人脑里插电极的设备上。

我把镜像dump下来,反编译。这个活我干过,前公司做过一段车机,逆向别人的驱动是常规操作。

三个通宵之后我找到了它。

读和写共用同一个环形缓冲区。这本身不是问题,很多驱动都这么干,省内存。问题出在超时重试的那段代码里——它把缓冲区句柄传下去的时候,没有带方向位。

方向位是一个bit。0是读,1是写。

在正常路径上,这个bit由上层调用者设置,永远是对的。可超时重试走的是另一条路,它复用了上一次调用留在结构体里的值。

如果上一次是写操作,而缓冲区没有清零,那么这一次"读",会把上一次残留的数据推回去。

推回哪里,取决于电极在哪。


我把复现步骤写成了文档。

环境、前置条件、操作步骤、预期结果、实际结果、影响面评估。截图七张。这种文档我写了六年,闭着眼睛都能写。

写完我通读了一遍,格式很干净,编号也没乱。

我没有提交。


第二天中午我给梁渡打电话。他在高铁上,信号断续。

我把事情说了。说到一半他打断我。

"你跟别人说了吗。"

不是"真的假的",不是"你确定"。

我说没有。

那头有一段静音,可能是过隧道。

"文档发我。别走邮件,用那个私有仓。"

我说好。

"rc4就在了。rc5修的。"他说,"生产上有一批设备没推rc5,因为推完要重新做临床验证,一做又是九个月。"

我没有接话。

"何奕。"

"嗯。"

"别用它。"

我等着他往下说。他没有。

过了两三秒他又开口,声音比刚才低一点,像是把手机换了个耳朵:"我说的是别用它。不是别研究它。你听懂了吗。"

我说听懂了。

我们都没有再说话。他那头有列车播报到站的声音,很远。他说我到了,挂了。

那天晚上我睡得很好。

四个月来第一次。