作者丨Jim Salter
译者丨核子可乐
策划丨张之栋、蔡芳芳
AMD 公司发布的 Ryzen 3000 处理器中,存在一项与随机数生成器相关的严峻微代码 bug。也正是由于这个早已曝光数月却没有得到有用处理的“过错”,本篇文章的主人公 Jim Salter 度过了一个十分糟糕的周末。你能梦想,一整天都在盯梢过错的问题,寻觅 bug 原因的场景吗?
Ryzen 3000 的 RDRAND 函数(本应成为一款高质量的伪随机数生成器)每次都会回来 0xFFFFFFFF,修正进程也是恰当折磨。
上周末,Jim 怀着激动的心境坐在家中的作业间里,在他计划布置自己的第一台 Ryzen 3000 作业站时,却惋惜的发现,AMD 的一项微代码 bug(开端公布于本年 7 月,但直到现在仍广泛存在于各类体系傍边)打破了这夸姣的梦想。
虽然 Jim 经过尽力,让这套 Ryzen 3700X 体系康复了正常,并且速度也恰当惊人,但他不得不供认的是:AMD 的微代码 bug 依然存在,并且现在短少简略易行的修正办法。
事实上,在 Ryzen 3700X 发布后不久,AMD Ryzen 3000 的运用者就现已发现了这款簇新的 CPU 存在问题:Windows 用户无法顺畅发动 Dstiny 2(原因是存在电源办理 bug,不过困扰 Jim 的倒不是这个问题),Linux 用户乃至发现自己常常无法正常发动体系。
福布斯杂志作者 Jason Evangelho 在本年 7 月的文章中陈述了开端现象与总结定见,AMD 公司的代表则经过电子邮件发出了回复声明:
AMD 公司现已确认了引发问题的底子原因,并对 BIOS 程序进行了修正,旨在处理 Ryzen 3000 处理器无法运转某些 Linux 发行版以及 Destiny 2 的功用问题。咱们现已将更新后的 BIOS 发放给各主板合作伙伴,期望顾客能够在未来几天之内运用到新的 BIOS。
并且 AMD 方面虽然在本年 7 月就做出了回复,但到到现在为止,AMD 方面也仅仅仅仅发送了告诉邮件罢了。它并没有在其他途径做出任何的相关提示,不只没有新闻稿,并且这封邮件看起来诚心略显缺乏,似乎在说这仅仅一个能够在一两周之内轻松处理的小问题。
现在,现已曩昔三个月的今日,踩了坑的 Jim 标明:AMD 的微代码 bug 问题十分严峻。
从 RDRAND 开端
存在 bug 的代码会对 RDRAND 指令做出过错的呼应,而这个 bug 之所以十分严峻,则需求从 RDRAND 说起。
事实上,从英特尔的 Broadwell 以及 AMD Zen 架构开端,现代 x86_64 CPU 有必要内置高质量的板载随机数生成器(RNG),担任运用热“噪声”快速向具有内核级拜访权限的用户供给高熵伪随机数。而 RDRAND,正是触发随机数生成的指令。
AMD 的整个规划体系本应该十分安全,可是实在的情况却存在一些误差。
首要是一条 CPUID 函数调用,用于查看 RDRAND 的可用性;此外,RDRAND 调用的回来值中还包括一条“进位”,该位会在 CPU RNG 无法生成满足的随机数时告诉作为调用方的应用程序。惋惜的是,在装置修正补丁之前,Ryzen 3000 会对 CPUID 01H 调用回应“yes”,并将进位设置为“1”,标明其现已成功创立了有机高质量随机数……一起每一次的“随机”数都被赋值为了 0xFFFFFFFF。
只需在满足广泛的数据集傍边,接连 20 个 0xFFFFFFFF 才或许被视为有用的“随机”分组。但在大多数情况下,咱们运用的数据集都没那么广泛。
咱们不要测验运用 /dev/hwrng 来查看自己的设备是否遭到 AMD 微代码 bug 的影响,这是由于 /dev/hwrng 或许会从其他来历获取数据。在 Jim 的事例中,它倒的确是从 RDRAND 处获取数据,这让 Jim 很快就发现了问题。
RDRAND bug 的首要影响
本年 6 月,Ryzen 3000 中的 RDRAND bug 初次被发现时,Linux 用户开端很多发布陈述,标明自己根据 Ryzen 3000 的操作体系无法正常发动。而引导失利正是由 systemd 运用 RDRAND 引发的;不过惋惜的是,这现已不是 systemd 第一次与 AMD CPU 上存在问题的随机数生成器发作抵触了。
前期一批 CPU 中存在的一项 bug,会导致某些 AMD 体系在从挂起情况康复至正常作业情况后中止生成正确的“随机”数。而此次发作的新 bug,则会导致 Ryzen 3000 用户全程得不到任何适宜的随机数。这两个问题,都导致了 systemd 在 Linux 操作体系中被长时刻确认。因而本年 5 月,systemd 提交了一项修正程序,假如 systemd 从 RNG 得到的回来值为 0xFFFFFFFF,则该修正程序会转而运用备用 RNG 源。(但这种修正办法本身也有问题,由于从技术上讲 0xFFFFFFFF 是个完全有用的随机数——因而,只需经过满足长的时刻,systemd 究竟会在收到这个哪怕本应正确的随机数时,将其误判为过错情况,然后再直接切换至 RNG。)
Systemd 的补丁虽然做的很一般,但的确能够让操作体系顺畅发动。仅仅它并不能真实从底子上处理问题,究竟这种治标不治本的办法压根没有触及到随机数生成器那个层面。
Jim 在自己的体系上,用了一整个周末的时刻,盯梢一个个过错问题。这个进程让 Jim 十分抓狂。
Jim 首要置疑问题来自体系上装置的全新 RX 590 显卡,然后就一次次更新操作体系发行版以及内核版别。但这些更新底子没用。
簇新的体系不断报出一个个厌烦的 BUG:软确认——22 项过错完全卡住了 PU#n,并敏捷令体系全体堕入瘫痪。/var/log/syslog 中的调用信息也没什么指导含义,不过至少让 Jim 找到了第一条头绪。
终究,在阅历了一系列测验、气急败坏的诅咒、无数杯咖啡和几口小酒之后,Jim 总算把 CPU 的频频确认与调用盯梢记载联络了起来。由于 Jim 发现,在每一次盯梢中,都会呈现“WireGuard”的身影。
Jim 称:事实证明,WireGuard 依托 RDRAND(假如可用)生成新的会话 ID。会话 ID 有必要仅有,WireGuard 还要求其不是简略的接连整数,因而它会从 RDRAND 中获取伪随机值,将其与现有会话 ID 清单进行比较以保证不存在抵触,然后将该 ID 分配给新会话。
请注意这儿的最终一句“保证不存在抵触”,它的含义在于,假如现有会话同新会话具有相同的 ID,则 WireGuard 会向 RDRAND 恳求另一个“随机”数,并再次查看其仅有性,依此类推。由于体系上的 RDRAND(以及任何未经更新的 Ryzen 3000 体系)一直回来 0xFFFFFFFF,因而这个进程就会无限循环。内核代码发作无限循环当然不是什么功德,紧随其后的必定是体系溃散与硬件重启。
但,问题并不是出在 WireGuard 身上!WireGuard 正确地查看了 RDRAND 是否可用、是否给出一个值,以及该值是否正确设置了进位。它的职责,便是保证不只获得了一个值,并且确认该值的确是恰当的随机值。可是即便这样,爱岗敬业的 WireGuard 仍是让用户的体系堕入了瘫痪。
现代体系需求高质量的伪随机数来完结很多使命,其间“随机”的含义当然不或许是“一直回来 0xFFFFFFFF”。还有另一种直观的候选办法,也便是地址空间布局随机化(ASLR)。Windows 与 Linux 都只选用 RDRAND 作为随机机制中的一部分,旨在保证永久不会以相同的次序加载同一段代码,然后减轻相关软件栈遭到损坏的危险。
修正问题,至少是发现问题
正如 AMD 公司代表在本年 7 月承受采访时所言,真实的修正手法是对主板进行 BIOS 更新,一起保证 BIOS 傍边包括针对 CPU 本体的微代码补丁。可是当 Jim 这样做时,却发现并没有那么简略。
Jim 运用 dmidecode 程序查看了自己的 BIOS,发现日期是 2019 年 8 月 12 日,所以当看到华硕主板下载页面上更新到 9 月的 BIOS 时,Jim 十分惊喜。为了赶快完毕这糟糕的一天,Jim 挑选了马上下载 BIOS 更新,并将其保存到 U 盘傍边,重新发动体系,然后进入设置程序,趁热打铁。
不过惋惜的是,在成功更新并再次重新发动之后,Jim 忽然意识到自己犯了个过错——没错,华硕虽然列出了 BIOS 的更新日期,但其供给的实践版别与 Jim 之前运用的相同,都是 3.2.0。所以 Jim 的 CPU 依然坚持以为 0xFFFFFFFF 是随机度最高、质量最好的生成数。
遭受这一系列作业的 Jim ,火气一下就上来了:systemd 虽然悄然处理了这个 bug,但大多数应用程序仅仅直接疏忽,我怎样知道问题究竟有没有得到修正?假如两年之后,事实证明 ASLR 底子无法供给真实的随机数,那我因而遇到的损坏性进犯又由谁来担任?
不过,好在几番冥思苦索后,Jim 忽然发现自己完全能够运用 Linux 上的 hexdump 东西对内核设备 /dev/hwrng 进行查看,以证明的确存在这一问题。
但 WireGuard 项目的 Jason Donenfeld 却正告称,/dev/hwrng 在某些体系上或许从其他来历处获取随机数,换句话说,当看到一大堆 FF 时必定能够证明它有问题,但当看到一大堆有用的伪随机数时也不能阐明它没有问题。为此,Jason Donenfeld 还大方地共享了多种测验程序,能够协助用户安全地直接拜访 RDRAND。
假如咱们运用的是 Linux,能够下载 rdrand-test.zip ,正常解压,然后在文件夹中直接运转。经过./amd-rdrandbug 指令,用户能够查看自己的体系是否存在这一特定 bug。./test-rdrand 能够输出 20 条 RDRAND 取值,假如咱们在测验中发现自己总是得到相同的值集,那么不管其看起来是否随机,都标明你现已成为这项 bug 的受害者!
假如咱们运用的是 Windows,那还得额定做点作业。首要下载 Ubuntu 桌面装置程序,然后创立一个 Ubuntu 发动 U 盘。接下来,你能够发动 Ubuntu 发动盘的实时环境(点击「Try Ubuntu」),然后下载并运转以下测验:
只需在满足广泛的数据集傍边,接连 20 个 0xFFFFFFFF 才或许被视为有用的“随机”分组。但在大多数情况下,用户运用的数据集都没那么广泛。
Jim 的总结
阅历了这样一个糟糕的周末,Jim 最终总结了自己的收成:
随机数生成器 bug 是个恰当严峻的问题,但愈加令人不安的是,在曩昔三个月的时刻里,AMD 公司并没有就此问题进行活跃的尽力与着重。虽然全体而言,Ryzen 3000 的确是一款超卓的 CPU 渠道,新体系也给我留下了深入的形象……可是,整整一个周末令人头痛的毛病排查阅历,让我对这套体系的全体安全性产生了严峻的置疑,我乃至不知道这个 bug 什么时候才干得到修正。
日前,我与 AMD 公司的代表取得了联络。对方答复了我关于硬件的问题,但没有给出详细处理方案。等有了最新音讯,我会及时向咱们报告更新音讯。
事情后续
过后,在 Jim 联络 AMD 就此事进行问询时,AMD 的一位代表问询了 Jim 的主板类型(Asrock Rack X470D4U),然后又联络了 Asrock。Asrock 团队供给了现已完结微代码修正的定制 BIOS 版别,但 Jim 以为这种只适用于个人的 BIOS 版别没有任何含义。
与此一起,有读者在 Jim 的文章谈论区给出了一些其他处理办法及缓解办法,虽然如同并没有什么用。
一种是在引导时将 nordrand 以参数方式传递给 GRUB。这种办法并不能处理问题,由于该办法实践上便是奉告内核不要运用 RDRAND 指令,这往往无法影响该指令本身的实践可用性。指令依然存在于体系傍边,而全部经过 CPUID 查看 RDRAND 可用性的代码也依然会遭到影响。相似的 random.trust_cpu Linux 引导选项也是如此。这些缓解性办法都没能真实禁用 RDRAND,因而不能算是问题的抱负处理方案。
另一种是装置 amd64-microcode 软件包。Jim 测验后标明,成果仍是不可。由于在默许情况下,amd64-microcode 与 intel-microcode 软件包被直接装置在 Ubuntu 19.10,以及所运用的体系傍边,但这并不能处理 RDRAND 的毛病。为此,Jim 再次联络了 AMD,要求对方代表查看该软件包的情况并确认是否有必要对其做出更新。
以下是 Jim 的验证:
现在最新 Ubuntu 10.10 体系上的 amd-64 微代码补丁,其依然无法处理 RDRAND 的问题。
在设置 nordrand 或许 random-trust_cpu=0 之后,rdrand 在 /proc/cpuinfo 下仍显现为可用,因而这两种引导选项均无法真实处理这个问题。
One more thing
截止到本文发布,Jim 的文章并没有进一步更新,咱们也无从得知他是否现已等到了 AMD 所许诺的那个“具有真实含义的通用 BIOS 版别”。
其实,关于某些“极客” 来说,处理器的微代码早已不是什么奥秘的东西,它能够被看成是一种处理器固件,从主板的 BIOS 中进行加载。而主板制造商则能够经过在新的 BIOS 版别中集成新的处理器微代码,支撑新的处理器或是对一些所谓的 bug 进行修正。
可是实在情况咱们也看到了,BIOS 的更新并不简单,bug 的修正难度也不低。不信,你看看近邻的英特尔,它也相同正在忙着修补自家的缝隙呢。
https://arstechnica.com/gadgets/2019/10/how-a-months-old-amd-microcode-bug-destroyed-my-weekend/#lg=1&slide=1
点个在看少个 bug