[compiler-rt] 15e9b1d - [libasan] Remove 4Mb stack limit for swapcontext unpoisoning
Vitaly Buka via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 22 17:37:58 PDT 2022
Author: Ivan Trofimov
Date: 2022-07-22T17:37:44-07:00
New Revision: 15e9b1d0c0bea607fc0aad4a851ddd32b5736c80
URL: https://github.com/llvm/llvm-project/commit/15e9b1d0c0bea607fc0aad4a851ddd32b5736c80
DIFF: https://github.com/llvm/llvm-project/commit/15e9b1d0c0bea607fc0aad4a851ddd32b5736c80.diff
LOG: [libasan] Remove 4Mb stack limit for swapcontext unpoisoning
Reviewed By: vitalybuka, eugenis
Differential Revision: https://reviews.llvm.org/D129219
Added:
Modified:
compiler-rt/lib/asan/asan_interceptors.cpp
compiler-rt/test/asan/TestCases/Linux/swapcontext_annotation.cpp
Removed:
################################################################################
diff --git a/compiler-rt/lib/asan/asan_interceptors.cpp b/compiler-rt/lib/asan/asan_interceptors.cpp
index ff6ffeca36d5d..817008253fc0e 100644
--- a/compiler-rt/lib/asan/asan_interceptors.cpp
+++ b/compiler-rt/lib/asan/asan_interceptors.cpp
@@ -243,14 +243,18 @@ DEFINE_REAL_PTHREAD_FUNCTIONS
#if ASAN_INTERCEPT_SWAPCONTEXT
static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
+ // Only clear if we know the stack. This should be true only for contexts
+ // created with makecontext().
+ if (!ssize)
+ return;
// Align to page size.
uptr PageSize = GetPageSizeCached();
uptr bottom = RoundDownTo(stack, PageSize);
+ if (!AddrIsInMem(bottom))
+ return;
ssize += stack - bottom;
ssize = RoundUpTo(ssize, PageSize);
- static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb
- if (AddrIsInMem(bottom) && ssize && ssize <= kMaxSaneContextStackSize)
- PoisonShadow(bottom, ssize, 0);
+ PoisonShadow(bottom, ssize, 0);
}
INTERCEPTOR(int, getcontext, struct ucontext_t *ucp) {
diff --git a/compiler-rt/test/asan/TestCases/Linux/swapcontext_annotation.cpp b/compiler-rt/test/asan/TestCases/Linux/swapcontext_annotation.cpp
index fd5ae17c4d0a5..5753f13979636 100644
--- a/compiler-rt/test/asan/TestCases/Linux/swapcontext_annotation.cpp
+++ b/compiler-rt/test/asan/TestCases/Linux/swapcontext_annotation.cpp
@@ -146,9 +146,61 @@ int Run(int arg, int mode, char *child_stack) {
return child_stack[arg];
}
+ucontext_t orig_huge_stack_context;
+ucontext_t child_huge_stack_context;
+
+// There used to be a limitation for stack unpoisoning (size <= 4Mb), check that it's gone.
+const int kHugeStackSize = 1 << 23;
+
+void ChildHugeStack() {
+ __sanitizer_finish_switch_fiber(nullptr, &main_thread_stack,
+ &main_thread_stacksize);
+ char x[32] = {0}; // Stack gets poisoned.
+ __sanitizer_start_switch_fiber(nullptr, main_thread_stack,
+ main_thread_stacksize);
+ if (swapcontext(&child_huge_stack_context, &orig_huge_stack_context) < 0) {
+ perror("swapcontext");
+ _exit(1);
+ }
+}
+
+void DoRunHugeStack(char *child_stack) {
+ getcontext(&child_huge_stack_context);
+ child_huge_stack_context.uc_stack.ss_sp = child_stack;
+ child_huge_stack_context.uc_stack.ss_size = kHugeStackSize;
+ makecontext(&child_huge_stack_context, (void (*)())ChildHugeStack, 0);
+ void *fake_stack_save;
+ __sanitizer_start_switch_fiber(&fake_stack_save,
+ child_huge_stack_context.uc_stack.ss_sp,
+ child_huge_stack_context.uc_stack.ss_size);
+ if (swapcontext(&orig_huge_stack_context, &child_huge_stack_context) < 0) {
+ perror("swapcontext");
+ _exit(1);
+ }
+ __sanitizer_finish_switch_fiber(
+ fake_stack_save, (const void **)&child_huge_stack_context.uc_stack.ss_sp,
+ &child_huge_stack_context.uc_stack.ss_size);
+ for (int i = 0; i < kHugeStackSize; ++i) {
+ child_stack[i] = i;
+ }
+}
+
+void RunHugeStack() {
+ const int run_offset = 1 << 14;
+ char *heap = new char[kHugeStackSize + run_offset + 1];
+ DoRunHugeStack(heap);
+ DoRunHugeStack(heap + run_offset);
+ DoRunHugeStack(heap);
+ delete[] heap;
+}
+
void handler(int sig) { CallNoReturn(); }
int main(int argc, char **argv) {
+ // CHECK: WARNING: ASan doesn't fully support makecontext/swapcontext
+ // CHECK-NOT: ASan is ignoring requested __asan_handle_no_return
+ RunHugeStack();
+
// set up a signal that will spam and trigger __asan_handle_no_return at
// tricky moments
struct sigaction act = {};
@@ -170,7 +222,6 @@ int main(int argc, char **argv) {
char *heap = new char[kStackSize + 1];
next_child_stack = new char[kStackSize + 1];
char stack[kStackSize + 1];
- // CHECK: WARNING: ASan doesn't fully support makecontext/swapcontext
int ret = 0;
// CHECK-NOT: ASan is ignoring requested __asan_handle_no_return
for (unsigned int i = 0; i < 30; ++i) {
More information about the llvm-commits
mailing list