summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/msan/lit_tests/wrap_indirect_calls2.cc42
-rw-r--r--lib/msan/lit_tests/wrap_indirect_calls_in_rtl.cc8
-rw-r--r--lib/msan/msan.cc24
-rw-r--r--lib/msan/msan_flags.h1
-rw-r--r--lib/msan/msan_interface_internal.h9
-rw-r--r--lib/sanitizer_common/sanitizer_common.h4
-rw-r--r--lib/sanitizer_common/sanitizer_linux_libcdep.cc5
7 files changed, 73 insertions, 20 deletions
diff --git a/lib/msan/lit_tests/wrap_indirect_calls2.cc b/lib/msan/lit_tests/wrap_indirect_calls2.cc
new file mode 100644
index 000000000..c188047ce
--- /dev/null
+++ b/lib/msan/lit_tests/wrap_indirect_calls2.cc
@@ -0,0 +1,42 @@
+// Test __msan_set_indirect_call_wrapper.
+
+// RUN: %clangxx_msan -mllvm -msan-wrap-indirect-calls=__msan_wrap_indirect_call \
+// RUN: -mllvm -msan-wrap-indirect-calls-fast=0 \
+// RUN: -O0 -g -rdynamic -Wl,--defsym=__executable_start=0 %s -o %t && %t
+
+// This test disables -msan-wrap-indirect-calls-fast, otherwise indirect calls
+// inside the same module are short-circuited and are never seen by the wrapper.
+
+#include <assert.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdint.h>
+
+extern "C" void __msan_set_indirect_call_wrapper(uintptr_t);
+
+bool done_f, done_g;
+
+void f(void) {
+ assert(!done_g);
+ done_f = true;
+}
+
+void g(void) {
+ assert(done_f);
+ done_g = true;
+}
+
+typedef void (*Fn)(void);
+extern "C" Fn my_wrapper(Fn target) {
+ if (target == f) return g;
+ return target;
+}
+
+int main(void) {
+ volatile Fn fp;
+ fp = &f;
+ fp();
+ __msan_set_indirect_call_wrapper((uintptr_t)my_wrapper);
+ fp();
+ return !(done_f && done_g);
+}
diff --git a/lib/msan/lit_tests/wrap_indirect_calls_in_rtl.cc b/lib/msan/lit_tests/wrap_indirect_calls_in_rtl.cc
index 18de9d705..b13caee33 100644
--- a/lib/msan/lit_tests/wrap_indirect_calls_in_rtl.cc
+++ b/lib/msan/lit_tests/wrap_indirect_calls_in_rtl.cc
@@ -1,13 +1,14 @@
// Test indirect call wrapping in MemorySanitizer runtime.
-// RUN: %clangxx_msan -O0 -g -rdynamic %s -o %t
-// RUN: MSAN_OPTIONS=wrap_indirect_calls=zzzwrapper %t
+// RUN: %clangxx_msan -O0 -g -rdynamic %s -o %t && %t
#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdint.h>
+extern "C" void __msan_set_indirect_call_wrapper(uintptr_t);
+
bool done;
void *ThreadFn(void *) {
@@ -24,13 +25,14 @@ void *ThreadFn2(void *) {
// ThreadFn is called indirectly from a wrapper function in MSan rtl and
// is subject to indirect call wrapping (it could be an native-to-translated
// edge).
-extern "C" uintptr_t zzzwrapper(uintptr_t f) {
+extern "C" uintptr_t my_wrapper(uintptr_t f) {
if (f == (uintptr_t)ThreadFn)
return (uintptr_t)&ThreadFn2;
return f;
}
int main(void) {
+ __msan_set_indirect_call_wrapper((uintptr_t)my_wrapper);
pthread_t t;
pthread_create(&t, 0, ThreadFn, 0);
pthread_join(t, 0);
diff --git a/lib/msan/msan.cc b/lib/msan/msan.cc
index cee62c520..c9c3b8acf 100644
--- a/lib/msan/msan.cc
+++ b/lib/msan/msan.cc
@@ -31,7 +31,7 @@ using namespace __sanitizer;
static THREADLOCAL int msan_expect_umr = 0;
static THREADLOCAL int msan_expected_umr_found = 0;
-static int msan_running_under_dr = 0;
+static bool msan_running_under_dr;
// Function argument shadow. Each argument starts at the next available 8-byte
// aligned address.
@@ -74,10 +74,6 @@ extern "C" SANITIZER_WEAK_ATTRIBUTE const int __msan_keep_going;
namespace __msan {
-static bool IsRunningUnderDr() {
- return false;
-}
-
void EnterSymbolizer() { ++is_in_symbolizer; }
void ExitSymbolizer() { --is_in_symbolizer; }
bool IsInSymbolizer() { return is_in_symbolizer; }
@@ -122,7 +118,6 @@ static void ParseFlagsFromString(Flags *f, const char *str) {
}
ParseFlag(str, &f->report_umrs, "report_umrs");
ParseFlag(str, &f->wrap_signals, "wrap_signals");
- ParseFlag(str, &f->wrap_indirect_calls, "wrap_indirect_calls");
// keep_going is an old name for halt_on_error,
// and it has inverse meaning.
@@ -147,7 +142,6 @@ static void InitializeFlags(Flags *f, const char *options) {
f->exit_code = 77;
f->report_umrs = true;
f->wrap_signals = true;
- f->wrap_indirect_calls = "dr_app_handle_mbr_target";
f->halt_on_error = !&__msan_keep_going;
// Override from user-specified string.
@@ -292,7 +286,6 @@ void __msan_init() {
VPrintf(1, "MSAN_OPTIONS: %s\n", msan_options ? msan_options : "<empty>");
- msan_running_under_dr = IsRunningUnderDr();
__msan_clear_on_return();
if (__msan_get_track_origins())
VPrintf(1, "msan_track_origins\n");
@@ -324,8 +317,6 @@ void __msan_init() {
msan_init_is_running = 0;
msan_inited = 1;
-
- InitializeIndirectCallWrapping(flags()->wrap_indirect_calls);
}
void __msan_set_exit_code(int exit_code) {
@@ -542,10 +533,21 @@ void __sanitizer_unaligned_store64(uu64 *p, u64 x) {
*p = x;
}
+void *__msan_wrap_indirect_call(void *target) {
+ return IndirectExternCall(target);
+}
+
+void __msan_dr_is_initialized() {
+ msan_running_under_dr = true;
+}
+
+void __msan_set_indirect_call_wrapper(uptr wrapper) {
+ SetIndirectCallWrapper(wrapper);
+}
+
#if !SANITIZER_SUPPORTS_WEAK_HOOKS
extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
const char* __msan_default_options() { return ""; }
} // extern "C"
#endif
-
diff --git a/lib/msan/msan_flags.h b/lib/msan/msan_flags.h
index 9cf48e604..93fa8a60d 100644
--- a/lib/msan/msan_flags.h
+++ b/lib/msan/msan_flags.h
@@ -26,7 +26,6 @@ struct Flags {
bool report_umrs;
bool wrap_signals;
bool halt_on_error;
- const char *wrap_indirect_calls;
};
Flags *flags();
diff --git a/lib/msan/msan_interface_internal.h b/lib/msan/msan_interface_internal.h
index 794b3540f..c87b2bad2 100644
--- a/lib/msan/msan_interface_internal.h
+++ b/lib/msan/msan_interface_internal.h
@@ -170,6 +170,15 @@ SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
/* OPTIONAL */ void __msan_free_hook(void *ptr);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_dr_is_initialized();
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__msan_wrap_indirect_call(void *target);
+
+SANITIZER_INTERFACE_ATTRIBUTE
+void __msan_set_indirect_call_wrapper(uptr wrapper);
} // extern "C"
#endif // MSAN_INTERFACE_INTERNAL_H
diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h
index b61e9a0f6..f9fc254e5 100644
--- a/lib/sanitizer_common/sanitizer_common.h
+++ b/lib/sanitizer_common/sanitizer_common.h
@@ -487,7 +487,7 @@ typedef void (*RangeIteratorCallback)(uptr begin, uptr end, void *arg);
#if SANITIZER_LINUX && !defined(SANITIZER_GO)
extern uptr indirect_call_wrapper;
-void InitializeIndirectCallWrapping(const char *wrapper_name);
+void SetIndirectCallWrapper(uptr wrapper);
template <typename F>
F IndirectExternCall(F f) {
@@ -495,7 +495,7 @@ F IndirectExternCall(F f) {
return indirect_call_wrapper ? ((WrapF)indirect_call_wrapper)(f) : f;
}
#else
-inline void InitializeIndirectCallWrapping(const char *wrapper_name) {}
+inline void SetIndirectCallWrapper(uptr wrapper) {}
template <typename F>
F IndirectExternCall(F f) {
return f;
diff --git a/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_linux_libcdep.cc
index 890dd8f99..ec8125dbc 100644
--- a/lib/sanitizer_common/sanitizer_linux_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_linux_libcdep.cc
@@ -356,9 +356,8 @@ uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
#ifndef SANITIZER_GO
uptr indirect_call_wrapper;
-void InitializeIndirectCallWrapping(const char *wrapper_name) {
- CHECK(wrapper_name && *wrapper_name);
- indirect_call_wrapper = (uptr)dlsym(RTLD_DEFAULT, wrapper_name);
+void SetIndirectCallWrapper(uptr wrapper) {
+ indirect_call_wrapper = wrapper;
}
#endif