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%不等的低落。而操作系统级别的修复只能缓解却不能被彻底办理这个安全问题,除非重新设计芯片构造或者操作系统。
从冯诺依曼架构确定至今的几十年韶光里,我们彷佛由于太在意芯片的性能而开拓出了很多诸如上述的提高芯片运行效率的技能。然而被我们忽略的硬件级别的安全性却是隐蔽在这下面更主要的特性。正所谓企者不立,跨者弗成, 一味看重芯片性能的开拓办法彷佛走到了尽头。而更加根本的冯诺依曼架构是否还能按照之前的脚步连续发展,彷佛也值得芯片架构师们寻思。