c - 该机器代码如何防止缓冲区溢出?

标签 c gcc assembly stack-overflow machine-code

以下是三个不同 .s 文件的一部分。 .c 文件已使用三个不同的选项进行编译:

  1. -fno-inline -fstack-protector-strong,
  2. -fno-inline -fsanitize=地址,
  3. -fno-inline -fno-stack-protector -zexecstack。

以下是.s文件的内容:

handle_read:
.LFB20:
    .cfi_startproc
    pushq   %r12
    .cfi_def_cfa_offset 16
    .cfi_offset 12, -16
    pushq   %rbp
    .cfi_def_cfa_offset 24
    .cfi_offset 6, -24
    movq    %rsi, %r12
    pushq   %rbx
    .cfi_def_cfa_offset 32
    .cfi_offset 3, -32
    movq    8(%rdi), %rbx
    movq    %rdi, %rbp
    movq    160(%rbx), %rsi
    movq    152(%rbx), %rdx
    cmpq    %rdx, %rsi
    jb      .L394
    cmpq    $5000, %rdx
    jbe     .L421

handle_read:
.LASANPC20:
.LFB20:
    .cfi_startproc
    pushq   %r15
    .cfi_def_cfa_offset 16
    .cfi_offset 15, -16
    pushq   %r14
    .cfi_def_cfa_offset 24
    .cfi_offset 14, -24
    pushq   %r13
    .cfi_def_cfa_offset 32
    .cfi_offset 13, -32
    pushq   %r12
    .cfi_def_cfa_offset 40
    .cfi_offset 12, -40
    pushq   %rbp
    .cfi_def_cfa_offset 48
    .cfi_offset 6, -48
    movq    %rdi, %rbp
    addq    $8, %rdi
    pushq   %rbx
    .cfi_def_cfa_offset 56
    .cfi_offset 3, -56
    movq    %rdi, %rax
    shrq    $3, %rax
    subq    $24, %rsp
    .cfi_def_cfa_offset 80
    cmpb    $0, 2147450880(%rax)
    jne     .L1170
    movq    8(%rbp), %rbx
    leaq    160(%rbx), %r13
    movq    %r13, %r15
    shrq    $3, %r15
    cmpb    $0, 2147450880(%r15)
    jne     .L1171
    leaq    152(%rbx), %r14
    movq    %rsi, %r12
    movq    160(%rbx), %rsi
    movq    %r14, %rax
    shrq    $3, %rax
    cmpb    $0, 2147450880(%rax)
    jne     .L1172
    movq    152(%rbx), %rdx
    leaq    144(%rbx), %rcx
    cmpq    %rdx, %rsi
    jb      .L1054
    cmpq    $5000, %rdx
    jbe     .L1055
    movl    $httpd_err400form, %eax
    shrq    $3, %rax
    cmpb    $0, 2147450880(%rax)
    jne     .L1173
    movl    $httpd_err400title, %eax
    movq    httpd_err400form(%rip), %r8
    shrq    $3, %rax
    cmpb    $0, 2147450880(%rax)
    jne     .L1174


handle_read:
.LFB20:
    .cfi_startproc
    pushq   %r12
    .cfi_def_cfa_offset 16
    .cfi_offset 12, -16
    pushq   %rbp
    .cfi_def_cfa_offset 24
    .cfi_offset 6, -24
    movq    %rsi, %r12
    pushq   %rbx
    .cfi_def_cfa_offset 32
    .cfi_offset 3, -32
    movq    8(%rdi), %rbx
    movq    %rdi, %rbp
    movq    160(%rbx), %rsi
    movq    152(%rbx), %rdx
    cmpq    %rdx, %rsi
    jb      .L384
    cmpq    $5000, %rdx
    jbe     .L411

谁能告诉我这些代码如何防止缓冲区溢出?

最佳答案

您的 handle_read 函数最终不会在堆栈上分配任何内容,因此 -fstack-protector-strong 无法保护任何内容,因此此选项没有任何区别。 -zexecstack 选项在生成的可执行文件中设置一个标志,告诉操作系统它应该允许执行存储在堆栈中的代码。它对生成的程序集没有影响。

只有 -fsanitize=address 选项具有显示在您发布的生成的程序集输出中的效果。它负责 shr​​q $3, rXX; cmp $0, 2147450880(%rXX); jne .LXXXX 序列出现在生成的程序集的第二个 block 中。这些指令在“影子内存”表中查找函数访问的内存中的每个地址。该表记录了哪些位置已分配,哪些位置尚未分配。如果插入的代码检测到程序正在尝试访问尚未分配的内存位置,则会导致程序退出并显示错误消息。

有关影子内存表如何工作以及AddressSanitizer一般如何工作的更多详细信息,您可以阅读作者的Usenix论文AddressSanitizer: A Fast Address Sanity Checker .

关于c - 该机器代码如何防止缓冲区溢出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33694789/

相关文章:

c++ - 哪个更快 : if (bool) or if(int)?

c - 执行的shellcode终止主程序

c - 在 C 语言的编译时评估的预处理器函数

c - Flex 启动条件意外结果

c - 好的 C 绘图库?

我可以在 Linux 驱动程序中使用 C11 的 <stdatomic.h> 吗?还是必须使用内存屏障的 Linux 函数?

c++ - 两个编译器互不喜欢

无法在 Eclipse 中使用 gcc -shared 找到库来构建 dll

exception - 是否存在未对齐数据会导致 x86 CPU 产生异常的情况?

c - 超声波传感器距离测量,可变溢出