From: Andrii Grynenko Date: Wed, 1 Mar 2017 18:37:55 +0000 (-0800) Subject: Fix ASAN integration with detect_stack_use_after_return turned on X-Git-Tag: v2017.03.06.00~8 X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=commitdiff_plain;h=58285440f100065fcc2f4357507bfd6ac8efd463 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 --- diff --git a/folly/fibers/Fiber.cpp b/folly/fibers/Fiber.cpp index 79866600..39dcc333 100644 --- a/folly/fibers/Fiber.cpp +++ b/folly/fibers/Fiber.cpp @@ -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_); diff --git a/folly/fibers/FiberManager.cpp b/folly/fibers/FiberManager.cpp index 2d17a4a3..8a04bde1 100644 --- a/folly/fibers/FiberManager.cpp +++ b/folly/fibers/FiberManager.cpp @@ -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(); diff --git a/folly/fibers/FiberManagerInternal-inl.h b/folly/fibers/FiberManagerInternal-inl.h index 89b87f08..df354aaa 100644 --- a/folly/fibers/FiberManagerInternal-inl.h +++ b/folly/fibers/FiberManagerInternal-inl.h @@ -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_, diff --git a/folly/fibers/FiberManagerInternal.h b/folly/fibers/FiberManagerInternal.h index b58ab0ed..18ec7628 100644 --- a/folly/fibers/FiberManagerInternal.h +++ b/folly/fibers/FiberManagerInternal.h @@ -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