[linux][kernel]meltdown攻击和retpoline防御分析

前言: Intel爆出来的漏洞,搞了一个大新闻,然后Linus也对Intel的补丁批判了一番。 关于meltdown攻击的原理,以及retpoline防御,见下文。 分析: 1,MMU & CPU Cache & CPL & spectulative exection & Syscall 有几个关键的概念需要说明: MMU,Memory Management Unit。在CPU(本文的CPU默认是x86)跑在protected mode下的时候,使用的是虚拟地址,MMU是一个硬件,负责把虚拟地址翻译成虚拟地址。同时,也会处理一些异常情况,例如,在进程访问空指针的时候,MMU会产生异常,交给CPU处理。 CPU Cache,CPU访问内存的速度相对于CPU的主频,是比较慢的。为了加速CPU访问速度,在CPU和内存之间,有了CPU cache。在Linux上执行lscpu,可以看到L1,L2,甚至L3的大小。根据局部性原理,CPU在短时间内访问较小的地址范围,CPU cache把当前访问的地址加载到cache中,会加速CPU的访问。 CPL,Current Privilege Level。Linux使用0和3两个特权级,分别表示内核态和用户态。区别就是内核态有更高的访问权限,可以访问所有地址。用户态的权限比较低,只能访问用户态地址空间。否则,CPU就会产生异常,kernel处理异常的时候发现,访问的权限超出,给进程发送signal 11,也就是常说的segmentation fault。 spectulative exection。当代CPU大多都具有一定的预执行能力,用来提高指令的执行效率。作者曾经做过实验,在主频差不多的情况下,x86的E5和arm a53上分别跑redis,跑分结果x86差不多是arm的4倍。这里面,x86的分支预测明显是优于arm的。 Syscall,系统调用。用户态(CPL3)请求内核服务的时候,需要陷入到内核态(CPL0)。内核处理完成后,再返回用户态(CPL3)。在这期间,是有一段时间,CPU是处于内核态的。 上面的概念,是这次meltdown攻击的基础。另外,https://meltdownattack.com/meltdown.pdf 这里有一篇更加详细的论文。 2,spectulative exection

如上文的程序流,在触发了exception之后,进入内核态来处理异常,再exception handler中处理。正常的程序流中不会执行到右侧灰色的指令。但是,因为CPU的spectulative exection,灰色的指令片段会被执行CPU偷偷的执行,而且,是以内核态的权限来执行(因为它的上一条指令,触发了exception,已经进入了内核态)。 这部分灰色的代码片段,就是meltdown攻击可以做文章的地方。 3,meltdown attack 在攻击之前,在用户态声明一个数组probe_array[256][4096]。再来看下文:

把这段放到灰色的代码片段中,如果CPU投机执行了这一段会发生什么: 第1行,把想要攻击的内核地址放到rcx中;这个地址本不能被用户态访问到,但是因为exception已经陷入到内核态,这段将会以内核态权限执行。 第2行,把刚刚声明的用户态数组probe_array的地址放到rbx中; 第4行,把rcx的数值放到al中;也就说,把想要攻击的内核地址的数据,取出来1个byte,放到了al中。想必读者朋友们还记得大学时候,课本中的al表示ax的低八位,ah表示ax的高八位吧。假设这个地址的数据是0x10,也就是十进制的16。 第5行,把rax里面的数值左移12位;也就是16 × 4096。 第7行,rbx+rax的地址上的数值放到rbx中。实际上,就是访问了probe_array[16][0]这个地址。 这段代码投机执行完,看起来没有发生什么,而且,CPU的分支也会回滚掉刚刚的操作。寄存器中也不会有这段代码执行的残留。 但是!!! 因为访问过probe_array[16][0],CPU的cache中会加载过probe_array[16][0]。 如果执行下面的代码: for (index = 0; index < 256; index++) { tsc0 = rdtsc(); dummy = probe_array[indx][0]; tsc1 = rdtsc(); } 用tsc来计量更加精确的时间,会发现:只有index等于16的时候,tsc1-tsc0的会非常短,因为它可以直接命中CPU cache!!! 作者在实验环境上测试,如果命中了cache,两次tsc的差值差不多几十。而其他没有命中cache的两次tsc差值差不多是千这个量级的。根据时间的巨大差异,就能判断出来命中cache与否。这样就可以dump出来要攻击的内核地址的数据是0x10。依次类推。 作者使用PC测试的,和服务器的CPU会有差异,具体的表现上,是否命中cache,基本就是几十倍的访问速度差异。 4,retpoline 作者在前文《[linux][retpoline] retpoline技术分析》中分析了retpoline的具体实现,在结合上文的例子中,看看是如何防止meltdown攻击的。

