处理器高危漏洞无人幸免树莓派我们不受

选自raspbrrypi.org

作者:EbnUpton

机器之心编译

参与:路雪、黄小天、李泽南

过去几天,对Mltdown和Spctr安全漏洞的讨论甚嚣尘上。该漏洞影响了所有的现代英特尔处理器,Spctr还影响了AMD处理器和ARM内核。Spctr漏洞使得攻击者可以绕过软件检查读取当前地址空间中的任意位置数据;Mltdown漏洞使得攻击者可以读取操作系统核地址空间的任意位置数据(用户程序通常不可访问该数据)。这两种漏洞皆通过边信道攻击(sid-channlattack)利用很多现代处理器都有的性能特征(缓存和推测执行)泄漏数据。近日,树莓派创始人EbnUpton称树莓派不受这些漏洞的影响,并撰文详解其原因。

谷歌ProjctZro团队发现的漏洞分别被称为「Mltdown」和「Spctr」。这些漏洞允许恶意程序从其它程序的内存中窃取信息,这意味着恶意程序可以监听密码、账户信息、密钥及理论上存储在进程中的任何内容。

其中,「Mltdown」影响英特尔处理器,它打破了用户应用程序和操作系统之间最基本的隔离。这种攻击允许程序访问其它程序和操作系统的内存,这可能导致数据泄露。而「Spctr」除了能影响英特尔处理器外,还能影响AMD与ARM架构的大量处理器,这意味着除服务器与个人电脑以外,智能手机等终端设备也会受到影响,几乎所有现代计算机处理器均无法幸免。它打破了不同应用程序之间的隔离,这意味着,攻击者可以使用恶意程序来获取被隔离的私有数据。

英特尔近日表示,在未来数周内将有软件补丁发布。尽管大多数PC用户不会受到影响,但安全补丁会导致处理器0-30%的运算速度下降。

根据EbnUpton所述,大量类似树莓派的廉价计算设备可能同样也不会受到两种安全漏洞的影响,包括很多低端安卓手机。

本文介绍现代处理器设计的一些概念,使用简单的Python程序解释这些概念,比如:

t=a+bu=c+dv=+fw=v+gx=h+iy=j+k

尽管你的计算机处理器不会直接执行Python,但这里的语句足够简单,大致相当于简单的机器指令。本文不详述过多处理器设计中的重要细节(主要是piplining和寄存器重命名),它们对理解Spctr和Mltdown的工作原理不太重要。

想全面了解处理器设计和现代计算机架构,可参阅Hnnssy和Pattrson的经典著作《ComputrArchitctur:AQuantitativApproach》。

什么是标量处理器?

最简单的现代处理器每次循环执行一个指令,我们称之为标量处理器。上述示例在标量处理器上需要执行六次循环。

树莓派1和树莓派Zro中使用的Intl和ARM都是标量处理器。

什么是超标量处理器?

很明显,加速标量处理器的方式就是提高其时钟频率(clockspd)。但是,我们很快就到达处理器内部逻辑门运行的极限;因此处理器设计人员开始寻找一次性处理多件事情的方式。

有序超标量处理器检查收到的大批指令,尝试在一个piplin中一次性执行多个指令,这取决于指令之间的依赖关系。依赖关系很重要:你或许认为双向超标量处理器可以将6个指令配对执行,如下所示:

t,u=a+b,c+dv,w=+f,v+gx,y=h+i,j+k

但是这没有作用:我们必须先计算v再计算w,即第三个和第四个指令无法同时执行。双向超标量处理器实际上无法找到与第三个指令配对的指令,因此,该示例将执行四个循环:

t,u=a+b,c+dv=+f#scondpipdosnothinghrw,x=v+g,h+iy=j+k

超标量处理器包括IntlPntium以及树莓派2和树莓派3分别使用的ARMCortx-A7和Cortx-A53。树莓派3的时钟频率只比树莓派2高33%,但性能大约是后者的2倍:部分原因在于Cortx-A53超出Cortx-A7的对大量指令的配对执行能力。

