If libsanitizer is built against glibc trunk, nothing really works: ./a ==91==ERROR: AddressSanitizer failed to allocate 0x0 (0) bytes of SetAlternateSignalStack (error code: 22) ==91==Process memory map follows: I think this is caused by // TODO(glider): different tools may require different altstack size. static const uptr kAltStackSize = SIGSTKSZ * 4; // SIGSTKSZ is not enough. void SetAlternateSignalStack() { stack_t altstack, oldstack; CHECK_EQ(0, sigaltstack(nullptr, &oldstack)); // If the alternate stack is already in place, do nothing. // Android always sets an alternate stack, but it's too small for us. if (!SANITIZER_ANDROID && !(oldstack.ss_flags & SS_DISABLE)) return; // TODO(glider): the mapped stack should have the MAP_STACK flag in the // future. It is not required by man 2 sigaltstack now (they're using // malloc()). void* base = MmapOrDie(kAltStackSize, __func__); altstack.ss_sp = (char*) base; altstack.ss_flags = 0; altstack.ss_size = kAltStackSize; CHECK_EQ(0, sigaltstack(&altstack, nullptr)); } called from #0 0x00007ffff7644650 in sigaltstack () from ./libasan.so.6 #1 0x00007ffff76bca92 in __sanitizer::SetAlternateSignalStack() () from ./libasan.so.6 #2 0x00007ffff76bcc65 in __sanitizer::InstallDeadlySignalHandlers(void (*)(int, void*, void*)) () from ./libasan.so.6 #3 0x00007ffff76ab60c in __asan::AsanInitInternal() [clone .part.0] () from ./libasan.so.6 #4 0x00007ffff7fdb6ee in _dl_init () from /lib64/ld-linux-x86-64.so.2 #5 0x00007ffff7fcc0ca in _dl_start_user () from /lib64/ld-linux-x86-64.so.2 and __asan_init which tail calls AsanInitInternal is registered in .preinit_array. As in newer glibcs SIGSTKSZ is no longer a constant - since https://sourceware.org/git/?p=glibc.git;a=commit;h=6c57d320484988e87e446e2e60ce42816bf51d53 - I think the above is invalid C++, because the function is called before the kAltStackSize variable is constructed (which is why we end up with calling MmapOrDie(0, __func__); and that fails miserably.
As a quick hack, we could do something like: #ifdef _SC_SIGSTKSZ #define kAltStackSize (SIGSTKSZ * 4) #else static const uptr kAltStackSize = SIGSTKSZ * 4; // SIGSTKSZ is not enough. #endif but the disadvantage is that sysconf will be called in that case on each use of kAltStackSize.
Confirmed by code inspection, but it's for sure sth not new (but would be nice to fix before GCC 11.1). I suggtest to simply move the initialization inside SetAlternateSignalStack. Sth like diff --git a/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp b/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp index d29438cf9db..803712e268e 100644 --- a/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp +++ b/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp @@ -165,7 +165,7 @@ bool SupportsColoredOutput(fd_t fd) { #if !SANITIZER_GO // TODO(glider): different tools may require different altstack size. -static const uptr kAltStackSize = SIGSTKSZ * 4; // SIGSTKSZ is not enough. +static const uptr kAltStackSize; void SetAlternateSignalStack() { stack_t altstack, oldstack; @@ -176,6 +176,7 @@ void SetAlternateSignalStack() { // TODO(glider): the mapped stack should have the MAP_STACK flag in the // future. It is not required by man 2 sigaltstack now (they're using // malloc()). + kAltStackSize = SIGSTKSZ * 4; // SIGSTKSZ is not enough. void* base = MmapOrDie(kAltStackSize, __func__); altstack.ss_sp = (char*) base; altstack.ss_flags = 0;
(In reply to Richard Biener from comment #2) > Confirmed by code inspection, but it's for sure sth not new (but would be > nice to fix before GCC 11.1). > > I suggtest to simply move the initialization inside SetAlternateSignalStack. > Sth like > > diff --git a/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp > b/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp > index d29438cf9db..803712e268e 100644 > --- a/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp > +++ b/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp > @@ -165,7 +165,7 @@ bool SupportsColoredOutput(fd_t fd) { > > #if !SANITIZER_GO > // TODO(glider): different tools may require different altstack size. > -static const uptr kAltStackSize = SIGSTKSZ * 4; // SIGSTKSZ is not enough. > +static const uptr kAltStackSize; > > void SetAlternateSignalStack() { > stack_t altstack, oldstack; > @@ -176,6 +176,7 @@ void SetAlternateSignalStack() { > // TODO(glider): the mapped stack should have the MAP_STACK flag in the > // future. It is not required by man 2 sigaltstack now (they're using > // malloc()). > + kAltStackSize = SIGSTKSZ * 4; // SIGSTKSZ is not enough. > void* base = MmapOrDie(kAltStackSize, __func__); > altstack.ss_sp = (char*) base; > altstack.ss_flags = 0; We can initialize it with a constructor or .init_array.
const vars in C++ can't be uninitialized nor modified. And initializing those in constructor or .init_array is too late, the problem is that the function is called from .preinit_array handler, so before anything is constructed. I'd suggest --- libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp.jj 2020-11-13 19:00:46.909618582 +0100 +++ libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp 2021-04-16 15:19:56.211942944 +0200 @@ -165,7 +165,13 @@ bool SupportsColoredOutput(fd_t fd) { #if !SANITIZER_GO // TODO(glider): different tools may require different altstack size. +#if SANITIZER_LINUX && defined(_SC_SIGSTKSZ) +// In glibc 2.34 and later SIGSTKSZ is no longer a compile time constant, +// but sysconf (_SC_SIGSTKSZ) call. +static uptr kAltStackSize; +#else static const uptr kAltStackSize = SIGSTKSZ * 4; // SIGSTKSZ is not enough. +#endif void SetAlternateSignalStack() { stack_t altstack, oldstack; @@ -173,6 +179,9 @@ void SetAlternateSignalStack() { // If the alternate stack is already in place, do nothing. // Android always sets an alternate stack, but it's too small for us. if (!SANITIZER_ANDROID && !(oldstack.ss_flags & SS_DISABLE)) return; +#if SANITIZER_LINUX && defined(_SC_SIGSTKSZ) + if (!kAltStackSize) kAltStackSize = SIGSTKSZ * 4; +#endif // TODO(glider): the mapped stack should have the MAP_STACK flag in the // future. It is not required by man 2 sigaltstack now (they're using // malloc()).
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>: https://gcc.gnu.org/g:d9f462fb372fb02da032cefd6b091d7582c425ae commit r11-8230-gd9f462fb372fb02da032cefd6b091d7582c425ae Author: Jakub Jelinek <jakub@redhat.com> Date: Sat Apr 17 11:27:14 2021 +0200 sanitizer: Fix asan against glibc 2.34 [PR100114] As mentioned in the PR, SIGSTKSZ is no longer a compile time constant in glibc 2.34 and later, so static const uptr kAltStackSize = SIGSTKSZ * 4; needs dynamic initialization, but is used by a function called indirectly from .preinit_array and therefore before the variable is constructed. This results in using 0 size instead and all asan instrumented programs die with: ==91==ERROR: AddressSanitizer failed to allocate 0x0 (0) bytes of SetAlternateSignalStack (error code: 22) Here is a cherry-pick from upstream to fix this. 2021-04-17 Jakub Jelinek <jakub@redhat.com> PR sanitizer/100114 * sanitizer_common/sanitizer_posix_libcdep.cpp: Cherry-pick llvm-project revisions 82150606fb11d28813ae6da1101f5bda638165fe and b93629dd335ffee2fc4b9b619bf86c3f9e6b0023.
Fixed on the trunk so far, guess some backporting will be useful.
Yeah, backporting everywhere is needed.
The releases/gcc-10 branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>: https://gcc.gnu.org/g:950bac27d63c1c2ac3a6ed867692d6a13f21feb3 commit r10-9732-g950bac27d63c1c2ac3a6ed867692d6a13f21feb3 Author: Jakub Jelinek <jakub@redhat.com> Date: Sat Apr 17 11:27:14 2021 +0200 sanitizer: Fix asan against glibc 2.34 [PR100114] As mentioned in the PR, SIGSTKSZ is no longer a compile time constant in glibc 2.34 and later, so static const uptr kAltStackSize = SIGSTKSZ * 4; needs dynamic initialization, but is used by a function called indirectly from .preinit_array and therefore before the variable is constructed. This results in using 0 size instead and all asan instrumented programs die with: ==91==ERROR: AddressSanitizer failed to allocate 0x0 (0) bytes of SetAlternateSignalStack (error code: 22) Here is a cherry-pick from upstream to fix this. 2021-04-17 Jakub Jelinek <jakub@redhat.com> PR sanitizer/100114 * sanitizer_common/sanitizer_posix_libcdep.cpp: Cherry-pick llvm-project revisions 82150606fb11d28813ae6da1101f5bda638165fe and b93629dd335ffee2fc4b9b619bf86c3f9e6b0023. (cherry picked from commit d9f462fb372fb02da032cefd6b091d7582c425ae)
The releases/gcc-9 branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>: https://gcc.gnu.org/g:3d0135bf3be416bbe2531dc763d19b749eb2b856 commit r9-9450-g3d0135bf3be416bbe2531dc763d19b749eb2b856 Author: Jakub Jelinek <jakub@redhat.com> Date: Sat Apr 17 11:27:14 2021 +0200 sanitizer: Fix asan against glibc 2.34 [PR100114] As mentioned in the PR, SIGSTKSZ is no longer a compile time constant in glibc 2.34 and later, so static const uptr kAltStackSize = SIGSTKSZ * 4; needs dynamic initialization, but is used by a function called indirectly from .preinit_array and therefore before the variable is constructed. This results in using 0 size instead and all asan instrumented programs die with: ==91==ERROR: AddressSanitizer failed to allocate 0x0 (0) bytes of SetAlternateSignalStack (error code: 22) Here is a cherry-pick from upstream to fix this. 2021-04-17 Jakub Jelinek <jakub@redhat.com> PR sanitizer/100114 * sanitizer_common/sanitizer_posix_libcdep.cc: Cherry-pick llvm-project revisions 82150606fb11d28813ae6da1101f5bda638165fe and b93629dd335ffee2fc4b9b619bf86c3f9e6b0023. (cherry picked from commit 950bac27d63c1c2ac3a6ed867692d6a13f21feb3)
The releases/gcc-8 branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>: https://gcc.gnu.org/g:ef195a39d0d3b929cc676302d074b42c25460601 commit r8-10912-gef195a39d0d3b929cc676302d074b42c25460601 Author: Jakub Jelinek <jakub@redhat.com> Date: Sat Apr 17 11:27:14 2021 +0200 sanitizer: Fix asan against glibc 2.34 [PR100114] As mentioned in the PR, SIGSTKSZ is no longer a compile time constant in glibc 2.34 and later, so static const uptr kAltStackSize = SIGSTKSZ * 4; needs dynamic initialization, but is used by a function called indirectly from .preinit_array and therefore before the variable is constructed. This results in using 0 size instead and all asan instrumented programs die with: ==91==ERROR: AddressSanitizer failed to allocate 0x0 (0) bytes of SetAlternateSignalStack (error code: 22) Here is a cherry-pick from upstream to fix this. 2021-04-17 Jakub Jelinek <jakub@redhat.com> PR sanitizer/100114 * sanitizer_common/sanitizer_posix_libcdep.cc: Cherry-pick llvm-project revisions 82150606fb11d28813ae6da1101f5bda638165fe and b93629dd335ffee2fc4b9b619bf86c3f9e6b0023. (cherry picked from commit 950bac27d63c1c2ac3a6ed867692d6a13f21feb3)
Fixed.
I just've seen it by compiling carbon-lang: https://github.com/carbon-language/carbon-lang (it could be reproduced when one downloads LLVM15 via homebrew as listed at carbon-lang README.md -- LLVM14 doesn't reproduce) More: https://github.com/carbon-language/carbon-lang/issues/2236 But here I see status 'RESOLVED FIXED'. Do you presume, my today's issue isn't connected?
(In reply to Alexander Enaldiev from comment #12) > But here I see status 'RESOLVED FIXED'. Do you presume, my today's issue > isn't connected? It could still be the same bug. It's supposed to be fixed in LLVM 13 and later, but maybe your program links against system libasan.a, which may not have been fixed yet by your distribution.