关注了就能看到更多这么棒的文章哦~
Random numbers and virtual-machine forks
By Jonathan Corbet
March 11, 2022
DeepL assisted translation
https://lwn.net/Articles/887207/
随机数生成器(RNG)的关键特征之一就是不可预测性(unpredictability),因此,天生就应该无法知道生成的下一个数字是多少。系统的安全性在很大程度上依赖这种不可预测性。如果攻击者能知道 RNG 未来输出的数值,就可能会窃听(或干扰)到网络对话、破坏加密密钥,等等。因此,在人们发现有一个常见的情况可以导致 RNG 的输出变得可以预测时,就感到非常不安。这个情况就是:虚拟机的分叉(forking)或复制(duplication)。Linux RNG 的维护者 Jason Donenfeld 正在研究解决这个问题的办法。
内核的 RNG 维护着一个 "熵池(entropy pool)",随机数就是从这里产生的。当环境中的随机性因素被采集进来时,就会被混入池中,保持熵的水平。每个正在运行中的系统都有自己的池子,自然也有自己的内部状态。如果两个系统由于某些原因使得各自的熵池都包含了相同的数据,那么它们就会产生相同的随机数序列,至少在一段时间内是这样的行为。这是不应该发生的事情。
但是,正如 Donenfeld 在 2 月份首次发布的 patch set 中指出的那样,有一种方法可以使两个系统最终拥有相同的熵池内容。如果一个正在运行的虚拟机以某种方式被复制,熵池也会随之被复制。如果一个机器进行了抓取 checkpoint 以及 restore 的动作,或者由于任何原因分叉(fork),这样就会有相同的熵池内容。一旦 restore 出来的虚拟机或 fork 出来的虚拟机开始运行时,它将再次沿着前一个实例创建时随机数据序列生成随机数,直到新的熵值加进来从而打乱池子。
微软似乎已经在 Windows 中解决了这个问题;该解决方案采用了通过 ACPI 固件提供的 "virtual-machine ID "的方式。当一个虚拟机 fork 或重新启动时,该 ID 就会被改变。内核可以观察这个值,并在注意到它的变化时,得出结论,某种形式的虚拟机 fork 已经发生,有必要采取行动来保持随机数据流的唯一性。在一些虚拟化系统中,包括 QEMU,都已经实现了这个功能,所以 Linux 也可以利用这个功能。
因此,该 patch set 增加了一个新的 "vmgenid" 驱动,使得内核可以使用 virtual-machine ID。当这个驱动收到通知(来自 ACPI 固件)时,它会检查 ID,如果 ID 改变了,就会调用一个新的函数(crng_vm_fork_inject())来通知 RNG,需要混入新内容到熵池了。具体做法就是把这个 virtual-machine ID 混入熵中。这个方法并不没有做到极致安全,但它确实解决了眼前的问题;Donenfeld 打算将这项工作合并到 5.18 中。
不过,这个工作并没有到此为止;在后来的电子邮件中,Donenfeld 描述了他接下来想做的改动。他首先抱怨了微软的解决方案的设计本身,其中有一个 race condition 竞态条件问题。内核要一直等到发现生成的 ID 已经变化之后,才能开始对虚拟机 fork 时间做出反应。新的虚拟机可能在这之前已经运行了一段时间,在这段时间内它还是会生成重复的随机数。他说,最好是提供一个简单的 "generation counter",在每次请求随机数据时由 CPU 快速轮询一下,这样就能够立即捕捉到最新的变化。"但我们目前没法这样做,因为微软在这方面没有与任何人合作,而且现在这个功能已经在几个 hypervisor 中都实现完毕了"。
在解决了这个问题之后,他开始了手头真正的任务:将有关虚拟机分叉的消息传播给其他关注此事件的内核子系统。他最初设想创建一个新的电源管理事件(power-management event),当作一个 notifier 来用,但人们认为这种做法比较奇怪,毕竟虚拟机 fork 实际上跟电源管理并没有什么关联。所以 Donenfeld 发布了一个新的解决方案,创建一个单独的 notifier(使用内核现有的通知器机制)来通知子系统。不出所料,第一个使用者就是 WireGuard VPN,它需要知道此类事件:
当虚拟机分叉时,WireGuard 很有必要清除现有的会话,这样不同的明文(plaintext)就不会使用相同的 key+nonce 来传输了,否则可能会对加密产生灾难性的后果。
用户空间的代码也可能可以从获悉虚拟机 fork 中受益;例如,Samba 服务器可能想在这种情况下重置 session。对于用户空间,Donenfeld 建议添加一个新的虚拟文件,程序可以轮询它来获取 VM-fork 的通知。这个文件目前位于 /proc/sys,尽管它不是一个真正的 sysctl 钮,毕竟它无法进行写入来调整系统行为。
总的来说,对这项工作的反响是很正面的;内核开发者往往都不希望看到加密导致灾难性的后果。尽管如此,Greg Kroah-Hartman 还是观察到了一些问题:" 这里的 '我们刚刚生成了一个新的 vm' 的 notifier 是在 random driver 里实现的,这似乎很不合理,但当然,现在可以就把它放在这里吧!" 因此,这项工作似乎也必定会在 5.18 版本的内核中合并。这应该有助于关闭一个我们许多人可能从未意识到存在的漏洞。
全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。
欢迎分享、转载及基于现有协议再创作~
长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~

针对虚拟机分叉可能导致随机数生成器输出可预测的问题,Linux内核开发者提出了解决方案。通过引入虚拟机ID监测并在检测到分叉时注入新熵,确保了随机数的不可预测性,进而保障了系统的安全性。
2162

被折叠的 条评论
为什么被折叠?



