Google的Project Zero继”The poisoned NUL byte, 2014 edition”后再次向公众展示一个看起来极度难以利用但实际又能利用成功的漏洞,rowhammer漏洞在Yoongu Kim et al的论文中谈到今天的DRAM单元为了让内存容量更大,所以在物理密度上更紧凑,但这样很难阻止临近的内存单元之间的电子上的互相影响,在足够多的访问次数后可以让某个单元的值从1变成0,或者相反。目前Google Project Zero的研究人员 Mark Seaborn和Thomas Dullien已经成功的在x86-64的GNU/Linux平台上利用这个漏洞通过CLFLUSH指令和PTEs(page table entries)的某一位的变化(比如0到1)直接获得内核权限,研究人员认为在其他的硬件架构和操作系统上也有类似的方法可以达到这一目的,解决这个漏洞的修复可能需要BIOS更新针对内存控制器部分的操作。
在Yoongu Kim et al的论文中谈到了关键的原理:
code1a:
mov (X), %eax // Read from address X mov (Y), %ebx // Read from address Y clflush (X) // Flush cache for address X clflush (Y) // Flush cache for address Y jmp code1a
两个因素导致位的变化:
1,地址选择:地址X和地址Y必须印射到内存的不同row但是又是在同一bank上。
每个DRAM芯片包含了很多行(row)的单元。访问一个byte在内存中涉及到将数据从row传输到芯片的”row buffer”中(放电操作),当读取或者写入row buffer的内容后,再把row buffer内容传输到原来的row单元里(充电操作)。这种”激活“一个row的操作(放电和充电)可以干扰到临近的row。如果这样做足够多的次数,临近row的自动刷新操作(一般是每64ms)可能会让临近row的位产生变化。row buffer作为缓存,如果地址X和Y指向相同的row,那code1a将会从row buffer中读取信息而不用任何”激活“操作。
每个DRAM的bank都有自己的”当前已激活的row”,所以如果地址X和地址Y指向不同的bank,code1a将会从那些bank的row buffer中读取信息而不用反复的激活row。所以,如果地址X和地址Y指向同一bank上不同的row,code1a会导致X和Y不断的被激活,这被称为ROWHAMMERING。
2,绕过缓存:没有了code1a中的CLFLUSH指令的话,内存读操作(mov)只会操作CPU的缓存。CLFLUSH刷新缓存的操作强制让内存的访问直接指向DRAM,而这会导致不断有row被重复的激活。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/49451.html