上文攻击的重点,是灰色的代码片段的投机执行。用户在灰色代码片段中埋入攻击代码,实现的dump内核数据。那么retpoline的解决方案,就是防止灰色代码的投机执行。如下图:

打开了RETPOLINE配置之后,并不是直接执行的系统调用的handler。

而是让预测分支执行pause和lfence。 从而避免了CPU投机执行攻击的代码。同时,也避免了CPU投机执行正常的用户代码。性能会有一点点牺牲。 5,影响 以作者的愚见,对于IaaS层,升级kernel,打开retpoline是逃不掉的,毕竟公有云的安全第一。 作者在4.14上,打开RETPOLINE的前后对比测试,redis的性能下降了不到5%。因为redis是全内存性数据库,对于网络IO的处理,需要频繁的和内核进行数据交换,几乎是能受到影响的极限;其他CPU密集型的服务,影响更小。 对于SaaS服务,或者对性能要求极高的网络服务,对这个补丁的要求并不高。以http服务为例,毕竟只是提供GET,PUT,DELETE方法等,并不会执行用户的代码。例如redis,对外提供命令,同样也不会执行到用户代码。

原文发布于微信公众号 - AlwaysGeek(gh_d0972b1eeb60)

原文发表时间:2018-02-04

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏pangguoming

浅谈分布式数据库

文章集中整理总结mysql分库分表开源产品,分布式数据库的设计,以及实际应用案例等相关内容,部分附上本文作者实际应用过程中的理解。

1.1K20
来自专栏Java后端技术栈

记一次解决业务系统生产环境宕机问题!

Zabbix告警生产环境应用shutdown,通过堡垒机登入生产环境,查看应用容器进程,并发现没有该业务应用的相应进程,第一感觉进程在某些条件下被系统杀死了,然...

9810
来自专栏jeremy的技术点滴

开发者的博客写作环境

29870
来自专栏恰童鞋骚年

NoSQL初探之人人都爱Redis:(1)Redis简介与简单安装

  随着互联网Web2.0网站的兴起,传统的关系数据库在应付Web2.0网站,特别是超大规模和高并发的SNS类型的Web2.0纯动态网站已经显得力不从心,暴露了...

12320
来自专栏Java成神之路

Java程序员常用工具集

我发现很多人没办法高效地解决问题的关键原因是不熟悉工具,不熟悉工具也还罢了,甚至还不知道怎么去找工具,这个问题就大条了。我想列下我能想到的一个Java程序员会用...

16330
来自专栏FreeBuf

MacOS再次出现漏洞,号称牢不可破的系统也有弱点

本文讲述了我在苹果的macOS系统内核中发现的几个堆栈和缓冲区溢出漏洞,苹果官方将这几个漏洞归类为内核中的远程代码执行漏洞,因此这些漏洞的威胁级别非常高。攻击者...

11020
来自专栏新智元

入坑搞定Python多种任务,Go 1.11 新版本正式发布!

新版本在工具链、运行时和库等方面有很多变化和改进,兼容性方面也依然会兼容旧版本。此外,新版本增加了两个最激动人心的新特性:对模块(modules)和WebAss...

17010
来自专栏后端技术探索

\bmysql5.7 再不升就out了

Mysql 5.7的GA版本在10月末已经发布了,有个大牛进行了性能测试,对比5.6版,每秒查询数增加了一倍,达到50w/s. 堪称是mysql史上的又一大里...

11340
来自专栏一名合格java开发的自我修养

kafka0.8--0.11各个版本特性预览介绍

kafka-0.8.2 新特性 producer不再区分同步(sync)和异步方式(async),所有的请求以异步方式发送,这样提升了客户端效率。produc...

8520
来自专栏杨建荣的学习笔记

MySQL 5.6, 5.7并行复制测试(r12笔记第9天)

对于主从延迟,其实一直以来就是一个颇有争议的话题,在MySQL阵营中,如果容忍一定的延迟的场景,通过主从来达到读写分离是个很不错的方案,但是延迟率到底有多...

45680

扫码关注云+社区

领取腾讯云代金券