首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在x86_64中使用clang-8的“影子调用栈”特性?

如何在x86_64中使用clang-8的“影子调用栈”特性?
EN

Stack Overflow用户
提问于 2019-12-11 16:31:28
回答 1查看 317关注 0票数 4

最近,我尝试在x86_64中测试clang-8的“影子调用堆栈”特性。但是当我运行“影子”程序时,即使它是一个"Hello_World“程序,它也总是抛出分段错误。我的编译命令是"clang-8 -fsanitize=shadow-call-stack malom.c“。“normal.c.c”只是一个简单的hello_world c程序:

代码语言:javascript
复制
#include <stdio.h>
int main(int argc, char *argv[])
{
    printf("Hello World!\n");
    return 0;
}

main函数的汇编代码如下:

代码语言:javascript
复制
   0x0000000000401130 <+0>: mov    (%rsp),%r10
   0x0000000000401134 <+4>: xor    %r11,%r11
   0x0000000000401137 <+7>: addq   $0x8,%gs:(%r11)
   0x000000000040113c <+12>:    mov    %gs:(%r11),%r11
   0x0000000000401140 <+16>:    mov    %r10,%gs:(%r11)
   0x0000000000401144 <+20>:    push   %rbp
   0x0000000000401145 <+21>:    mov    %rsp,%rbp
   0x0000000000401148 <+24>:    sub    $0x20,%rsp
   0x000000000040114c <+28>:    movl   $0x0,-0x4(%rbp)
   0x0000000000401153 <+35>:    mov    %edi,-0x8(%rbp)
   0x0000000000401156 <+38>:    mov    %rsi,-0x10(%rbp)
   0x000000000040115a <+42>:    movabs $0x402004,%rdi
   0x0000000000401164 <+52>:    mov    $0x0,%al
   0x0000000000401166 <+54>:    callq  0x401030 <printf@plt>
   0x000000000040116b <+59>:    xor    %ecx,%ecx
   0x000000000040116d <+61>:    mov    %eax,-0x14(%rbp)
   0x0000000000401170 <+64>:    mov    %ecx,%eax
   0x0000000000401172 <+66>:    add    $0x20,%rsp
   0x0000000000401176 <+70>:    pop    %rbp
   0x0000000000401177 <+71>:    xor    %r11,%r11
   0x000000000040117a <+74>:    mov    %gs:(%r11),%r10
   0x000000000040117e <+78>:    mov    %gs:(%r10),%r10
   0x0000000000401182 <+82>:    subq   $0x8,%gs:(%r11)
   0x0000000000401187 <+87>:    cmp    %r10,(%rsp)
   0x000000000040118b <+91>:    jne    0x401192 <main+98>
   0x0000000000401191 <+97>:    retq   
   0x0000000000401192 <+98>:    ud2

当我运行这个程序时,它抛出:

代码语言:javascript
复制
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401137 in main ()

clang-8 documentation中,它标识了使用x86的gs寄存器的这个特性。但实际运行表明存在一些问题。是gs寄存器的问题吗?有谁可以帮我?提前谢谢。

EN

回答 1

Stack Overflow用户

发布于 2019-12-11 17:29:32

问题是,运行时环境必须将gs寄存器初始化为指向可以存储影子调用堆栈的位置。这并不是很明确地说,但可以从the Clang documentation派生

ShadowCallStack目前仅支持x86_64和aarch64。编译器-rt中目前没有提供运行时,因此必须由编译的应用程序提供运行时。

使用标准运行时,gs寄存器不会指向任何地方,因此写访问失败,并出现分段错误。Android libc提供了这样的运行时。

然而,影子调用堆栈功能不仅被认为是低效的,而且在x86_64上也是不安全的,并在以后的版本中被删除。如果你真的想使用这个功能,你应该仔细考虑。如果您仍然这样做,那么您必须准备好运行时环境,并正确初始化gs寄存器。

有一个syscall arch_prctl() (没有被libc包装),可以用来设置gs寄存器:

代码语言:javascript
复制
arch_prctl(ARCH_SET_GS, baseaddr);

这可能是一个很好的开始,但在填充影子调用堆栈之前(即在main()之前),必须调用它。一个不错的做法是在_start()函数中对其进行初始化,该函数通常位于单元crt1.o或类似单元中。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59281598

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档