LWN:检测Intel CPU的split locks以及阻止攻击

640点击上方蓝色字关注我们~



Detecting and handling split locks

June 7, 2019

This article was contributed by Marta Rybczyńska


Intel的体系结构里面在某些情况下会允许非对齐的内存访问,而其他体系结构(ARM, RISC-V)都不支持。一个例子就是在对memory做atomic操作的时候,如果这个操作对象是分布在相邻的两个cache line上。这个能力对大多数人来说都很陌生,相应的带来的影响也更加少人知道。其实这个特性带来的性能和安全影响可能很大,会破坏实时性进程的实时性,或者让恶意进程能把整个系统拖慢。最近,Fenghua Yu就做了一些工作,能把这种情况检测出来饼解决。他提出的split-lock patchset已经发展到第八版了。


From misaligned memory accesses to split locks

misaligned memory(非对齐内存)的访问,主要是在CPU访问的内存地址没有对齐边界的情况。一个访问8字节的指令如果拿到的参数是4字节对齐的变量,就会出现这种情况。例如,对地址0x1008读取4个byte的指令,是一个aligned(对齐的)操作;而从0x1006读取4个byte就没有对齐。非对齐的访问,在各种体系架构里面会出现不同的现象,有可能仍然正确高效的执行完毕了,也有可能出现exception(异常)停止程序的执行,或者拿到错误结果。


哪怕处理器能透明的支持非对齐访问的操作,也很有可能会伴随着性能下降。例如CPU可能会把一个非对齐的访问分成两个内存访问操作。另一个可能性是处理器进入exception异常处理流程,然后交给kernel来处理好这个非对齐访问,然后再返回原程序继续执行。因此一个可移植性好、性能好的程序,应该要避免产生非对齐访问。kernel的代码规范(Documentation/unaligned-memory-access.txt)里面也提到开发者需要假设所有开发平台上面都需要保证满足对齐的要求。


有一类特殊的非对齐访问,就是占用了两个cache line的,这种可能会让处理器先读取多个cache line,然后再做真正的load/store操作。如果这里的操作是个atomic院子操作,那就更麻烦了,因为处理器需要保证数据的一致性。Intel平台上支持这种操作,专门称之为“split lock”。


在split lock情况下,各个CPU看到的数据必须要保持一致,也就是说两个cache line必须同时更改。对这种不太常见的操作,硬件设计上通常都是采用特殊逻辑来处理的,因此split lock一般都会带来各种后果,就像Yu的patch set里面提到的。Intel的做法是把整个memory bus都lock住,从而解决一致性问题。所谓的bus lock住,就意味着其他CPU或者外设都不能访问memory bus了。此外把bus lock住这个操作本身也会花费一些时间,也会带来一些全局性的性能损失。


相对应的,如果这个原子操作只需要访问一个cache line,那么只需要做一个轻量级的cache lock即可,这样只要软件开发人员把他们的变量配置成cache line对齐的,就能避免split lock,从而提升性能。


Split lock consequences

Yu解释了一下他为什么要做这个工作,主要是希望能达到硬实时(hard realtime),云计算,避免安全漏洞。最重要的一点,某些系统上会有可能让硬实时进程跑在某些CPU core上,其他普通优先级的task就运行在其他CPU上,这种环境里普通进程如果访问非对齐地址,split lock机制就会导致bus lock然后硬实时进程被拖慢,无法达到实时性要求。Yu指出,直到现在,这种复杂的实时进程都没法被很好的支持起来,原因就在于此,实时进程开发者没有办法避免其他的那些不可信的进程通过split lock来拖慢实时进程,因此没法部署这些硬实时方案。


云计算场景里,一个guest系统里的某个普通进程就可能导致其他CPU无法访问memory,从而让整个系统(包含很多个guest系统)的性能下降。同样的,恶意代码也能利用这个功能拖慢系统,实现DoS(denial-of-service)攻击。


Solutions

从即将发布的Tremont这一代Intel处理器开始,CPU会在split lock出现的时候生成一个exception异常(称之为“alignment check”,或者#AC)。此前的处理器就只支持对split lock统计一下发生个数(perf的sq_misc.split_lock counter就是这个统计数),从而方便debug,但是没有办法让系统马上响应、采取措施。Yu的工作依赖这些最新一代处理器里新加的这个exception机制。


在split lock发生的时候应该采取什么措施,是此前这组patch set在review过程中的一个焦点。目前版本的patch set主要关注在如何检测上。假如split-lock事件发生在kernel里面,就会报出一个warning,然后关闭当前CPU上的检测功能。在warning报出之后,导致split lock的那个指令仍会正常执行,然后系统也正常运行下去。此前讨论中大家一直在争使应该让系统进panic状态。理论上来说kernel里面只要发生了split lock就都是一个bug,应该被fix,不过这个bug应该还没有严重到需要让kernel立刻panic来处理的地步。


如果发生在用户态进程里面,情况就不一样了,这时缺省行为是让此进程收到一个fatal信号SIGBUS。这样这个进程作者就必须要先fix这个bug,才能成功让这个程序运行起来。如果split lock是由于系统固件导致的,那么也会让系统立刻hang住。开发者们做这个决定也是因为担心firmware作者不会去fix这个问题。


split-lock的检测功能缺省会被打开,不过系统管理员仍然能够控制这个功能的行为,可以在kernel启动的时候加上nosplit_lock_detect这个参数来关闭检测机制。也有一个sysfs接口能在运行时关闭这个机制(/sys/devices/system/cpu/split_lock_detect)。


这组patch set也支持了KVM。实现方法是在guest OS里面模拟这个寄存器,暴露这些配置接口。而host系统就要缺省把此功能打开。大家讨论后得出,对guest系统来说,如果host系统打开了这个机制,guest系统也就会缺省打开。这意味着只要host kernel打开了split lock监测并且guest触发了这个exception,那guest os就会立刻停止。另一种情况,如果host kernel关闭了检测机制,guest可以自己选择是打开还是关闭这个功能。


Further work

这个话题已经经过多轮讨论了,受到kernel developer的关注和多次回复,包括Thomas Gleixner和Ingo Molnar。还有一些遗留问题,不过看起来很有机会能合入mainline kernel(主线分支)了。


全文完

LWN文章遵循CC BY-SA 4.0许可协议。

极度欢迎将文章分享到朋友圈 
热烈欢迎转载以及基于现有协议上的修改再创作~


长按下面二维码关注:Linux News搬运工,希望每周的深度文章以及开源社区的各种新近言论,能够让大家满意~


640?wx_fmt=jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值