什么是无序处理器(out-of-ordrprocssor)?

回到我们的示例,我们可以看到即使v和w之间存在依赖关系,我们也可以找到其他独立的指令填补第二次循环中空的pip。无序超标量处理器能够打乱指令的顺序(同样受限于指令之间的依赖关系)以保持每个piplin都处于忙碌状态。

无序处理器可以有效交换w和x的顺序:

t=a+bu=c+dv=+fx=h+iw=v+gy=j+k

允许执行三次循环:

t,u=a+b,c+dv,x=+f,h+iw,y=v+g,j+k

无序处理器包括IntlPntium2(以及大部分后续Intl和AMDx86处理器,除了一些Atom和Quark设备)和很多近期的ARM处理器,如Cortx-A9、-A15、-A17、-A57。

什么是分支预测器(branchprdictor)?

上述示例是直线式代码块。真正的程序不是这样的:他们还包括正向分支(用于实现条件运算,如if语句)、反向分支(用于实现loop)。分支可能是无条件的(通常被采用),也可能是有条件的(是否采用取决于计算值)。

获取指令时,处理器可能遇到依赖于计算值的条件分支(而该值目前尚未计算出)。为了避免停顿,处理器必须猜测下一个要获取的指令:内存顺序(对应未采用分支)或分支目标(对应采用分支)上的下一个指令。分支预测器通过收集某一个分支之前被采用频率的相关统计数据,帮助处理器猜测该分支是否被采用。

现在分支预测器非常复杂,可以生成非常准确的预测。树莓派3的额外性能部分是由于Cortx-A7和Cortx-A53之间分支预测的改进。但是,攻击者也可以通过执行精心设计的一系列分支,误训练分支预测器作出较差的预测。

什么是推测?

重排序顺序指令(rordringsquntialinstruction)是一种恢复指令级别并行化的强大方法,但是由于处理器变得更宽(能够一次执行三个或四个指令),保证所有piplin处于忙碌状态变得更难了。因此,现代处理器提高了推测能力。推测执行可以处理并不需要的指令:这样就可以保证piplin处于忙碌状态,如果最后该指令没有被执行,我们只需要放弃结果就可以了。

推测执行不必要的指令(以及支持推测和重排序的基础架构)需要耗费大量能源,但是在很多情况下为了获取单线程性能的提升,这种方法是值得的。分支预测器用于选择通过程序最可能的路径,最大化推测获得收益的可能性。

为了展示推测的好处,我们可以看一下另一个示例:

t=a+bu=t+cv=u+difv:w=+fx=w+gy=x+h

现在,我们具备从t到u到v、从w到x到y的依赖关系,那么没有推测的双向无序处理器无法填充第二个piplin。它用三次循环来计算t、u和v,之后处理器知道if语句的主体是否被执行,然后用三次循环来计算w、x和y。假设if(由一个分支指令实现)使用了一次循环,那么该示例可以执行四次(v是零)或七次循环(v不是零)。如果分支预测器表明if语句的主体很可能被执行,那么推测可以有效打乱程序,如下:

t=a+bu=t+cv=u+dw_=+fx_=w_+gy_=x_+hifv:w,x,y=w_,x_,y_

因此现在我们有了额外的指令级别的并行来保持piplin繁忙:

t,w_=a+b,+fu,x_=t+c,w_+gv,y_=u+d,x_+hifv:w,x,y=w_,x_,y_

循环计数在推测性无序处理器中变得不太明确,但是w、x和y的分支和条件更新(几乎)是空闲的,因此上述示例几近于执行三个循环。

什么是缓存?

在过去,处理器速度与内存访问速度成正比。我的BBCMicro(2MHz),可以每2μs(微秒)执行一次指令,存储周期为0.25μs。在接下来的35年中,处理器已经变的非常快,但是内存几乎没变化:树莓派3中的一个Cortx-A53可以每0.5ns(纳秒)执行一次指令,但是可能需要ns才能访问主存。

a=mm[0]b=mm[1]

需要ns。

但在实践中,程序倾向于以相对可预测的方式访问内存,同时展示时间局部性(如果我访问一个定位,我很可能很快再次访问它)和空间局部性(如果我访问一个定位,我很可能很快访问附近的位置)。缓存利用这些属性来降低访问内存的平均成本。

缓存是一个小的片上内存,接近于处理器,存储最近使用的位置(及其近邻)内容的副本,以便在随后的访问中可以快速获取。借助缓存,上述示例的执行将稍微超过ns:

a=mm[0]#nsdlay,copismm[0:15]intocachb=mm[1]#mm[1]isinthcach

从Spctr和Mltdown的角度来看,最重要的一点是你可以对内存访问的时间进行计时,你可以知道访问的地址是在缓存之中(短时)或者不在(长时)。

什么是边信道?

来自维基百科:

「边信道攻击是基于从密码系统的物理实现获得的信息的任何攻击,而不是算法中的蛮力或理论弱点(相较于密码分析学)。例如,定时信息、功耗、电磁泄漏甚至声音都可以提供额外的信息源,这些信息可被用来破解系统。」

Spctr和Mltdown属于边信道攻击,通过定时来观察缓存中是否有另一个可访问的位置,以推断内存位置的内容,这些内容通常不应该被访问。

把它放在一起

现在让我们看看如何结合推测和缓存以允许类似Mltdown的攻击。考虑下面这个示例,它是一个有时读取所有非法(内核)地址的用户程序,并导致错误(崩溃):

t=a+bu=t+cv=u+difv:w=krn_mm[addrss]#ifwgthr,faultx=w0xy=usr_mm[x]

现在,假设我们可以训练分支预测器,使其相信v很可能是非零的,那么我们的无序双向超标量处理器就会混洗程序,像这样:

t,w_=a+b,krn_mm[addrss]u,x_=t+c,w_0xv,y_=u+d,usr_mm[x_]ifv:#faultw,x,y=w_,x_,y_#wnvrgthr

即使处理器总是推测性地读取内核地址,它必须推迟产生的错误,直到知道v是非零。从表面上看,这是安全的,因为:

v是零,所以非法读取的结果不会被提交给w

v是非零,但在读取结果被提交给w之前发生了错误

然而,假设我们在执行代码之前刷新缓存,并排列a、b、c、d以使v实际上为零。现在第三个循环中的推测性读取为:

v,y_=u+d,usr_mm[x_]

其将依赖非法读取结果的第八位获取用户地址0x或0x,并把地址及其近邻加载进缓存。由于v是零,推测性指令的结果将被摈弃,执行将继续。如果我们随后访问其中一个地址,就可以决定哪个地址在缓存之中。恭喜:你刚刚从内核地址空间读取了一个位!

真正的Mltdown实际上要比这更复杂(特别是,为了避免错误训练分支预测器,作者无条件地优先执行非法读取,并处理产生的异常),但原理是相同的。Spctr使用相似方法来颠覆软件阵列边界检查。

结论

现代处理器竭尽全力保持抽象,从而成为直接访问内存的有序标量机器,而事实上,使用包括缓存、指令重排序和推测在内的大量技术来提供比简单处理器更高的性能有望成为现实。Mltdown和Spctr就是当我们在抽象的语境中推理安全性,然后在抽象与现实之间遇到细微差别时会发生的事情的实例。

树莓派使用的ARM、Cortx-A7和Cortx-A53内核中推测的缺失使我们免于此类攻击。

机器之心发布首份《人工智能技术趋势报告》,纵览人工智能的23个分支技术。明晰历史发展路径,解读现有瓶颈及未来发展趋势。点击阅读原文,立即获取报告完整版。

赞赏

长按







































贵阳白癜风治疗中心
白癜风研究院



转载请注明地址:http://www.fupenzia.com/fzpj/1338.html
  • 上一篇文章:
  • 下一篇文章:
  • 热点文章

    • 没有热点文章

    推荐文章

    • 没有推荐文章