Commit 8ef03f99 authored by Kenny Yu's avatar Kenny Yu Committed by Facebook GitHub Bot

ensure normal stack addresses are valid when walking async stacks

Summary: This ensures that when we collect the normal stack traces while collecting the async stack traces, the normal stack addresses are within a valid range. The normal stack addresses may be invalid because some functions may not follow the usual calling convention, for example with TSAN or with Lua FFI calling into C++.

Reviewed By: yfeldblum

Differential Revision: D32108552

fbshipit-source-id: 97b652f5e71b67dfa810549d837c7a0393d7c4cb
parent c8aa2cb7
...@@ -68,6 +68,10 @@ ssize_t getStackTrace( ...@@ -68,6 +68,10 @@ ssize_t getStackTrace(
namespace { namespace {
// Heuristic for guessing the maximum stack frame size. This is needed to ensure
// we do not have stack corruption while walking the stack.
constexpr uint64_t kMaxExpectedStackFrameSize = 0x1000000000;
#if FOLLY_HAVE_LIBUNWIND #if FOLLY_HAVE_LIBUNWIND
inline bool getFrameInfo(unw_cursor_t* cursor, uintptr_t& ip) { inline bool getFrameInfo(unw_cursor_t* cursor, uintptr_t& ip) {
...@@ -181,14 +185,18 @@ size_t walkNormalStack( ...@@ -181,14 +185,18 @@ size_t walkNormalStack(
StackFrame* normalStackFrame, StackFrame* normalStackFrame,
StackFrame* normalStackFrameStop) { StackFrame* normalStackFrameStop) {
size_t numFrames = 0; size_t numFrames = 0;
while (numFrames < maxAddresses && normalStackFrame != nullptr) {
auto* normalStackFrameNext = normalStackFrame->parentFrame;
if (!(normalStackFrameNext > normalStackFrame &&
normalStackFrameNext <
normalStackFrame + kMaxExpectedStackFrameSize)) {
// Stack frame addresses should increase as we traverse the stack. // Stack frame addresses should increase as we traverse the stack.
// If it doesn't, it means we have stack corruption, or an unusual calling // If it doesn't, it means we have stack corruption, or an unusual calling
// convention. In this case, stop walking the stack early to avoid incorrect // convention. Ensure that each subsequent frame's address is within a
// stack walking. // valid range. If it does not, stop walking the stack early to avoid
auto* normalStackFrameStart = normalStackFrame; // incorrect stack walking.
while (numFrames < maxAddresses && normalStackFrame != nullptr && break;
normalStackFrame >= normalStackFrameStart) { }
auto* normalStackFrameNext = normalStackFrame->parentFrame;
if (normalStackFrameStop != nullptr && if (normalStackFrameStop != nullptr &&
normalStackFrameNext == normalStackFrameStop) { normalStackFrameNext == normalStackFrameStop) {
// Reached end of normal stack, need to transition to the async stack. // Reached end of normal stack, need to transition to the async stack.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment