[compiler-rt] c93e4b6 - [asan] Reset stack bounds of context

Vitaly Buka via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 22 13:40:32 PDT 2022


Author: Vitaly Buka
Date: 2022-07-22T13:40:16-07:00
New Revision: c93e4b6b2c497aecda82029d6f161bd81da26dab

URL: https://github.com/llvm/llvm-project/commit/c93e4b6b2c497aecda82029d6f161bd81da26dab
DIFF: https://github.com/llvm/llvm-project/commit/c93e4b6b2c497aecda82029d6f161bd81da26dab.diff

LOG: [asan] Reset stack bounds of context

ClearShadowMemoryForContextStack assumes that context contains the stack
bounds. This is not true for a context from getcontext or oucp of
swapcontext.

Reviewed By: kstoimenov

Differential Revision: https://reviews.llvm.org/D130218

Added: 
    

Modified: 
    compiler-rt/lib/asan/asan_interceptors.cpp
    compiler-rt/lib/asan/asan_internal.h
    compiler-rt/lib/asan/asan_linux.cpp
    compiler-rt/lib/asan/asan_mac.cpp
    compiler-rt/lib/asan/asan_win.cpp
    compiler-rt/test/asan/TestCases/Linux/swapcontext_test.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/asan/asan_interceptors.cpp b/compiler-rt/lib/asan/asan_interceptors.cpp
index 78d23abaad63a..ff6ffeca36d5d 100644
--- a/compiler-rt/lib/asan/asan_interceptors.cpp
+++ b/compiler-rt/lib/asan/asan_interceptors.cpp
@@ -253,6 +253,14 @@ static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) {
     PoisonShadow(bottom, ssize, 0);
 }
 
+INTERCEPTOR(int, getcontext, struct ucontext_t *ucp) {
+  // API does not requires to have ucp clean, and sets only part of fields. We
+  // use ucp->uc_stack to unpoison new stack. We prefer to have zeroes then
+  // uninitialized bytes.
+  ResetContextStack(ucp);
+  return REAL(getcontext)(ucp);
+}
+
 INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
             struct ucontext_t *ucp) {
   static bool reported_warning = false;
@@ -266,6 +274,10 @@ INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
   uptr stack, ssize;
   ReadContextStack(ucp, &stack, &ssize);
   ClearShadowMemoryForContextStack(stack, ssize);
+
+  // See getcontext interceptor.
+  ResetContextStack(oucp);
+
 #    if __has_attribute(__indirect_return__) && \
         (defined(__x86_64__) || defined(__i386__))
   int (*real_swapcontext)(struct ucontext_t *, struct ucontext_t *)
@@ -643,6 +655,7 @@ void InitializeAsanInterceptors() {
   ASAN_INTERCEPT_FUNC(longjmp);
 
 #if ASAN_INTERCEPT_SWAPCONTEXT
+  ASAN_INTERCEPT_FUNC(getcontext);
   ASAN_INTERCEPT_FUNC(swapcontext);
 #endif
 #if ASAN_INTERCEPT__LONGJMP

diff  --git a/compiler-rt/lib/asan/asan_internal.h b/compiler-rt/lib/asan/asan_internal.h
index 7468f126d37b1..9c46f225116ee 100644
--- a/compiler-rt/lib/asan/asan_internal.h
+++ b/compiler-rt/lib/asan/asan_internal.h
@@ -106,6 +106,7 @@ void AsanApplyToGlobals(globals_op_fptr op, const void *needle);
 void AsanOnDeadlySignal(int, void *siginfo, void *context);
 
 void ReadContextStack(void *context, uptr *stack, uptr *ssize);
+void ResetContextStack(void *context);
 void StopInitOrderChecking();
 
 // Wrapper for TLS/TSD.

diff  --git a/compiler-rt/lib/asan/asan_linux.cpp b/compiler-rt/lib/asan/asan_linux.cpp
index defd81bc19e22..89450fc120a04 100644
--- a/compiler-rt/lib/asan/asan_linux.cpp
+++ b/compiler-rt/lib/asan/asan_linux.cpp
@@ -214,11 +214,19 @@ void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
   *stack = (uptr)ucp->uc_stack.ss_sp;
   *ssize = ucp->uc_stack.ss_size;
 }
-#else
+
+void ResetContextStack(void *context) {
+  ucontext_t *ucp = (ucontext_t *)context;
+  ucp->uc_stack.ss_sp = nullptr;
+  ucp->uc_stack.ss_size = 0;
+}
+#  else
 void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
   UNIMPLEMENTED();
 }
