SafeStack-friendly stack protection in ART.
This code takes an address of a stack variable to find the current
stack top. With SafeStack, such variables can be allocated on a
separate, "unsafe" stack, generating a completely bogus address.
Use __builtin_frame_address(0) instead.
Change-Id: I84fe3161bdd01cebbb4e9bebf2aca86783cc6f15
diff --git a/runtime/thread.cc b/runtime/thread.cc
index fb24828..147e07b 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -513,14 +513,20 @@
return stack_size;
}
+// Return the nearest page-aligned address below the current stack top.
+NO_INLINE
+static uint8_t* FindStackTop() {
+ return reinterpret_cast<uint8_t*>(
+ AlignDown(__builtin_frame_address(0), kPageSize));
+}
+
// Install a protected region in the stack. This is used to trigger a SIGSEGV if a stack
// overflow is detected. It is located right below the stack_begin_.
ATTRIBUTE_NO_SANITIZE_ADDRESS
void Thread::InstallImplicitProtection() {
uint8_t* pregion = tlsPtr_.stack_begin - kStackOverflowProtectedSize;
- uint8_t* stack_himem = tlsPtr_.stack_end;
- uint8_t* stack_top = reinterpret_cast<uint8_t*>(reinterpret_cast<uintptr_t>(&stack_himem) &
- ~(kPageSize - 1)); // Page containing current top of stack.
+ // Page containing current top of stack.
+ uint8_t* stack_top = FindStackTop();
// Try to directly protect the stack.
VLOG(threads) << "installing stack protected region at " << std::hex <<
@@ -932,8 +938,7 @@
}
// Sanity check.
- int stack_variable;
- CHECK_GT(&stack_variable, reinterpret_cast<void*>(tlsPtr_.stack_end));
+ CHECK_GT(FindStackTop(), reinterpret_cast<void*>(tlsPtr_.stack_end));
return true;
}