【问题标题】:Why address sanitizer doesn't work for bss global overflow?为什么地址清理程序不适用于 bss 全局溢出?
【发布时间】:2018-05-17 22:28:48
【问题描述】:

我做了什么。

测试1

  1 #include <stdio.h>                                                              
  2                                                                                 
  3 int test[16];                                                                   
  4                                                                                 
  5 int main()                                                                      
  6 {                                                                               
  7     test[17] = -1;                                                              
  8 } 

/tmp $ gcc ./main.c -o main -fsanitize=address
/tmp $ ./main 
/tmp $

测试2

  1 #include <stdio.h>                                                              
  2                                                                                 
  3 int test[16] = {1};                                                             
  4                                                                                 
  5 int main()                                                                      
  6 {                                                                               
  7     test[17] = -1;                                                              
  8 }

 /tmp $ gcc ./main.c -o main -fsanitize=address
 /tmp $ ./main 

=================================================================
==19776==ERROR: AddressSanitizer: global-buffer-overflow on address 
...

看起来全局缓冲区溢出检测不适用于放置在 bss 中的全局变量(是这样吗?)。这背后的原因是什么?

更新:

存储的代码未优化。 系统信息:

$ gcc --version
gcc (Ubuntu 7.2.0-8ubuntu3.2) 7.2.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

【问题讨论】:

  • 你试过clang吗?
  • 我不确定分配是否会生成任何代码。
  • @EugeneSh。不生成代码是可以的(因为它无论如何都是 UB,即使没有,没有volatile 也没有可观察到的行为),但是当这取决于变量是否被初始化时,我会感到惊讶......
  • @Jean-François Fabre 我没试过 clang,我现在只对 gcc 感兴趣。

标签: c memory-management buffer-overflow address-sanitizer


【解决方案1】:

这是FAQ:

问:为什么 ASan 没有在我的 代码?

A1:如果你的错误太明显,编译器可能已经 在 Asan 运行时对其进行了优化。

A2:另一个仅限 C 语言的选项是访问全局通用符号 不受 Asan 保护(您可以使用 -fno-common 禁用通用符号的生成并希望检测到更多错误)。

您的案例可能已被 A2 覆盖,因此添加 -fno-common 应该会有所帮助。

常见符号(默认为零初始化全局变量生成)的问题在于,由于其奇怪的遗留语义,Asan 无法为它们插入红区(有关血腥细节,请参阅 GCC #55739)。通过提供-fno-common,您可以禁用公共生成,而是要求 GCC 在所有情况下生成正常的全局符号(这有可能会破坏依赖公共符号行为的编写不良的程序,但通常这不是问题)。

【讨论】:

  • 在此处添加 -fno-common 标志会有所帮助。此外,如果您愿意,您可以对该标志以及它如何具体影响 asan 行为给出更广泛的解释。这对其他人会有所帮助,他们将来会提到这个问题。谢谢。
  • @AlexHoppus 我尝试添加更多细节,如果可以改进,请告诉我。
【解决方案2】:

其他工具,包括我们的(语义设计)CheckPointer 工具,可以执行此操作。 (编辑输出以删除一些不相关的文本):

对于 OP 定义的 test1.c:

c:\DMS\Domains\C\GCC4\Tools\CheckPointer\Example\Source>DMSCheckPointer C~GCC4 test1.c
C~GCC4 CheckPointer Version 1.2.1001
Copyright (C) 2011-2016 Semantic Designs, Inc; All Rights Reserved; SD Confidential

c:\DMS\Domains\C\GCC4\Tools\CheckPointer\Example\Source>gcc.exe -I"c:\DMS\Domains\C\GCC4\Tools\CheckPointer" -I.\Target -otest1.exe Target\test1.c <snip>

test1
*** Error: CWE-119: Improper Restriction of Operations within the Bounds of a Memory Buffer
       Dereference of pointer is out of bounds.
in function: main, line: 7, file c:\DMS\Domains\C\GCC4\Tools\CheckPointer\Example\Source\test1.c

对于 test2.c:

c:\DMS\Domains\C\GCC4\Tools\CheckPointer\Example\Source>DMSCheckPointer C~GCC4 test2.c
C~GCC4 CheckPointer Version 1.2.1001
Copyright (C) 2011-2016 Semantic Designs, Inc; All Rights Reserved; SD Confidential

c:\DMS\Domains\C\GCC4\Tools\CheckPointer\Example\Source>gcc.exe -I"c:\DMS\Domains\C\GCC4\Tools\CheckPointer" -I.\Target -otest2.exe Target\test2.c <snip>

test2
*** Error: CWE-119: Improper Restriction of Operations within the Bounds of a Memory Buffer
       Dereference of pointer is out of bounds.
in function: main, line: 7, file c:\DMS\Domains\C\GCC4\Tools\CheckPointer\Example\Source\test2.c

CheckPointer 不需要围绕数据的“红区”;它根据语言语义检查访问。这意味着它将,例如,检测结构中任何位置的 char 数组末尾的访问,无论该结构是本地(堆栈)变量,在堆中,在线程本地存储中还是嵌入在某些其他结构中。

与“CWE-119”相关的“奇怪的措辞”不是我们选择的词,它是由Common Weakness Enumeration 的标准定义的。 CheckPointer 使用 CWE 定义、分类和描述报告错误。

【讨论】:

    猜你喜欢
    • 2016-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-22
    • 2019-03-28
    • 2023-04-05
    • 1970-01-01
    相关资源
    最近更新 更多