[Fuchsia] Safestack fix for exceptions

The safestack stack pointer is cached when invoking Dart code, and
manually restored when jumping over C++ frames for Dart exceptions
in Exceptions::JumpToFrame().

fixes #31356

Change-Id: I71c2e86d1d4f24571dd618a5db06fd1277339ebc
Reviewed-on: https://dart-review.googlesource.com/23141
Commit-Queue: Zach Anderson <zra@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
This commit is contained in:
Zachary Anderson 2017-11-22 19:27:54 +00:00 committed by commit-bot@chromium.org
parent 726337aa69
commit f97e11f624
10 changed files with 180 additions and 1 deletions

View file

@ -4,6 +4,7 @@
#include "vm/dart_entry.h"
#include "platform/safe_stack.h"
#include "vm/class_finalizer.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/debugger.h"
@ -31,8 +32,16 @@ RawObject* DartEntry::InvokeFunction(const Function& function,
class ScopedIsolateStackLimits : public ValueObject {
public:
NO_SANITIZE_SAFE_STACK
explicit ScopedIsolateStackLimits(Thread* thread, uword current_sp)
: thread_(thread), saved_stack_limit_(0) {
: thread_(thread),
#if defined(USING_SAFE_STACK)
saved_stack_limit_(0),
saved_safestack_limit_(0)
#else
saved_stack_limit_(0)
#endif
{
ASSERT(thread != NULL);
// Set the thread's stack_base based on the current
// stack pointer, we keep refining this value as we
@ -47,6 +56,11 @@ class ScopedIsolateStackLimits : public ValueObject {
ASSERT(thread->isolate() == Isolate::Current());
saved_stack_limit_ = thread->saved_stack_limit();
thread->SetStackLimitFromStackBase(os_thread->stack_base());
#if defined(USING_SAFE_STACK)
saved_safestack_limit_ = OSThread::GetCurrentSafestackPointer();
thread->set_saved_safestack_limit(saved_safestack_limit_);
#endif
}
~ScopedIsolateStackLimits() {
@ -55,11 +69,17 @@ class ScopedIsolateStackLimits : public ValueObject {
// to a stack limit of 0 when all nested invocations are done and
// we have bottomed out.
thread_->SetStackLimit(saved_stack_limit_);
#if defined(USING_SAFE_STACK)
thread_->set_saved_safestack_limit(saved_safestack_limit_);
#endif
}
private:
Thread* thread_;
uword saved_stack_limit_;
#if defined(USING_SAFE_STACK)
uword saved_safestack_limit_;
#endif
};
// Clears/restores Thread::long_jump_base on construction/destruction.
@ -80,6 +100,7 @@ class SuspendLongJumpScope : public StackResource {
LongJumpScope* saved_long_jump_base_;
};
NO_SANITIZE_SAFE_STACK
RawObject* DartEntry::InvokeFunction(const Function& function,
const Array& arguments,
const Array& arguments_descriptor,

View file

@ -445,6 +445,7 @@ static void JumpToExceptionHandler(Thread* thread,
frame_pointer, false /* do not clear deopt */);
}
NO_SANITIZE_SAFE_STACK // This function manipulates the safestack pointer.
void Exceptions::JumpToFrame(Thread* thread,
uword program_counter,
uword stack_pointer,
@ -481,6 +482,13 @@ void Exceptions::JumpToFrame(Thread* thread,
ASAN_UNPOISON(reinterpret_cast<void*>(current_sp),
stack_pointer - current_sp);
// We are jumping over C++ frames, so we have to set the safestack pointer
// back to what it was when we entered the runtime from Dart code.
#if defined(USING_SAFE_STACK)
const uword saved_ssp = thread->saved_safestack_limit();
OSThread::SetCurrentSafestackPointer(saved_ssp);
#endif
func(program_counter, stack_pointer, frame_pointer, thread);
#endif
UNREACHABLE();

View file

@ -5,7 +5,9 @@
#ifndef RUNTIME_VM_OS_THREAD_H_
#define RUNTIME_VM_OS_THREAD_H_
#include "platform/address_sanitizer.h"
#include "platform/globals.h"
#include "platform/safe_stack.h"
#include "vm/allocation.h"
#include "vm/globals.h"
@ -108,6 +110,11 @@ class OSThread : public BaseThread {
// May fail for the main thread on Linux and Android.
static bool GetCurrentStackBounds(uword* lower, uword* upper);
#if defined(USING_SAFE_STACK)
static uword GetCurrentSafestackPointer();
static void SetCurrentSafestackPointer(uword ssp);
#endif
// Used to temporarily disable or enable thread interrupts.
void DisableThreadInterrupts();
void EnableThreadInterrupts();

View file

@ -11,7 +11,9 @@
#include <errno.h> // NOLINT
#include <sys/time.h> // NOLINT
#include "platform/address_sanitizer.h"
#include "platform/assert.h"
#include "platform/safe_stack.h"
#include "platform/signal_blocker.h"
#include "platform/utils.h"
@ -246,6 +248,21 @@ bool OSThread::GetCurrentStackBounds(uword* lower, uword* upper) {
return true;
}
#if defined(USING_SAFE_STACK)
NO_SANITIZE_ADDRESS
NO_SANITIZE_SAFE_STACK
uword OSThread::GetCurrentSafestackPointer() {
#error "SAFE_STACK is unsupported on this platform"
return 0;
}
NO_SANITIZE_ADDRESS
NO_SANITIZE_SAFE_STACK
void OSThread::SetCurrentSafestackPointer(uword ssp) {
#error "SAFE_STACK is unsupported on this platform"
}
#endif
Mutex::Mutex(NOT_IN_PRODUCT(const char* name))
#if !defined(PRODUCT)
: name_(name)

View file

@ -14,9 +14,12 @@
#include <zircon/syscalls.h>
#include <zircon/syscalls/object.h>
#include <zircon/threads.h>
#include <zircon/tls.h>
#include <zircon/types.h>
#include "platform/address_sanitizer.h"
#include "platform/assert.h"
#include "platform/safe_stack.h"
namespace dart {
@ -228,6 +231,63 @@ bool OSThread::GetCurrentStackBounds(uword* lower, uword* upper) {
return true;
}
#if defined(USING_SAFE_STACK)
#define STRINGIFY(s) #s
NO_SANITIZE_ADDRESS
NO_SANITIZE_SAFE_STACK
uword OSThread::GetCurrentSafestackPointer() {
uword result;
#if defined(HOST_ARCH_X64)
#define _loadfsword(index) "movq %%fs:" STRINGIFY(index) ", %0"
asm volatile(
_loadfsword(ZX_TLS_UNSAFE_SP_OFFSET)
: "=r"(result) // outputs
);
#undef _loadfsword
#elif defined(HOST_ARCH_ARM64)
#define _loadword(index) "ldr %0, [%0, " STRINGIFY(index) "]"
asm volatile(
"mrs %0, TPIDR_EL0;\n"
_loadword(ZX_TLS_UNSAFE_SP_OFFSET)
: "=r"(result) // outputs
);
#else
#error "Architecture not supported"
#endif
return result;
}
NO_SANITIZE_ADDRESS
NO_SANITIZE_SAFE_STACK
void OSThread::SetCurrentSafestackPointer(uword ssp) {
#if defined(HOST_ARCH_X64)
#define str(s) #s
#define _storefsword(index) "movq %0, %%fs:" str(index)
asm volatile(
_storefsword(ZX_TLS_UNSAFE_SP_OFFSET)
: // outputs.
: "r"(ssp) // inputs.
: // clobbered.
);
#undef _storefsword
#undef str
#elif defined(HOST_ARCH_ARM64)
#define _storeword(index) "str %1, [%0, " STRINGIFY(index) "]"
uword tmp;
asm volatile(
"mrs %0, TPIDR_EL0;\n"
_storeword(ZX_TLS_UNSAFE_SP_OFFSET)
: "=r"(tmp) // outputs.
: "r"(ssp) // inputs.
: // clobbered.
);
#else
#error "Architecture not supported"
#endif
}
#undef STRINGIFY
#endif
Mutex::Mutex(NOT_IN_PRODUCT(const char* name))
#if !defined(PRODUCT)
: name_(name)

View file

@ -13,7 +13,9 @@
#include <sys/syscall.h> // NOLINT
#include <sys/time.h> // NOLINT
#include "platform/address_sanitizer.h"
#include "platform/assert.h"
#include "platform/safe_stack.h"
#include "platform/signal_blocker.h"
#include "platform/utils.h"
@ -248,6 +250,21 @@ bool OSThread::GetCurrentStackBounds(uword* lower, uword* upper) {
return true;
}
#if defined(USING_SAFE_STACK)
NO_SANITIZE_ADDRESS
NO_SANITIZE_SAFE_STACK
uword OSThread::GetCurrentSafestackPointer() {
#error "SAFE_STACK is unsupported on this platform"
return 0;
}
NO_SANITIZE_ADDRESS
NO_SANITIZE_SAFE_STACK
void OSThread::SetCurrentSafestackPointer(uword ssp) {
#error "SAFE_STACK is unsupported on this platform"
}
#endif
Mutex::Mutex(NOT_IN_PRODUCT(const char* name))
#if !defined(PRODUCT)
: name_(name)

View file

@ -18,7 +18,9 @@
#include <sys/sysctl.h> // NOLINT
#include <sys/types.h> // NOLINT
#include "platform/address_sanitizer.h"
#include "platform/assert.h"
#include "platform/safe_stack.h"
#include "platform/utils.h"
#include "vm/profiler.h"
@ -210,6 +212,21 @@ bool OSThread::GetCurrentStackBounds(uword* lower, uword* upper) {
return true;
}
#if defined(USING_SAFE_STACK)
NO_SANITIZE_ADDRESS
NO_SANITIZE_SAFE_STACK
uword OSThread::GetCurrentSafestackPointer() {
#error "SAFE_STACK is unsupported on this platform"
return 0;
}
NO_SANITIZE_ADDRESS
NO_SANITIZE_SAFE_STACK
void OSThread::SetCurrentSafestackPointer(uword ssp) {
#error "SAFE_STACK is unsupported on this platform"
}
#endif
Mutex::Mutex(NOT_IN_PRODUCT(const char* name))
#if !defined(PRODUCT)
: name_(name)

View file

@ -11,7 +11,9 @@
#include <process.h> // NOLINT
#include "platform/address_sanitizer.h"
#include "platform/assert.h"
#include "platform/safe_stack.h"
namespace dart {
@ -190,6 +192,21 @@ bool OSThread::GetCurrentStackBounds(uword* lower, uword* upper) {
return true;
}
#if defined(USING_SAFE_STACK)
NO_SANITIZE_ADDRESS
NO_SANITIZE_SAFE_STACK
uword OSThread::GetCurrentSafestackPointer() {
#error "SAFE_STACK is unsupported on this platform"
return 0;
}
NO_SANITIZE_ADDRESS
NO_SANITIZE_SAFE_STACK
void OSThread::SetCurrentSafestackPointer(uword ssp) {
#error "SAFE_STACK is unsupported on this platform"
}
#endif
void OSThread::SetThreadLocal(ThreadLocalKey key, uword value) {
ASSERT(key != kUnsetThreadLocalKey);
BOOL result = TlsSetValue(key, reinterpret_cast<void*>(value));

View file

@ -104,6 +104,9 @@ Thread::Thread(Isolate* isolate)
REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS)
REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT) safepoint_state_(0),
execution_state_(kThreadInNative),
#if defined(USING_SAFE_STACK)
saved_safestack_limit_(0),
#endif
next_(NULL) {
#if !defined(PRODUCT)
dart_stream_ = Timeline::GetDartStream();

View file

@ -7,6 +7,7 @@
#include "include/dart_api.h"
#include "platform/assert.h"
#include "platform/safe_stack.h"
#include "vm/atomic.h"
#include "vm/bitfield.h"
#include "vm/globals.h"
@ -221,6 +222,13 @@ class Thread : public BaseThread {
// The true stack limit for this isolate.
uword saved_stack_limit() const { return saved_stack_limit_; }
#if defined(USING_SAFE_STACK)
uword saved_safestack_limit() const { return saved_safestack_limit_; }
void set_saved_safestack_limit(uword limit) {
saved_safestack_limit_ = limit;
}
#endif
#if defined(TARGET_ARCH_DBC)
// Access to the current stack limit for DBC interpreter.
uword stack_limit() const { return stack_limit_; }
@ -801,6 +809,10 @@ class Thread : public BaseThread {
uint32_t safepoint_state_;
uint32_t execution_state_;
#if defined(USING_SAFE_STACK)
uword saved_safestack_limit_;
#endif
Thread* next_; // Used to chain the thread structures in an isolate.
explicit Thread(Isolate* isolate);