mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 12:13:01 +00:00
[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:
parent
726337aa69
commit
f97e11f624
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue