aboutsummaryrefslogtreecommitdiff
path: root/compiler-rt
diff options
context:
space:
mode:
authorVitaly Buka <vitalybuka@google.com>2022-07-20 18:23:17 -0700
committerVitaly Buka <vitalybuka@google.com>2022-07-22 13:40:16 -0700
commitc93e4b6b2c497aecda82029d6f161bd81da26dab (patch)
tree70985b3ade5d0b0fad429a9b32150615111c69fd /compiler-rt
parent6a1ccf61cdf80c793f9c699ada33af5d85263b30 (diff)
[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
Diffstat (limited to 'compiler-rt')
-rw-r--r--compiler-rt/lib/asan/asan_interceptors.cpp13
-rw-r--r--compiler-rt/lib/asan/asan_internal.h1
-rw-r--r--compiler-rt/lib/asan/asan_linux.cpp12
-rw-r--r--compiler-rt/lib/asan/asan_mac.cpp2
-rw-r--r--compiler-rt/lib/asan/asan_win.cpp2
-rw-r--r--compiler-rt/test/asan/TestCases/Linux/swapcontext_test.cpp6
6 files changed, 34 insertions, 2 deletions
diff --git a/compiler-rt/lib/asan/asan_interceptors.cpp b/compiler-rt/lib/asan/asan_interceptors.cpp
index 78d23abaad63..ff6ffeca36d5 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 7468f126d37b..9c46f225116e 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 defd81bc19e2..89450fc120a0 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 4f4ce92cc6a1..a2d5c31a3f77 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 81958038fb1c..f11df0613d1f 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 7478225899af..102e62f5d4e8 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;