This is an archive of the discontinued LLVM Phabricator instance.

sanitizer_common: initialize sanitizer runtimes lazily from signal interceptors
ClosedPublic

Authored by dvyukov on Jul 13 2023, 5:19 AM.

Details

Summary

Currently if a program calls sigaction very early (before non-lazy sanitizer
initialization, in particular if .preinit_array initialization is not enabled),
then sigaction will wrongly fail since the interceptor is not initialized yet.

In all other interceptors we do lazy runtime initialization for this reason,
but we don't do it in the signal interceptors.
Do lazy runtime initialization in signal interceptors as well.

Diff Detail

Event Timeline

dvyukov created this revision.Jul 13 2023, 5:19 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 13 2023, 5:19 AM
dvyukov requested review of this revision.Jul 13 2023, 5:19 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 13 2023, 5:19 AM
Herald added a subscriber: Restricted Project. · View Herald Transcript
dvyukov added inline comments.Jul 13 2023, 5:19 AM
compiler-rt/test/lit.common.cfg.py
932

Needed to move it for -shared-libsan in the test to work.

melver accepted this revision.Jul 13 2023, 7:06 AM
This revision is now accepted and ready to land.Jul 13 2023, 7:06 AM
This revision was landed with ongoing or failed builds.Jul 13 2023, 7:28 AM
This revision was automatically updated to reflect the committed changes.

Vitaly, I've landed this to catch bot failures earlier. But if you have any comments, I will fix them in a separate commit.

Caslyn added a subscriber: Caslyn.Jul 13 2023, 11:59 AM
Caslyn added inline comments.
compiler-rt/test/ubsan/TestCases/Misc/Linux/sigaction.cpp
1

Hello - this test is failing on clang-linux builders in Fuchsia. For ex: https://luci-milo.appspot.com/ui/p/fuchsia/builders/toolchain.ci/clang-linux-arm64/b8775675662976612977/overview.

Below is the error output, it appears the issue is that %run doesn't expand to anything when running this script on Linux builds:

Script:
--
: 'RUN: at line 1';      /b/s/w/ir/x/w/llvm_build/./bin/clang  --driver-mode=g++ -fsanitize=thread   -Wthread-safety -Wthread-safety-reference -Wthread-safety-beta   -fsanitize=undefined -shared-libsan /b/s/w/ir/x/w/llvm-llvm-project/compiler-rt/test/ubsan/TestCases/Misc/Linux/sigaction.cpp -o /b/s/w/ir/x/w/llvm_build/runtimes/runtimes-aarch64-unknown-linux-gnu-bins/compiler-rt/test/ubsan/ThreadSanitizer-aarch64/TestCases/Misc/Linux/Output/sigaction.cpp.tmp &&  /b/s/w/ir/x/w/llvm_build/runtimes/runtimes-aarch64-unknown-linux-gnu-bins/compiler-rt/test/ubsan/ThreadSanitizer-aarch64/TestCases/Misc/Linux/Output/sigaction.cpp.tmp 2>&1 | FileCheck /b/s/w/ir/x/w/llvm-llvm-project/compiler-rt/test/ubsan/TestCases/Misc/Linux/sigaction.cpp
--
Exit Code: 2

Command Output (stderr):
--
FileCheck error: '<stdin>' is empty.
FileCheck command line:  FileCheck /b/s/w/ir/x/w/llvm-llvm-project/compiler-rt/test/ubsan/TestCases/Misc/Linux/sigaction.cpp

Vitaly, I've landed this to catch bot failures earlier. But if you have any comments, I will fix them in a separate commit.

LGTM

Caslyn added inline comments.Jul 13 2023, 7:30 PM
compiler-rt/test/ubsan/TestCases/Misc/Linux/sigaction.cpp
1

it appears the issue is that...

Sorry, I don't think that's it. The invocation only fails when running with UBSan-ThreadSanitizer-aarch64 :: TestCases/Misc/Linux/sigaction.cpp.

Thanks for reporting.
I've tested similar command for x86 (my host) and it worked.
I've sent a change with XFAIL for aarch64 to make bots green: https://reviews.llvm.org/D155272

mysterymath added inline comments.
compiler-rt/test/ubsan/TestCases/Misc/Linux/sigaction.cpp
1

I dug into this a bit more, and found that there's a segfault in the sanitizer code leading up to the fprintf in ctor(). It dereferences some value that it picks out of the GOT, but that isn't mapped in the binary. I'm not entirely sure what it's doing, or why this selectively doesn't work on the Fuchsia builders.

Hi @vitalybuka @dvyukov

This seems to have flagged an issue with some test configurations, it seems if tsan's so is built with ld.bfd instead of ld.lld then the tsan shared library gets corrupted, causing this test to fail.
I am wondering if it is a know issue using tsan + gnu ld ?

cmake -G Ninja -DLLVM_INCLUDE_EXAMPLES=OFF -DCLANG_ENABLE_ARCMT=OFF -DPYTHON_EXECUTABLE=/usr/bin/python3 -DCLANG_ENABLE_CLANGD=OFF -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCOMPILER_RT_TEST_USE_LLD=0 -DLLVM_BUILD_RUNTIME=ON -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;compiler-rt;cross-project-tests;lld" -DCMAKE_BUILD_TYPE=Release -S ./llvm -B build && ninja -C build -j8 check-ubsan

