[llvm-commits] [compiler-rt] r168508 - in /compiler-rt/trunk/lib/asan: asan_intercepted_functions.h asan_interceptors.cc asan_internal.h asan_posix.cc asan_report.cc asan_win.cc lit_tests/swapcontext_test.cc
Alexey Samsonov
samsonov at google.com
Fri Nov 23 01:46:34 PST 2012
Author: samsonov
Date: Fri Nov 23 03:46:34 2012
New Revision: 168508
URL: http://llvm.org/viewvc/llvm-project?rev=168508&view=rev
Log:
[ASan] Add interceptor for swapcontext to fight with false positives in some of its use cases.
Added:
compiler-rt/trunk/lib/asan/lit_tests/swapcontext_test.cc
Modified:
compiler-rt/trunk/lib/asan/asan_intercepted_functions.h
compiler-rt/trunk/lib/asan/asan_interceptors.cc
compiler-rt/trunk/lib/asan/asan_internal.h
compiler-rt/trunk/lib/asan/asan_posix.cc
compiler-rt/trunk/lib/asan/asan_report.cc
compiler-rt/trunk/lib/asan/asan_win.cc
Modified: compiler-rt/trunk/lib/asan/asan_intercepted_functions.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_intercepted_functions.h?rev=168508&r1=168507&r2=168508&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_intercepted_functions.h (original)
+++ compiler-rt/trunk/lib/asan/asan_intercepted_functions.h Fri Nov 23 03:46:34 2012
@@ -53,8 +53,10 @@
#if !defined(ANDROID) && !defined(_WIN32)
# define ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 1
+# define ASAN_INTERCEPT_SWAPCONTEXT 1
#else
# define ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 0
+# define ASAN_INTERCEPT_SWAPCONTEXT 0
#endif
// On Darwin siglongjmp tailcalls longjmp, so we don't want to intercept it
@@ -88,6 +90,12 @@
DECLARE_FUNCTION_AND_WRAPPER(void*, signal, int signum, void *handler);
# endif
+// ucontext.h
+# if ASAN_INTERCEPT_SWAPCONTEXT
+DECLARE_FUNCTION_AND_WRAPPER(int, swapcontext, struct ucontext_t *oucp,
+ struct ucontext_t *ucp);
+# endif
+
// setjmp.h
DECLARE_FUNCTION_AND_WRAPPER(void, longjmp, void *env, int value);
# if ASAN_INTERCEPT__LONGJMP
Modified: compiler-rt/trunk/lib/asan/asan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_interceptors.cc?rev=168508&r1=168507&r2=168508&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.cc Fri Nov 23 03:46:34 2012
@@ -136,6 +136,28 @@
struct sigaction *oldact);
#endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
+#if ASAN_INTERCEPT_SWAPCONTEXT
+INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
+ struct ucontext_t *ucp) {
+ static bool reported_warning = false;
+ if (!reported_warning) {
+ Report("WARNING: ASan doesn't fully support makecontext/swapcontext "
+ "functions and may produce false positives in some cases!\n");
+ reported_warning = true;
+ }
+ // Clear shadow memory for new context (it may share stack
+ // with current context).
+ ClearShadowMemoryForContext(ucp);
+ int res = REAL(swapcontext)(oucp, ucp);
+ // swapcontext technically does not return, but program may swap context to
+ // "oucp" later, that would look as if swapcontext() returned 0.
+ // We need to clear shadow for ucp once again, as it may be in arbitrary
+ // state.
+ ClearShadowMemoryForContext(ucp);
+ return res;
+}
+#endif
+
INTERCEPTOR(void, longjmp, void *env, int val) {
__asan_handle_no_return();
REAL(longjmp)(env, val);
@@ -689,6 +711,9 @@
ASAN_INTERCEPT_FUNC(sigaction);
ASAN_INTERCEPT_FUNC(signal);
#endif
+#if ASAN_INTERCEPT_SWAPCONTEXT
+ ASAN_INTERCEPT_FUNC(swapcontext);
+#endif
#if ASAN_INTERCEPT__LONGJMP
ASAN_INTERCEPT_FUNC(_longjmp);
#endif
Modified: compiler-rt/trunk/lib/asan/asan_internal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_internal.h?rev=168508&r1=168507&r2=168508&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_internal.h (original)
+++ compiler-rt/trunk/lib/asan/asan_internal.h Fri Nov 23 03:46:34 2012
@@ -116,6 +116,7 @@
void SetAlternateSignalStack();
void UnsetAlternateSignalStack();
void InstallSignalHandlers();
+void ClearShadowMemoryForContext(void *context);
void AsanPlatformThreadInit();
// Wrapper for TLS/TSD.
Modified: compiler-rt/trunk/lib/asan/asan_posix.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_posix.cc?rev=168508&r1=168507&r2=168508&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_posix.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_posix.cc Fri Nov 23 03:46:34 2012
@@ -27,6 +27,7 @@
#include <stdlib.h>
#include <sys/time.h>
#include <sys/resource.h>
+#include <ucontext.h>
#include <unistd.h>
static const uptr kAltStackSize = SIGSTKSZ * 4; // SIGSTKSZ is not enough.
@@ -95,6 +96,17 @@
MaybeInstallSigaction(SIGBUS, ASAN_OnSIGSEGV);
}
+void ClearShadowMemoryForContext(void *context) {
+ ucontext_t *ucp = (ucontext_t*)context;
+ uptr sp = (uptr)ucp->uc_stack.ss_sp;
+ uptr size = ucp->uc_stack.ss_size;
+ // Align to page size.
+ uptr bottom = sp & ~(kPageSize - 1);
+ size += sp - bottom;
+ size = RoundUpTo(size, kPageSize);
+ PoisonShadow(bottom, size, 0);
+}
+
// ---------------------- TSD ---------------- {{{1
static pthread_key_t tsd_key;
Modified: compiler-rt/trunk/lib/asan/asan_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_report.cc?rev=168508&r1=168507&r2=168508&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_report.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_report.cc Fri Nov 23 03:46:34 2012
@@ -180,7 +180,7 @@
Printf(" [%zu, %zu) '%s'\n", beg, beg + size, buf);
}
Printf("HINT: this may be a false positive if your program uses "
- "some custom stack unwind mechanism\n"
+ "some custom stack unwind mechanism or swapcontext\n"
" (longjmp and C++ exceptions *are* supported)\n");
DescribeThread(t->summary());
return true;
Modified: compiler-rt/trunk/lib/asan/asan_win.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_win.cc?rev=168508&r1=168507&r2=168508&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_win.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_win.cc Fri Nov 23 03:46:34 2012
@@ -139,6 +139,10 @@
// Nothing here for now.
}
+void ClearShadowMemoryForContext(void *context) {
+ UNIMPLEMENTED();
+}
+
} // namespace __asan
// ---------------------- Interface ---------------- {{{1
Added: compiler-rt/trunk/lib/asan/lit_tests/swapcontext_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/lit_tests/swapcontext_test.cc?rev=168508&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/lit_tests/swapcontext_test.cc (added)
+++ compiler-rt/trunk/lib/asan/lit_tests/swapcontext_test.cc Fri Nov 23 03:46:34 2012
@@ -0,0 +1,66 @@
+// Check that ASan plays well with easy cases of makecontext/swapcontext.
+
+// RUN: %clangxx_asan -m64 -O0 %s -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -m64 -O1 %s -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -m64 -O2 %s -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -m64 -O3 %s -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -m32 -O0 %s -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -m32 -O1 %s -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -m32 -O2 %s -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -m32 -O3 %s -o %t && %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+#include <ucontext.h>
+#include <unistd.h>
+
+ucontext_t orig_context;
+ucontext_t child_context;
+
+void Child(int mode) {
+ char x[32] = {0}; // Stack gets poisoned.
+ printf("Child: %p\n", x);
+ // (a) Do nothing, just return to parent function.
+ // (b) Jump into the original function. Stack remains poisoned unless we do
+ // something.
+ if (mode == 1) {
+ if (swapcontext(&child_context, &orig_context) < 0) {
+ perror("swapcontext");
+ _exit(0);
+ }
+ }
+}
+
+int Run(int arg, int mode) {
+ const int kStackSize = 1 << 20;
+ char child_stack[kStackSize + 1];
+ printf("Child stack: %p\n", child_stack);
+ // Setup child context.
+ getcontext(&child_context);
+ 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);
+ if (swapcontext(&orig_context, &child_context) < 0) {
+ perror("swapcontext");
+ return 0;
+ }
+ // Touch childs's stack to make sure it's unpoisoned.
+ for (int i = 0; i < kStackSize; i++) {
+ child_stack[i] = i;
+ }
+ return child_stack[arg];
+}
+
+int main(int argc, char **argv) {
+ // CHECK: WARNING: ASan doesn't fully support makecontext/swapcontext
+ int ret = 0;
+ ret += Run(argc - 1, 0);
+ printf("Test1 passed\n");
+ // CHECK: Test1 passed
+ ret += Run(argc - 1, 1);
+ printf("Test2 passed\n");
+ // CHECK: Test2 passed
+ return ret;
+}
More information about the llvm-commits
mailing list