-#endif
+
+void ResetContextStack(void *context) { UNIMPLEMENTED(); }
+#  endif
 
 void *AsanDlSymNext(const char *sym) {
   return dlsym(RTLD_NEXT, sym);

diff  --git a/compiler-rt/lib/asan/asan_mac.cpp b/compiler-rt/lib/asan/asan_mac.cpp
index 4f4ce92cc6a15..a2d5c31a3f774 100644
--- a/compiler-rt/lib/asan/asan_mac.cpp
+++ b/compiler-rt/lib/asan/asan_mac.cpp
@@ -99,6 +99,8 @@ void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
   UNIMPLEMENTED();
 }
 
+void ResetContextStack(void *context) { UNIMPLEMENTED(); }
+
 // Support for the following functions from libdispatch on Mac OS:
 //   dispatch_async_f()
 //   dispatch_async()

diff  --git a/compiler-rt/lib/asan/asan_win.cpp b/compiler-rt/lib/asan/asan_win.cpp
index 81958038fb1ce..f11df0613d1f4 100644
--- a/compiler-rt/lib/asan/asan_win.cpp
+++ b/compiler-rt/lib/asan/asan_win.cpp
@@ -267,6 +267,8 @@ void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
   UNIMPLEMENTED();
 }
 
+void ResetContextStack(void *context) { UNIMPLEMENTED(); }
+
 void AsanOnDeadlySignal(int, void *siginfo, void *context) { UNIMPLEMENTED(); }
 
 bool PlatformUnpoisonStacks() { return false; }

diff  --git a/compiler-rt/test/asan/TestCases/Linux/swapcontext_test.cpp b/compiler-rt/test/asan/TestCases/Linux/swapcontext_test.cpp
index 7478225899afb..102e62f5d4e8a 100644
--- a/compiler-rt/test/asan/TestCases/Linux/swapcontext_test.cpp
+++ b/compiler-rt/test/asan/TestCases/Linux/swapcontext_test.cpp
@@ -9,6 +9,8 @@
 // Android and musl do not support swapcontext.
 // REQUIRES: x86-target-arch && glibc-2.27
 
+#include <assert.h>
+#include <memory.h>
 #include <stdio.h>
 #include <ucontext.h>
 #include <unistd.h>
@@ -33,6 +35,7 @@ void ThrowAndCatch() {
 }
 
 void Child(int mode) {
+  assert(orig_context.uc_stack.ss_size == 0);
   char x[32] = {0};  // Stack gets poisoned.
   printf("Child: %p\n", x);
   ThrowAndCatch();  // Simulate __asan_handle_no_return().
@@ -50,13 +53,16 @@ void Child(int mode) {
 int Run(int arg, int mode, char *child_stack) {
   printf("Child stack: %p\n", child_stack);
   // Setup child context.
+  memset(&child_context, 0xff, sizeof(child_context));
   getcontext(&child_context);
+  assert(child_context.uc_stack.ss_size == 0);
   child_context.uc_stack.ss_sp = child_stack;
   child_context.uc_stack.ss_size = kStackSize / 2;
   if (mode == 0) {
     child_context.uc_link = &orig_context;
   }
   makecontext(&child_context, (void (*)())Child, 1, mode);
+  memset(&orig_context, 0xff, sizeof(orig_context));
   if (swapcontext(&orig_context, &child_context) < 0) {
     perror("swapcontext");
     return 0;


        


More information about the llvm-commits mailing list