分享

轰动整个计算机领域的芯片问题,究竟是怎么回事?

 谁是及时雨 2018-01-13

在2017年年底的一个周末,来自奥地利格拉茨技术大学的一名研究员写出了一个程序,成功的从操作系统中最受保护的地方获取了自己网页浏览和私人邮件信息。由于这个漏洞源于芯片设计本身,他和他的同事们次日便将这个消息邮件告知了英特尔公司。一个星期后他们收到了英特尔公司的回复。原来他们已经不是第一个找到这个漏洞的人,而英特尔公司也已经在着手修复。为了不给黑客攻击的机会,双方答应了延缓这个发现的发表,直到新年伊始。


2018年1月2日,论文发表,英特尔、AMD和ARM的芯片同时被爆出安全问题。总结来说,这个芯片设计漏洞能够引起两种网络黑客攻击,分别是“崩溃(meltdown)”和“幽灵(spectre)”。


○ 英特尔芯片设计漏洞可能引起两种网络黑客攻击,分别是“崩溃”和“幽灵”。


“崩溃”是一种打破应用程序与操作系统之间隔离的攻击。在崩溃攻击下,软件就可以直接访问权限外的内存,从而调取其他应用程序和系统资源“幽灵”则是一种打破不同应用程序之间隔离的攻击。它可以让黑客进行伪装,骗过系统的检测,最终达到调取资源的目的。


这意味着什么呢?这意味着只要用电脑,理论上都可能受到安全攻击而且这个安全问题是根植在芯片的架构里,除非重新设计操作系统或者芯片,否则这个问题无法从根本上得到解决。而一切的原因,都源自于我们几十年来过于追求CPU的性能。


计算机架构


自从冯诺依曼在1945年提出了计算机架构至今的70多年的时间里,计算机的发展一直都基于这种架构。除了在晶体管层面上的发展,计算机架构师们也一直想方设法在架构上做文章,使程序运行更快。其中被沿用至今的包括多级储存(memory hierarchy)乱序执行(out-of-order execution)推测执行(speculative execution)



多级储存:


首先来说说多级储存。如上图所示,简单来说储存从离CPU由远到近可分为硬盘(Disk)内存(RAM)缓存(cache)寄存器(register)。储存大小和读取时间都是硬盘最大,然后依次递减。现在的计算机一般有512GB或者1TB容量的硬盘,16G或者8G的内存,以及几到十几MB左右的缓存。在这三级的储存中只有硬盘是非易失性记忆(non-volatile memory)。也就是说只有硬盘在计算机断电之后仍能储存数据。因此,我们平常需要的所有东西(启动程序除外)都储存在硬盘里。开机之后由启动程序开启操作系统,由操作系统将需要的数据从硬盘移到内存。而缓存的设计则是为了CPU能够更快的读取平时所需要的数据。


试想一下,假如你正在写一篇论文,需要在图书馆查找资料。你会把所需要的各种书从不同的书架上取下来放在桌上,然后再从中选一两本写当下章节需要常看的书放在手边以便随时翻阅。计算机架构的设计也遵从了这样一个原则。如果你是一个CPU,那么图书馆就是硬盘,放书所用的桌子就是内存,而你手边触手能即的地方就是缓存。而当你离开图书馆的时候,桌上和你手边的书也会被管理员清空并放回原本的书架上。由此可见,多级储存的设计目的就在于能让CPU能够尽量频繁的 “在触手可及的地方拿到需要的书”


乱序执行


再来说说乱序执行。所有程序最终都会被拆分成一条条的指令,由CPU逐个执行。然而每条指令所花的时间并不相同,比如你去图书馆书架上取书花的时间肯定比从手边拿书要长。最初的架构设计是让CPU按程序顺序依次逐个执行指令。然而这就出现了一个新的问题,如果一个指令需要花很长时间来执行(通常因为该指令没有获得足够多的执行资源),那么后面指令(无论再简单,需要花的时间再少)也必须等这条指令执行完之后才能开始执行。这就像在一条很窄的路上行车,如果前面有一辆车出了故障走不了,在这辆故障车等拖车来的这段时间里,后面的车也只好堵着。当然现实生活中我们基本不会遇到这样的情景。如果一辆车出了问题,它通常会靠边停车,在打双闪等拖车的同时,让后面的车能够顺利通过。而后来计算机架构的设计也遵从了这一理念。如果一条指令需要花很长时间才能完成执行,那么这条指令会被放到一个特殊的地方(reservation station),以便让CPU能够执行之后的指令。只有当放在reservation station的指令获得足够多资源执行的时候,该指令才会重新被执行。这就是被用在如今几乎所有芯片里的技术—乱序执行。


推测执行:


最后再来看看推测执行。假设你每晚放学必须要和你的朋友一起去吃个宵夜。你们通常都会去城东的烧烤店吃烧烤。当然,如果烧烤店人满为患,你们也会选择城北边的炸鸡店。那么问题来了,放学的时候你怎么知道烧烤店是否还有位子呢?当然你可以打电话去问,但是老板通常很忙,打个电话得等个20分钟才有回复。那么放学后的你现在应该何去何从呢?现在你之前的经验起了作用。如果你之前百分之八十的时候去烧烤店都是有座位的,那么你在放学打电话的这20分钟时间里,你完全可以在接到答复之前先往烧烤店走着,反正有百分之八十的机会你不用折返去城北。而整套机制放在计算机里就是推测执行。在CPU执行指令的时候通常都会遇到判定,如果判定为真则执行一部分代码,如果判定为伪,则执行另一段代码。而通常判定是需要等待很长时间。而现在的CPU都会根据之前的控制流预测判定的结果,在结果确定之前,CPU会执行预测结果指向的指令。如果预测对了,那么CPU则节省了等待判定结果的时间。如果预测错了,则CPU会从开始判定的位置重新接受新的,正确的指令。虽然倒回原点重新执行新的指令会比较耗时,但是如果之前预测的准确性很高,比如90%,那么这个结果还是可以接受的,毕竟总体上来说CPU执行指令还是省了不少时间。


上述三个架构上的技巧大大提高了CPU执行指令的效率。究其原理,主要就是使CPU能一直有事可做,不至于在那里空转浪费时间。然而,正是这三个几乎现在所有CPU都有的特性,导致了这次芯片安全性能的滑铁卢。在了解具体情况之前,我们还要了解一个操作系统的重要特性。


操作系统的特性


无论是什么操作系统都会在两个级别下运行,一个是用户级别(user mode),一个是系统级别(kernel mode)。而用户级别的优先级会低于系统级别。也就是说系统级别的资源在用户级别下是不能使用读取的。这样设置的原因是防止用户读取他不应该读取的信息,比如其他用户的密码。例如在程序的某个地方用户试图读取其权限外的数据,系统会自动从用户级别跳到系统级别,然后阻止用户读取该数据。这就像你要进别人家的门,但是密码输入错误,门是会自动锁住,不让你进。


然而乱序执行和推测执行改变了这一切。从根本上说,乱序执行可以暂时跳过一些指令直接执行后面的指令。而推测执行时,错误的推测可能让CPU直接执行一些权限外的指令。这就像你能在输入的门禁密码得到判定前先进别人家逛一圈,等密码判定为错,再请你出去,然后锁门。


从计算机架构上来看,如之前所述,计算机需要的数据都会提前存储在内存中以供读取。如果我们故意制造一个非法的数据访问,因为该操作访问了超过权限的内存,操作理应会被拒绝。然而因为乱序执行和推测执行的存在,这些非法操作可以在还没有被拒绝前执行。虽然最后这些非法操作最终会被系统拒绝并忽略(不对系统状态造成影响),但这些已执行过的非法访问的数据会因为多级储存的架构而留在缓存上面。通过简单的技术手段就可以反复推出真实的敏感数据。也就是说你输入的密码因为芯片的内部设计,可以被其他用户级别的程序直接获取。这就好比在图书馆有一列书架上的书是不允许学生借阅的,但因为图书管理员允许在身份确认前进入借阅,作为学生的你可以先进去把需要的书拿出来放到你的桌上。即使管理员最后确认了你的学生身份,禁止了你的权限,但这个时候你需要的书已经被拿了出来放在了你的桌上。即便你不主动去读,我们也不能阻止其他人偷偷去翻阅这本书。


所幸的是各大芯片公司对此早就在内部有了未公开的研究,爆出该问题的论文也是在各大公司有了更新和应对措施之后才被公之于众。各个公司都发布了自己的系统更新用于缓解该问题的严重性。但是值得注意的是,目前的补救办法只能通过操作系统的补丁来修复。而这些补丁会对芯片的性能带来从5%到30%不等的下降。而操作系统级别的修复只能缓解却不能被彻底解决这个安全问题,除非重新设计芯片结构或者操作系统。


从冯诺依曼架构确定至今的几十年时间里,我们似乎因为太在意芯片的性能而开发出了很多诸如上述的提高芯片运行效率的技术。然而被我们忽略的硬件级别的安全性却是隐藏在这下面更重要的特性。正所谓企者不立,跨者不行, 一味注重芯片性能的开发方式似乎走到了尽头。而更加根本的冯诺依曼架构是否还能按照之前的脚步继续发展,似乎也值得芯片架构师们深思。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多