[PATCH] D88501: [asan][test] Several Posix/unpoison-alternate-stack.cpp fixes
Rainer Orth via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 29 10:10:32 PDT 2020
ro created this revision.
ro added a reviewer: vitalybuka.
ro added a project: Sanitizers.
Herald added subscribers: Sanitizers, fedor.sergeev.
ro requested review of this revision.
`Posix/unpoison-alternate-stack.cpp` currently `FAIL`s on Solaris/i386 and the investigation revealed several generic problems:
- `clang` warns compiling the testcase:
/vol/llvm/src/llvm-project/local/compiler-rt/test/asan/TestCases/Posix/unpoison-alternate-stack.cpp:83:7: warning: nested designators are a C99 extension [-Wc99-designator]
.sa_sigaction = signalHandler,
^~~~~~~~~~~~~
/vol/llvm/src/llvm-project/local/compiler-rt/test/asan/TestCases/Posix/unpoison-alternate-stack.cpp:84:7: warning: ISO C++ requires field designators to be specified in declaration order; field '_funcptr' will be initialized after field 'sa_flags' [-Wreorder-init-list]
.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/vol/llvm/src/llvm-project/local/compiler-rt/test/asan/TestCases/Posix/unpoison-alternate-stack.cpp:83:8: note: previous initialization for field '_funcptr' is here
.sa_sigaction = signalHandler,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/sys/signal.h:71:30: note: expanded from macro 'sa_sigaction'
#define sa_sigaction _funcptr._sigaction
^
/vol/llvm/src/llvm-project/local/compiler-rt/test/asan/TestCases/Posix/unpoison-alternate-stack.cpp:149:7: warning: ISO C++ requires field designators to be specified in declaration order; field 'ss_flags' will be initialized after field 'ss_size' [-Wreorder-init-list]
.ss_size = AltStackSize,
^~~~~~~~~~~~~~~~~~~~~~~
/vol/llvm/src/llvm-project/local/compiler-rt/test/asan/TestCases/Posix/unpoison-alternate-stack.cpp:148:19: note: previous initialization for field 'ss_flags' is here
.ss_flags = 0,
^
This can all easily be avoided by initializing each field separately.
- The test `SEGV`s:
Thread 4 received signal SIGSEGV, Segmentation fault.
[Switching to Thread 2 (LWP 2)]
0x08157f0f in __asan_memcpy (to=0xfe5d2e30, from=0x808cda0 <__const._ZN12_GLOBAL__N_123setSignalAlternateStackEPv.Action>, size=32) at /vol/llvm/src/llvm-project/dist/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:21
21 void *__asan_memcpy(void *to, const void *from, uptr size) {
(gdb) where
#0 0x08157f0f in __asan_memcpy (to=0xfe5d2e30, from=0x808cda0 <__const._ZN12_GLOBAL__N_123setSignalAlternateStackEPv.Action>, size=32) at /vol/llvm/src/llvm-project/dist/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:21
#1 0x081b080e in (anonymous namespace)::setSignalAlternateStack(void*) () at /vol/llvm/src/llvm-project/dist/compiler-rt/test/asan/TestCases/Posix/unpoison-alternate-stack.cpp:86
#2 0x081b02bc in (anonymous namespace)::threadFun(void*) () at /vol/llvm/src/llvm-project/dist/compiler-rt/test/asan/TestCases/Posix/unpoison-alternate-stack.cpp:107
#3 0x0816dd2a in __asan::AsanThread::ThreadStart (this=0xfe3f3000, os_id=2, signal_thread_is_registered=0xfeffd724) at /vol/llvm/src/llvm-project/dist/compiler-rt/lib/asan/asan_thread.cpp:262
#4 0x081400d0 in asan_thread_start (arg=0xfeffd720) at /vol/llvm/src/llvm-project/dist/compiler-rt/lib/asan/asan_interceptors.cpp:205
#5 0xfe281d3b in _thrp_setup () from /lib/libc.so.1
#6 0xfe282090 in ?? () from /lib/libc.so.1
in the sequence determing the GOT address at the `calll` insn:
subl $5424, %esp # imm = 0x1530
calll .L1$pb
.L1$pb:
The problem is that the default Solaris/i386 stack size is only 4 kB, while `__asan_memcpy` tries to allocate either 5436 (32-bit) or 10688 bytes (64-bit) on the stack. This patch avoids this by requiring at least 16 kB stack size.
- When I later investigated `PlatformUnpoisonStacks` calling `GetThreadStackAndTls`, I was reminded that `GetTls` is a dummy on Solaris. I do have a (not yet fully portable) implemtation, however that's moot for this testcase.
- Even without `-fsanitize=address` or in a minimal testcase derived from this one, I get an assertion failure:
Assertion failed: !isOnSignalStack(), file /vol/llvm/src/llvm-project/dist/compiler-rt/test/asan/TestCases/Posix/unpoison-alternate-stack.cpp, line 117
The fundamental problem with this testcase is that `longjmp` from a signal handler is highly unportable; XPG7 strongly warns against it and it is thus unspecified which stack is used when `longjmp`ing from a signal handler running on an alternative stack.
So I'm `XFAIL`ing this testcases on Solaris.
Tested on `amd64-pc-solaris2.11` and `x86_64-pc-linux-gnu`.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D88501
Files:
compiler-rt/test/asan/TestCases/Posix/unpoison-alternate-stack.cpp
Index: compiler-rt/test/asan/TestCases/Posix/unpoison-alternate-stack.cpp
===================================================================
--- compiler-rt/test/asan/TestCases/Posix/unpoison-alternate-stack.cpp
+++ compiler-rt/test/asan/TestCases/Posix/unpoison-alternate-stack.cpp
@@ -7,7 +7,10 @@
// RUN: %run %t
// XFAIL: ios && !iossim
+// longjmp from signal handler is unportable.
+// XFAIL: solaris
+#include <algorithm>
#include <cassert>
#include <cerrno>
#include <csetjmp>
@@ -83,10 +86,9 @@
void setSignalAlternateStack(void *AltStack) {
sigaltstack((stack_t const *)AltStack, nullptr);
- struct sigaction Action = {
- .sa_sigaction = signalHandler,
- .sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK,
- };
+ struct sigaction Action;
+ Action.sa_sigaction = signalHandler;
+ Action.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK;
sigemptyset(&Action.sa_mask);
sigaction(SIGUSR1, &Action, nullptr);
@@ -137,9 +139,11 @@
// reports when the stack is reused.
int main() {
size_t const PageSize = sysconf(_SC_PAGESIZE);
+ // The Solaris defaults of 4k (32-bit) and 8k (64-bit) are too small.
+ size_t const MinStackSize = std::max(PTHREAD_STACK_MIN, 16 * 1024);
// To align the alternate stack, we round this up to page_size.
size_t const DefaultStackSize =
- (PTHREAD_STACK_MIN - 1 + PageSize) & ~(PageSize - 1);
+ (MinStackSize - 1 + PageSize) & ~(PageSize - 1);
// The alternate stack needs a certain size, or the signal handler segfaults.
size_t const AltStackSize = 10 * PageSize;
size_t const MappingSize = DefaultStackSize + AltStackSize;
@@ -149,11 +153,10 @@
MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
- stack_t const AltStack = {
- .ss_sp = (char *)Mapping + DefaultStackSize,
- .ss_flags = 0,
- .ss_size = AltStackSize,
- };
+ stack_t AltStack;
+ AltStack.ss_sp = (char *)Mapping + DefaultStackSize;
+ AltStack.ss_flags = 0;
+ AltStack.ss_size = AltStackSize;
pthread_t Thread;
pthread_attr_t ThreadAttr;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D88501.294946.patch
Type: text/x-patch
Size: 2082 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200929/0a2a3b65/attachment.bin>
More information about the llvm-commits
mailing list