Arm64 Linux Kernel KPTI (Meltdown防御)方案解释

ZenonXiu修志龙

                                                                    MindShare思享                      1月17日

原创声明:未经作者许可,不许转载。本文纯属个人观点

Meltdown概述

Meltdown破坏了位于用户和操作系统之间的基本隔离,允许恶意代码访问内核内存,从而窃取其他应用程序以及OS数据。这个漏洞“熔化”了由硬件来实现的安全边界。低权限用户级别的应用程序能利用它“越界”间接获取内存数据。

Meltdown 允许能够在存

在漏洞的处理器上运行代码,

获得整个内核的数据。 Meltdown 的根本

原因是推测性和乱序执行造成的。 

有关Meltdown的介绍文章已经有很多,在本文中不再赘述.

本文主要说明arm64 Linux kernel是如何通过KPTI(Kernel Page Table Isolation 技术来解决Meltdown的问题。

需要说明的是,在Meltdown和Spectre问题爆发之前,Arm已经有计划利用KPTI (Kaiser)技术实现KASLR(Kernel Address Space Layout Randomization).  Kaiser 防御机制具有阻

止 Meltdown攻击的作用.

Meltdown on Arm processor

Arm

Cortex-A processors 中只有Cortex-A75受到Meltdown(Variant3) 的影响,Cortex-A75

DynamIQ处理器是目前Arm公布的最高性能的处理器(所以out of order最多). 在Arm的security

whitepaper里Meltdown对应的是Variant 3 和 3a. KPTI是针对variant 3. 因为3a

只能读到部分更高EL的system registers(不能改写), 到目前为止,还没有能利用这个实现攻击的办法. 

并且Cortex-A75也不受3a影响。

White paper 可以从这里下到 https://developer.arm.com/support/security-update/download-the-whitepaper 

问题描述:

Cortex-A75在更低的EL(比如user

application in EL0)时,可以speculatively去访问更高EL(比如kernel in

EL1)才有访问权限的数据,虽然最终application代码不能通过load/store指令得到kernel的data(最终如果这个load被architectually执行会触发MMU访问权限fault,

导致segment fault), 但是speculation已经将某些数据带到cache里,通过精心设计的cache

FLUSH+RELOAD 侧边道攻击,可以通过间接手段得到kernel的数据。

所以这个问题的发生由 (在低特权级的ELspeculative access 更高EL数据)+(精心设计的低特权级代码)+(Cache FLUSH+RELOAD side channel attack)来触发的。

参考white paper 提供的代码

在EL0,有下面代码

1  LDR X1, [X2] ; 精心设计这个load产生cache miss, 以便CPU会speculative做 4和7的访问

2  CBZ X1, over ; 这个跳转按代码逻辑会跳

3               ; 但是CPU预测不跳

4  LDR X3, [X4] ; X4指向只能kernel访问的kernel space地址

5  LSL X3, X3, #imm

6  AND X3, X3, #0xFC0  ;移位成 probe buffer的offset7  LDR X5, [X6,X3] ; X6 是user application可以访问的地址,用来做cache side

;channel attack 的probe buffer8 over

1.首先 用Cache FLUSH+RELOAD的办法讲probe buffer对应的数据都从cache 赶出去。

2. 制作条件(让上面1对应的load miss in cache)

3. 执行以上代码

3. 因为Speculation, CPU会speculatively load 以上代码的4和7,因为是speculation, 指令不会retire和回写到X3和X5. 但是数据可以带进cache.

  比如如果kernel数据是1的话,在probe buffer 里offset 为0x1000对应的数据会进cache

  如果kernel数据是0的话,在probe buffer 里offset 为0x0000对应的数据会进cache

4. 如果最终architectually 执行 

4  LDR X3, [X4]

会导致访问权限segment fault.

5. 攻击者可以以cache line size 为stirde遍历访问probe buffer的数据, 并测量每个访问时间,如果那个访问时间短,说明其数据已经在cache 里面。再利用step3,可以反推出kernel data是 0还是1.

比如如果对probe buffer offset 为0x000的数据访问时间短,那么可推出kernel data是0

比如如果对probe buffer offset 为0x000的数据访问时间短,那么可推出kernel data是1

理解上面的内容需要对CPU设计有比较好的理解,因为本人一直支持Arm 构架和CPU, 所以理解并不费事。

为了帮助理解,贴一个我认为最接近的比喻,

我们把CPU比做学校食堂,把黑客比作两个男生A,B,用户则是女神。

这天,男生A,B总要想办法获得女神的一点私密信息——比如,女神今天午饭吃的啥~

中午,女神来到食堂打饭,点了一份小笼包。

男生A在女神后面跟食堂大娘说:我也来一份,跟她一样的~

然而这会食堂大娘表示,你等会,你前面还有人哦。

好吧,虽然说是这么说,但是后面的厨房师傅已经听到了对话,已经提前开始准备好了另一份小笼包.....

后来女神点好走了,轮到男生A点,他表示,我要一个跟她一样的...

然而这会,

食堂大娘表示,人家是人家,你是你,我们不能透露女神隐私喔,你可以走了,下一个! (这就是目前CPU的内置的安全防线)

然而!

当下一个男生B走到食堂大娘面前,直接说:随便,哪道菜最快给我上哪道...

于是乎,既然之前厨房师傅已经提前多准备好了一份小笼包,就干脆直接把小笼包给了男生B....

这下男生知道了,女神中午吃了小笼包......

关键信息,就这么被泄露了,

虽然以上比喻中有很多不贴切

并没有关键的用kernel data作为 probe buffer index部分。。。

男生和女生的包子应该是隔离的

Meltdown 防御 on Arm64 Linux

接下来的内容假设大家对Arm Linux 比较熟悉。

通过以上分析,我们知道了这个问题最关键的地方是,

在EL0运行application时,application

speculatively访问kernel address时, MMU可以做这个地址转换,MMU

hardware并不检查访问权限,只做VA到PA的地址转换. 得到PA后可以做memory access到cache中。

有人会问,为什么MMU不做访问权限检查,地址转换同时做访问权限检查不是随便可以做的事情吗?对software

engineer来说好像工作并不多,但是对CPU的设计者来说,在RTL关键路径(critical

path)上作一些看似不多的工作会带来后端综合的timing收敛的问题,影响到CPU可以跑到的最高频率。

并且现代CPU的设计也不能禁止 speculation, out of order,我们不能因噎废食,否则性能可能一夜回到解放前。

解决方案是什么呢? 方法就是,

在运行user

application 的时候,将kernel mapping 减少到最少,只保留必须的user到kernel的exception entry

mapping. 其他的kernel mapping 在运行user application时都去掉,变成无效mapping,

这样的话,如果user访问kernel data, 在MMU地址转换的时候就会被挡掉(因为无效mapping).

设计方面就是设计一个trampoline 的kernel PGD给运行user时用。

Trampoline kernel mapping PGD只包含exception entry必需的mapping.

当user

通过系统调用,或是timer或其他异常进入kernel是首先用trampoline的mapping,

接下来tramponline的vector处理会将kernel mapping 换成正常的kernel mapping

(SWAPPER_PGD_DIR), 并直接跳转到kernel原来的vector entry, 继续正常处理。

我们把上述过程称之为map kernel mapping.

当从kernel返回到user时,正常的kernel_exit会调用trampoline的exit,tramp_exit会重新将kernel mapping 换成是trampoline. 这个过程叫unmap kernel mapping.

相关代码请看Will Deacon 的patch set

[v2,13/18] arm64: entry: Hook up entry trampoline to exception vectors- - -2017-11-30Will DeaconNew

[v2,12/18] arm64: entry: Explicitly pass exception level to kernel_ventry macro- - -2017-11-30Will DeaconNew

[v2,11/18] arm64: mm: Map entry trampoline into trampoline and kernel page tables- - -2017-11-30Will DeaconNew

[v2,10/18] arm64: entry: Add exception trampoline page for exceptions from EL0

https://patchwork.kernel.org/patch/10085275/

如果大家对Arm MMU, TLB工作原理比较熟悉的话,可能会进一步想到一个问题。User和kernel的translation是共享同一TLB 硬件的。

大家知道MMU会现在TLB里lookup,

我们需要避免user application发出的kernel address可以在TLB

hit,因为TLB中可能已经有了用过的SWAPPER_PGD_DIR mapping的entry.

在KPTI之前kernel的mapping都是global(不匹配ASID). User application发出的kernel

address translation可以直接在TLB hit。这样的话KPTI的translation table隔离机制就不work了。

这个问题可以用在kernel和user切换时对整个TLB invalidate,但是代价很高,我们要避免。

怎么处理呢?KPTI会

1. 给kernel space 也分配ASID,kernel mapping也变成和userspace一样的non global mapping.

2. kernel分配ASID的时候,分出一个奇偶ASID对,kernel用偶的,user用奇的,从2开始分。比如kernel ASID 2, user ASID3 或kernel ASID 4, user ASID 5.

这样的话因为运行在user时的ASID和kernel时的ASID不一样,user发出的地址没法hit到kernel的TLB entry。

这个问题会在后面的图示里表达比较清楚。

代码请参照  Will Deacon patch set

[03/18] arm64: mm: Move ASID from TTBR0 to TTBR1- - -2017-11-17Will DeaconNew

[02/18] arm64: mm: Temporarily disable ARM64_SW_TTBR0_PAN- - -2017-11-17Will DeaconNew

[01/18] arm64: mm: Use non-global mappings for kernel space

[07/18] arm64: mm: Allocate ASIDs in pairs- - -2017-11-17Will DeaconNew

[06/18] arm64: mm: Fix and re-enable ARM64_SW_TTBR0_PAN

需要说明的是,虽然trampoline是个聪明的办法,但是KPTI的开发还在演化中,以后可能会有变化。

Arm64 KPTI 图示

代码可以大家去看,但是看懂代码需要对Arm 构架和Linux kernel要比较了解。

为了帮助大家理解,我连夜画了几个图。

图1 没有KTPI时运行在user application的地址转换和访问

图2 没有KTPI时运行在kernel的地址转换和访问

图3 有KTPI时运行在user application的地址转换和访问

图4  有KTPI时运行在kernel的地址转换和访问

图5 Trampoline工作流程

总结

Arm64 Linux KPTI巧妙地通过trampoline以最小kernel改动实现了Meltdown的防御。

KPTI可以通过enable一下kernel configuration来开关。

UNMAP_KERNEL_AT_EL0

Kernel patch set可以在这里找到,

https://patchwork.kernel.org/project/linux-arm-kernel/list/?submitter=will+deacon

Meltdown(variant 3) 只对Cortex-A75有影响。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容