Commit 58285440 authored by Andrii Grynenko's avatar Andrii Grynenko Committed by Facebook Github Bot

Fix ASAN integration with detect_stack_use_after_return turned on

Summary: detect_stack_use_after_return enables fake stack logic. Previous implementation was relying on fiber releasing its fake stack before switch, which is not safe, because that fake stack may actually be in use. This diff implements a hacky workaround by building a freeFakeStack function, which can release fake stack outside of the fiber. Ideally this function should be provided by ASAN itself.

Reviewed By: yfeldblum

Differential Revision: D4631962

fbshipit-source-id: 6213e2a6b3cbc35fae3793fcf86b0614dd8ff825
parent 94a3d5d3
......@@ -103,6 +103,9 @@ void Fiber::init(bool recordStackUsed) {
Fiber::~Fiber() {
#ifdef FOLLY_SANITIZE_ADDRESS
if (asanFakeStack_ != nullptr) {
fiberManager_.freeFakeStack(asanFakeStack_);
}
fiberManager_.unpoisonFiberStack(this);
#endif
fiberManager_.stackAllocator_.deallocate(fiberStackLimit_, fiberStackSize_);
......
......@@ -217,6 +217,22 @@ void FiberManager::registerFinishSwitchStackWithAsan(
}
}
void FiberManager::freeFakeStack(void* fakeStack) {
static AsanStartSwitchStackFuncPtr fnStart = getStartSwitchStackFunc();
static AsanFinishSwitchStackFuncPtr fnFinish = getFinishSwitchStackFunc();
if (fnStart == nullptr || fnFinish == nullptr) {
LOG(FATAL) << "The version of ASAN in use doesn't support fibers";
}
void* saveFakeStack;
const void* stackBottom;
size_t stackSize;
fnStart(&saveFakeStack, nullptr, 0);
fnFinish(fakeStack, &stackBottom, &stackSize);
fnStart(nullptr, stackBottom, stackSize);
fnFinish(saveFakeStack, nullptr, nullptr);
}
void FiberManager::unpoisonFiberStack(const Fiber* fiber) {
auto stack = fiber->getStack();
......
......@@ -85,11 +85,10 @@ inline void FiberManager::deactivateFiber(Fiber* fiber) {
DCHECK(fiber->asanMainStackBase_);
DCHECK(fiber->asanMainStackSize_);
// Release fake stack if fiber is completed
auto saveFakeStackPtr =
fiber->state_ == Fiber::INVALID ? nullptr : &fiber->asanFakeStack_;
registerStartSwitchStackWithAsan(
saveFakeStackPtr, fiber->asanMainStackBase_, fiber->asanMainStackSize_);
&fiber->asanFakeStack_,
fiber->asanMainStackBase_,
fiber->asanMainStackSize_);
SCOPE_EXIT {
registerFinishSwitchStackWithAsan(
fiber->asanFakeStack_,
......
......@@ -478,6 +478,7 @@ class FiberManager : public ::folly::Executor {
void* fakeStack,
const void** saveStackBase,
size_t* saveStackSize);
void freeFakeStack(void* fakeStack);
void unpoisonFiberStack(const Fiber* fiber);
#endif // FOLLY_SANITIZE_ADDRESS
......
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