为什么地址消毒器不能防止BSS全局溢出?

9

我的工作内容。

测试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 吗? - Jean-François Fabre
我不确定这个赋值语句是否生成任何代码。 - Eugene Sh.
@EugeneSh。如果不生成代码(因为它无论如何都是UB,即使没有volatile也没有可观察的行为),那么这应该是可以的,但如果这取决于变量是否初始化,我会感到惊讶... - user2371524
@Jean-François Fabre 我还没有尝试过clang,现在我只对gcc感兴趣。 - Alex Hoppus
除非gcc正在执行错误的检查,而从生成的检查中看不出来这一点。 - Shafik Yaghmour
显示剩余2条评论
2个回答

6

以下内容源自FAQ:

问: 为什么ASan没有报告我代码中明显的无效内存访问问题?

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

答2: 另一个只适用于C语言的选项是对未被Asan保护的全局公共符号的访问(您可以使用-fno-common禁用生成公共符号,以便更多地检测到错误)。

您的情况可能由答2覆盖,因此添加-fno-common应该会有所帮助。

关于公共符号(默认情况下针对零初始化的全局变量生成),存在一个问题,由于其怪异的传统语义,Asan不能为其插入红区(请参见GCC #55739了解详细信息)。通过提供-fno-common,您可以禁用公共符号的生成,并要求GCC在所有情况下生成普通的全局符号(这会有一小部分可能会破坏依赖于公共符号行为的程序,但通常不是问题)。


添加-fno-common标志在这里有帮助。此外,如果您愿意,您可以对此标志进行更广泛的解释,并具体说明它如何影响asan行为。这将有助于其他人,在未来参考此问题。谢谢。 - Alex Hoppus
@AlexHoppus 我尝试添加了一些更多的细节,如果有需要改进的地方请告诉我。 - yugr

-2
其他工具,包括我们(Semantic Designs)的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定义、分类和描述报告错误。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接