C++ 程序因 ASAN 失败(AddressSanitizer:DEADLYSIGNAL)

问题描述 投票:0回答:1

我已经在 C++ 中使用 ASAN 很长时间了,现在我只是与 ASAN 链接并让 DEADLYSIGNAL 执行生成的程序。例如:

p.cpp:

 int main() { return 0; }

我编译一下:

$ c++ -o p p.cpp -fsanitize=address -fsanitize=undefined

我执行它:

$ ./p
AddressSanitizer:DEADLYSIGNAL
AddressSanitizer:DEADLYSIGNAL
AddressSanitizer:DEADLYSIGNAL
AddressSanitizer:DEADLYSIGNAL
AddressSanitizer:DEADLYSIGNAL
AddressSanitizer:DEADLYSIGNAL
Segmentation fault (core dumped)

这种情况开始在某些机器上发生。在使用 ASAN 进行编译的机器上,在 ASAN 失败的机器上使用 ASAN 编译的可执行文件也可以工作,因此它似乎不是可执行文件本身的问题。

如果我使用单一消毒,无论是

sanitize=undefined
还是
sanitize=address
,它也可以工作,但两者的组合都会失败。当然,完全不消毒也能正常工作。

我的设置是:

$ c++ --version
c++ (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
Copyright (C) 2021 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.

在 Ubuntu 22.04.4 下。

gdb 不允许对使用 ASAN 编译的程序进行调试,但以下是其有价值的输出:

$ gdb p
GNU gdb (Ubuntu 12.1-0ubuntu1~22.04) 12.1
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from p...
(gdb) run
Starting program: /tmp/p 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
==432014==LeakSanitizer has encountered a fatal error.
==432014==HINT: For debugging, try setting environment variable LSAN_OPTIONS=verbosity=1:log_threads=1
==432014==HINT: LeakSanitizer does not work under ptrace (strace, gdb, etc)
[Inferior 1 (process 432014) exited with code 01]
(gdb) bt
No stack.
(gdb) 

后期注意事项:

  • 通过安装新的 Ubuntu 22.04 并安装 g++ 可以完美重现此错误。
  • 在某些机器中,需要进行几次尝试才能再现它。
  • 此时,我没有一台 Ubuntu 22.04 机器不会重现此错误。
c++ gcc address-sanitizer
1个回答
0
投票

我刚刚做了一些测试,发现这与 ASLR(地址空间布局随机化)有某种关系。如果禁用它(

echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
),它不会崩溃。 (至少超过 20k 次尝试它没有崩溃。)这也是它不会每次崩溃的原因,因为它显然取决于库在地址空间中的加载位置。

作为一种解决方法,您可以在开发系统上禁用 ASLR,但我不建议在生产中这样做,因为 ASLR 是一项有用的安全功能。

这也暗示了为什么它不会出现在另一个发行版上的 Ubuntu Docker 容器中,因为内核实际上处理了 ASLR 的一部分,而 Docker 容器仍然在另一个发行版的内核上运行。

我的猜测是 Ubuntu 应用了一些内核补丁,以与其他发行版不同的方式影响 ASLR,这就是为什么这种情况只发生在 Ubuntu VM/直接安装中,但不会发生在例如码头工人。这并不意味着 Ubuntu 使用的补丁一定有问题,它仍然可能是 glibc 和/或 libasan 中存在仅由 Ubuntu 内核创建的条件触发的错误。 (或者他们确实在内核中引入了一个错误。)

我将在周末仔细研究这个问题,但我希望这个解决方法同时可以帮助您。

(另请参阅这个关于 ASLR 的 askubuntu stackexchange 问题,了解如何禁用它的详细信息。)

© www.soinside.com 2019 - 2024. All rights reserved.