From 031069d2bd41a2d4017988baea023ab33c445e8f Mon Sep 17 00:00:00 2001 From: Ryan Macnak Date: Tue, 10 Oct 2017 22:52:25 +0000 Subject: [PATCH] [vm] Avoid using a generated stub to get the current SP, since generated stubs aren't available during early start up. Change-Id: Ib0d78965ba5ccb1fa2b084d82b2bb79485b7900f Reviewed-on: https://dart-review.googlesource.com/12780 Commit-Queue: Ryan Macnak Reviewed-by: Zach Anderson --- runtime/platform/address_sanitizer.h | 24 +++++++------------ runtime/platform/platform_sources.gni | 1 + runtime/platform/safe_stack.h | 22 ++++++++++++++++++ runtime/vm/thread.cc | 33 ++++++++------------------- runtime/vm/thread.h | 4 +++- 5 files changed, 44 insertions(+), 40 deletions(-) create mode 100644 runtime/platform/safe_stack.h diff --git a/runtime/platform/address_sanitizer.h b/runtime/platform/address_sanitizer.h index e6a45e80548..e6216685e07 100644 --- a/runtime/platform/address_sanitizer.h +++ b/runtime/platform/address_sanitizer.h @@ -10,17 +10,23 @@ // Allow the use of ASan (AddressSanitizer). This is needed as ASan needs to be // told about areas where the VM does the equivalent of a long-jump. #if defined(__has_feature) - #if __has_feature(address_sanitizer) +#define USING_ADDRESS_SANITIZER +#endif +#endif + +#if defined(USING_ADDRESS_SANITIZER) extern "C" void __asan_unpoison_memory_region(void*, size_t); extern "C" void __lsan_register_root_region(const void* p, size_t size); extern "C" void __lsan_unregister_root_region(const void* p, size_t size); +#define NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) #define ASAN_UNPOISON(ptr, len) __asan_unpoison_memory_region(ptr, len) #define LSAN_REGISTER_ROOT_REGION(ptr, len) \ __lsan_register_root_region(ptr, len) #define LSAN_UNREGISTER_ROOT_REGION(ptr, len) \ __lsan_unregister_root_region(ptr, len) #else // __has_feature(address_sanitizer) +#define NO_SANITIZE_ADDRESS #define ASAN_UNPOISON(ptr, len) \ do { \ } while (false && (ptr) == 0 && (len) == 0) @@ -30,20 +36,6 @@ extern "C" void __lsan_unregister_root_region(const void* p, size_t size); #define LSAN_UNREGISTER_ROOT_REGION(ptr, len) \ do { \ } while (false && (ptr) == 0 && (len) == 0) -#endif // __has_feature(address_sanitizer) - -#else // defined(__has_feature) - -#define ASAN_UNPOISON(ptr, len) \ - do { \ - } while (false && (ptr) == 0 && (len) == 0) -#define LSAN_REGISTER_ROOT_REGION(ptr, len) \ - do { \ - } while (false && (ptr) == 0 && (len) == 0) -#define LSAN_UNREGISTER_ROOT_REGION(ptr, len) \ - do { \ - } while (false && (ptr) == 0 && (len) == 0) - -#endif // defined(__has_feature) +#endif // defined(USING_ADDRESS_SANITIZER) #endif // RUNTIME_PLATFORM_ADDRESS_SANITIZER_H_ diff --git a/runtime/platform/platform_sources.gni b/runtime/platform/platform_sources.gni index b17d96715c1..e007ac3dacd 100644 --- a/runtime/platform/platform_sources.gni +++ b/runtime/platform/platform_sources.gni @@ -19,6 +19,7 @@ platform_sources = [ "hashmap.h", "inttypes_support_win.h", "memory_sanitizer.h", + "safe_stack.h", "signal_blocker.h", "text_buffer.cc", "text_buffer.h", diff --git a/runtime/platform/safe_stack.h b/runtime/platform/safe_stack.h new file mode 100644 index 00000000000..3c68059132b --- /dev/null +++ b/runtime/platform/safe_stack.h @@ -0,0 +1,22 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#ifndef RUNTIME_PLATFORM_SAFE_STACK_H_ +#define RUNTIME_PLATFORM_SAFE_STACK_H_ + +#include "platform/globals.h" + +#if defined(__has_feature) +#if __has_feature(safe_stack) +#define USING_SAFE_STACK +#endif +#endif + +#if defined(USING_SAFE_STACK) +#define NO_SANITIZE_SAFE_STACK __attribute__((no_sanitize("safe-stack"))) +#else +#define NO_SANITIZE_SAFE_STACK +#endif + +#endif // RUNTIME_PLATFORM_SAFE_STACK_H_ diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc index 4273fbb0d7c..bbd5a559561 100644 --- a/runtime/vm/thread.cc +++ b/runtime/vm/thread.cc @@ -4,6 +4,8 @@ #include "vm/thread.h" +#include "platform/address_sanitizer.h" +#include "platform/safe_stack.h" #include "vm/compiler_stats.h" #include "vm/dart_api_state.h" #include "vm/growable_array.h" @@ -414,30 +416,15 @@ void Thread::ClearStackLimit() { SetStackLimit(~static_cast(0)); } -/* static */ +// Disable AdressSanitizer and SafeStack transformation on this function. In +// particular, taking the address of a local gives an address on the stack +// instead of an address in the shadow memory (AddressSanitizer) or the safe +// stack (SafeStack). +NO_SANITIZE_ADDRESS +NO_SANITIZE_SAFE_STACK uword Thread::GetCurrentStackPointer() { -#if !defined(TARGET_ARCH_DBC) - // Since AddressSanitizer's detect_stack_use_after_return instruments the - // C++ code to give out fake stack addresses, we call a stub in that case. - ASSERT(StubCode::GetCStackPointer_entry() != NULL); - uword (*func)() = reinterpret_cast( - StubCode::GetCStackPointer_entry()->EntryPoint()); -#else - uword (*func)() = NULL; -#endif -// But for performance (and to support simulators), we normally use a local. -#if defined(__has_feature) -#if __has_feature(address_sanitizer) || __has_feature(safe_stack) - uword current_sp = func(); - return current_sp; -#else - uword stack_allocated_local_address = reinterpret_cast(&func); - return stack_allocated_local_address; -#endif -#else - uword stack_allocated_local_address = reinterpret_cast(&func); - return stack_allocated_local_address; -#endif + uword stack_allocated_local = reinterpret_cast(&stack_allocated_local); + return stack_allocated_local; } void Thread::ScheduleInterrupts(uword interrupt_bits) { diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h index b9042046df2..e029abede9e 100644 --- a/runtime/vm/thread.h +++ b/runtime/vm/thread.h @@ -204,7 +204,9 @@ class Thread : public BaseThread { void ClearStackLimit(); // Returns the current C++ stack pointer. Equivalent taking the address of a - // stack allocated local, but plays well with AddressSanitizer. + // stack allocated local, but plays well with AddressSanitizer and SafeStack. + // Accurate enough for stack overflow checks but not accurate enough for + // alignment checks. static uword GetCurrentStackPointer(); // Access to the current stack limit for generated code. This may be