******************** TEST 'UBSan-ThreadSanitizer-x86_64 :: TestCases/Misc/Linux/sigaction.cpp' FAILED ********************
Script:
--
: 'RUN: at line 1';      /home/pierre/llvm-project/build/./bin/clang  --driver-mode=g++ -fsanitize=thread  -m64  -fsanitize=undefined -shared-libsan /home/pierre/llvm-project/compiler-rt/test/ubsan/TestCases/Misc/Linux/sigaction.cpp -o /home/pierre/llvm-project/build/projects/compiler-rt/test/ubsan/ThreadSanitizer-x86_64/TestCases/Misc/Linux/Output/sigaction.cpp.tmp &&  /home/pierre/llvm-project/build/projects/compiler-rt/test/ubsan/ThreadSanitizer-x86_64/TestCases/Misc/Linux/Output/sigaction.cpp.tmp 2>&1 | FileCheck /home/pierre/llvm-project/compiler-rt/test/ubsan/TestCases/Misc/Linux/sigaction.cpp
--
Exit Code: 1

Command Output (stderr):
--
/usr/bin/ld: /home/pierre/llvm-project/build/lib/clang/17/lib/x86_64-unknown-linux-gnu/libclang_rt.tsan.so: siglongjmp: invalid version 21 (max 0)
/usr/bin/ld: /home/pierre/llvm-project/build/lib/clang/17/lib/x86_64-unknown-linux-gnu/libclang_rt.tsan.so: error adding symbols: bad value
clang: error: linker command failed with exit code 1 (use -v to see invocation)

llvm-readelf -a lib/clang/17/lib/x86_64-unknown-linux-gnu/libclang_rt.tsan.so > /dev/null
llvm-readelf: warning: 'lib/clang/17/lib/x86_64-unknown-linux-gnu/libclang_rt.tsan.so': SHT_GNU_versym section refers to a version index 21 which is missing
llvm-readelf: warning: 'lib/clang/17/lib/x86_64-unknown-linux-gnu/libclang_rt.tsan.so': unable to get a version for entry 754 of SHT_GNU_versym section with index 4: SHT_GNU_versym section refers to a version index 21 which is missing
llvm-readelf: warning: 'lib/clang/17/lib/x86_64-unknown-linux-gnu/libclang_rt.tsan.so': unable to get a version for entry 2617 of SHT_GNU_versym section with index 4: SHT_GNU_versym section refers to a version index 21 which is missing
llvm-readelf: warning: 'lib/clang/17/lib/x86_64-unknown-linux-gnu/libclang_rt.tsan.so': unable to get a version for entry 3154 of SHT_GNU_versym section with index 4: SHT_GNU_versym section refers to a version index 21 which is missing

Many thanks!

Pierre

I am wondering if it is a know issue using tsan + gnu ld ?

No, I wasn't aware.

These looks like existing bugs that were exposed by the test due to use of shared runtime.
It looks like the shared runtime is not well tested in general.

arichardson added inline comments.
compiler-rt/test/lit.common.cfg.py
939

This breaks testing only the builtins library since config.bits is only set in memprof/asan/asan_abi.
AttributeError: 'TestingConfig' object has no attribute 'bits'.

If I understand this correctly, libasan_dir will expand to <GCC>/../lib(64), i.e. /usr/lib. Would it be possible to use gcc -print-file-name=libasan.so instead?

❯ gcc -print-file-name=libasan.so      
/usr/lib/gcc/x86_64-linux-gnu/12/libasan.so
❯ gcc -print-file-name=libasan.so -m32
/usr/lib/gcc/x86_64-linux-gnu/12/32/libasan.so

Would it be possible to use gcc -print-file-name=libasan.so instead?

In clang the library is called libclang_rt.asan.so.
Also if the compiler is host, won't this give path to the host asan, while we need the local just built library.

Would it be possible to use gcc -print-file-name=libasan.so instead?

In clang the library is called libclang_rt.asan.so.
Also if the compiler is host, won't this give path to the host asan, while we need the local just built library.

It currently gives the path to the libraries in the same tree as the GCC installation since the branch that triggers the error is guarded by compiler==gcc. Do we actually need this logic if the compiler rt libpath was already added in the line above?

Would it be possible to use gcc -print-file-name=libasan.so instead?

In clang the library is called libclang_rt.asan.so.
Also if the compiler is host, won't this give path to the host asan, while we need the local just built library.

It currently gives the path to the libraries in the same tree as the GCC installation since the branch that triggers the error is guarded by compiler==gcc. Do we actually need this logic if the compiler rt libpath was already added in the line above?

I just tried building compiler-rt with GCC again and am still seeing this error. Would be nice if we could fix this, even if it's just getattr(config, "bits", "") rather than some more correct fix.

    libasan_dir = os.path.join(gcc_dir, "..", "lib" + config.bits)
                                                      ^^^^^^^^^^^
AttributeError: 'TestingConfig' object has no attribute 'bits'