Jos*_*ica 5 assembly x86-64 intel spectre
Intel CET(控制流执行技术)由两部分组成:SS(影子堆栈)和 IBT(间接分支跟踪)。如果您需要间接地转移到地方,你不能把一个endbr64由于某种原因,你可以抑制IBT单个jmp或call指令用notrack。是否有等效的方法来抑制单个ret指令的SS ?
对于上下文,我正在考虑这将如何与 retpolines 交互,其关键控制流程或多或少类似于push real_target; call retpoline; pop junk; ret. 如果没有办法为此抑制 SS ret,那么在启用 CET 时是否有其他方法让 retpolines 工作?如果没有,我们将有哪些选择?我们是否需要为所有内容维护两组二进制包,一组用于需要 retpolines 的旧 CPU,另一组用于支持 CET 的新 CPU?如果英特尔被证明是错误的,而我们最终仍然需要在他们的新 CPU 上使用 retpolines 呢?我们是否必须放弃 CET 才能使用它们?
在玩了一下程序集之后,我发现您可以将retpolines 与 CET 一起使用,但它不太理想。就是这样。作为参考,请考虑以下 C 代码:
extern void (*fp)(void);
int f(void) {
fp();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译它会产生gcc -mindirect-branch=thunk -mfunction-return=thunk -O3这样的结果:
f:
subq $8, %rsp
movq fp(%rip), %rax
call __x86_indirect_thunk_rax
xorl %eax, %eax
addq $8, %rsp
jmp __x86_return_thunk
__x86_return_thunk:
call .LIND1
.LIND0:
pause
lfence
jmp .LIND0
.LIND1:
lea 8(%rsp), %rsp
ret
__x86_indirect_thunk_rax:
call .LIND3
.LIND2:
pause
lfence
jmp .LIND2
.LIND3:
mov %rax, (%rsp)
ret
Run Code Online (Sandbox Code Playgroud)
事实证明,您只需将 thunk 修改为如下所示即可实现此目的:
__x86_return_thunk:
call .LIND1
.LIND0:
pause
lfence
jmp .LIND0
.LIND1:
push %rdi
movl $1, %edi
incsspq %rdi
pop %rdi
lea 8(%rsp), %rsp
ret
__x86_indirect_thunk_rax:
call .LIND3
.LIND2:
pause
lfence
jmp .LIND2
.LIND3:
push %rdi
rdsspq %rdi
wrssq %rax, (%rdi)
pop %rdi
mov %rax, (%rsp)
ret
Run Code Online (Sandbox Code Playgroud)
通过使用incsspq、rdsspq、 和wrssq指令,您可以修改影子堆栈以匹配对真实堆栈的更改。我使用Intel SDE测试了这些修改后的 thunk ,它们确实使控制流错误消失了。
这是个好消息。这是坏消息:
endbr64,我在 thunk 中使用的 CET 指令在不支持 CET 的 CPU 上不是 NOP(它们会导致SIGILL)。这意味着您需要两组不同的 thunk,并且需要使用 CPU 调度来根据 CET 是否可用来选择正确的 thunk。__x86_indirect_thunk_rax是否存在来解决这个问题endbr64,但这真的很不优雅,而且可能会很慢。| 归档时间: |
|
| 查看次数: |
826 次 |
| 最近记录: |