欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

Linux LTS 版本内核 CPU Spectre 侧信道漏洞补丁分析

来源:本站整理 作者:佚名 时间:2019-09-10 TAG: 我要投稿

通过这篇文章我将深入分析最近的一个Specter漏洞补丁程序,其中一个补丁是手动打到Linux内核中的。我将介绍此修复程序所采取的方法,从其发出警告到向后移植到Long Term Support (LTS) kernels时被破坏。我们将研究后端漏洞的原理以及导致这种backporting失败的upstream过程中的bug。还会介绍我们是如何独立挖到此漏洞的以及我们的Respectre插件是如何自动修复这个底层漏洞的。
我能够找到的最早版本的补丁程序是来自于Dianzhang Chen的这个补丁,它是在2019年5月24日被发布的。它通过ptrace系统调用来解决具有用户控制索引的数组的推测访问。最初的解决方案还是挺好的,但Thomas Gleixner提出补丁可以被绕过,一个月后,他们又发布了补丁的第二个版本。
由于补丁的细节很重要,我做了一个比较:
 diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
 index a166c96..cbac646 100644
 --- a/arch/x86/kernel/ptrace.c
 +++ b/arch/x86/kernel/ptrace.c
 @@ -25,6 +25,7 @@
  #include
  #include
  #include
 +#include
 
  #include
  #include
 @@ -643,9 +644,11 @@ static unsigned long ptrace_get_debugreg(struct task_struct *tsk, int n)
  {
   struct thread_struct *thread = &tsk->thread;
   unsigned long val = 0;
 + int index = n;
 
   if (n ptrace_bps[n];
 +  index = array_index_nospec(index, HBP_NUM);
 +  struct perf_event *bp = thread->ptrace_bps[index];
 
    if (bp)
     val = bp->hw.info.address;
可以看到,代码块的开头在声明bp指针之前初始化了索引变量。
这导致下面的编译器警告:
 arch/x86/kernel/ptrace.c: In function 'ptrace_get_debugreg':
 arch/x86/kernel/ptrace.c:705:3: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
    struct perf_event *bp = thread->ptrace_bps[index];
    ^~~~~~
尽管有这个警告,但这段代码被逐字地合并到了Thomas Gleixner的x86 / tip tree中,可以在这里看到。此前合并的5.3-RC1的补丁,Linus Torvalds发现警告的LKML邮件列表。但是,当对tree做实际合并时,没有提到对补丁的更新。
LTS内核中采用的修复方法是通过简单地交换顺序:
 +               struct perf_event *bp = thread->ptrace_bps[index];
 +               index = array_index_nospec(index, HBP_NUM);
为了解释为什么说这个补丁是失效的,先看一下array_index_nospec()API。此函数获取索引值以及索引的第一个较大的越界值。如果不使用条件控制流,它会将该索引转换为原始索引值(如果在边界内)或零(如果超出边界)。通过确保原始索引的所有后续使用改为使用从此API返回的值,可以防止具有越界索引值的推测路径的破坏。
但是,在索引array_index_nospec ()宏之前,“index”用作ptrace_bps数组的索引。此外,由于“索引”在函数中没有后续使用,整个array_index_nospec()操作通常被编译器视为dead store,并通过称为死存储消除(DSE)的优化传递消除。由于在执行array_index_nospec()的某些内联汇编中使用了“volatile”关键字,后一种效果最终不会发生。
我们可以通过查看函数的反汇编来看下一:
 .text:0000000000000648 ptrace_get_debugreg proc near           ; CODE XREF: getreg32+EF
 .text:0000000000000648                                         ; arch_ptrace+6E
 .text:0000000000000648                 push    rbp
 .text:0000000000000649                 cmp     esi, 3 ; esi = index (or n), this is the if (n
Respectre编译器插件是世界上最先进,最有效,最高效的防御 CPU Spectre 侧信道攻击的工具。该插件使用高级静态分析自动查找潜在的Specter实例,并通过高性能检测消除它们。值
通过获取当前代码并修复漏洞后,可以得到以下输出:
 arch/x86/kernel/ptrace.c: In function 'ptrace_get_debugreg':
 arch/x86/kernel/ptrace.c:717:22: note: Spectre v1 array index bound '3'
    struct perf_event *bp = thread->ptrace_bps[n];
                       ^
 arch/x86/kernel/ptrace.c:717:22: note: Spectre v1 array index mask adjust: inc constbound: yes
我们为客户提供像Respectre这样的防御工具可以填补个人的临时手动修补留下的空白,这确实是有好处的。
最后要说的是,上游社区的开发者并没有发现这个漏洞,这么多人都参与其中,因此应该存在很多机会来阻止这种糟糕的修复技术被引入。然而,这个补丁漏洞不仅被发布,而且传播到了所有支持的稳定内核中,这表明上游的开发社区根本不像公众所认为的那样厉害。
 

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载