Linux LTS 版本内核 CPU Spectre 侧信道漏洞补丁剖析 | 申博官网
登录
  • 欢迎进入申博官网!
  • 如果您觉得申博官网对你有帮助,那么赶紧使用Ctrl+D 收藏申博官网并分享出去吧
  • 这里是申博官方网!
  • 申博官网是菲律宾sunbet官网品牌平台!
  • 申博开户专业品牌平台!

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

申博_新闻事件 申博 27次浏览 已收录 0个评论

经由过程这篇文章我将深入剖析近来的一个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 <linux/rcupdate.h>
  #include <linux/export.h>
  #include <linux/context_tracking.h>
 +#include <linux/nospec.h>
  
  #include <linux/uaccess.h>
  #include <asm/pgtable.h>
 @@ -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 < HBP_NUM) {
 -  struct perf_event *bp = thread->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内核中采纳的修复要领是经由过程简朴地交流递次:

印巴战役暗影下的收集战——近期印巴APT构造进击运动汇总

一、背景 印度和巴基斯坦同属于南亚地区的两个国家,但是由于一些历史原因,两国关系一直不大和睦,冲突不断。从2019年初开始,双方关系突然紧张,冲突升级。2月26日,印度空军飞越克什米尔印巴实际控制线,被巴基斯坦军方击落并俘获一名印度空军飞行员,同时这也是印度首次袭击巴基斯坦境内。前段时间两国在克什米尔印军队集结并且频繁交火,印方甚至水淹巴基斯坦,打开阿尔奇大坝,造成巴基斯坦面临洪水的危机,同时印方几日前公开宣称,可能会先对巴基斯

 +               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 < HBP_NUM) check
 .text:000000000000064C                 mov     rbp, rsp
 .text:000000000000064F                 jg      short loc_673
 .text:0000000000000651                 movsxd  rsi, esi ; rsi = sign-extended index
 .text:0000000000000654 ; rdx is 'bp' here, using rsi derived from user-provided one, with no speculation barrier
 .text:0000000000000654                 mov     rdx, [rdi+rsi*8+800h]
 .text:000000000000065C ; here begins the unused array_index_nospec()
 .text:000000000000065C                 cmp     rsi, 4 ; from arch/x86/include/asm/barrier.h asm volatile
 .text:0000000000000660                 sbb     rsi, rsi ; from arch/x86/include/asm/barrier.h asm volatile
 .text:0000000000000663                 xor     eax, eax ; fallout from arch/x86/include/asm/barrier.h asm volatile
 .text:0000000000000665                 test    rdx, rdx
 .text:0000000000000668                 jz      short loc_68F
 .text:000000000000066A                 mov     rax, [rdx+138h]
 .text:0000000000000671                 jmp     short loc_68F
 .text:0000000000000673 ; ---------------------------------------------------------------------------
 .text:0000000000000673
 .text:0000000000000673 loc_673:                                ; CODE XREF: ptrace_get_debugreg+7
 .text:0000000000000673                 cmp     esi, 6
 .text:0000000000000676                 jnz     short loc_681
 .text:0000000000000678                 mov     rax, [rdi+820h]
 .text:000000000000067F                 jmp     short loc_68F
 .text:0000000000000681 ; ---------------------------------------------------------------------------
 .text:0000000000000681
 .text:0000000000000681 loc_681:                                ; CODE XREF: ptrace_get_debugreg+2E
 .text:0000000000000681                 xor     eax, eax
 .text:0000000000000683                 cmp     esi, 7
 .text:0000000000000686                 jnz     short loc_68F
 .text:0000000000000688                 mov     rax, [rdi+828h]
 .text:000000000000068F
 .text:000000000000068F loc_68F:                                ; CODE XREF: ptrace_get_debugreg+20
 .text:000000000000068F                                         ; ptrace_get_debugreg+29 ...
 .text:000000000000068F                 pop     rbp
 .text:0000000000000690                 retn
 .text:0000000000000690 ptrace_get_debugreg endp

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如许的防备东西能够弥补个人的暂时手动修补留下的空缺,这确实是有优点的。

末了要说的是,上游社区的开辟者并没有发明这个破绽,这么多人都介入个中,因而应当存在许多机会来阻挠这类蹩脚的修复手艺被引入。但是,这个补丁破绽不仅被宣布,而且流传到了一切支撑的稳固内核中,这表明上游的开辟社区基础不像民众所以为的那样凶猛。

本文翻译自:https://grsecurity.net/teardown_of_a_failed_linux_lts_spectre_fix.php


申博|网络安全巴士站声明:该文看法仅代表作者自己,与本平台无关。版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明Linux LTS 版本内核 CPU Spectre 侧信道漏洞补丁剖析
喜欢 (0)
[]
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址