Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
[security][CVE-2018-6337] Flush folly::secureRandom buffer on fork
D8109884 D8110240 CVE-2018-6337
- Loading branch information
1 parent
1ef6d97
commit e2d10a1
Showing
1 changed file
with
111 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| diff --git a/third-party/folly/src/folly/Random.cpp b/third-party/folly/src/folly/Random.cpp | ||
| index afb62f5d..40a6b17f 100644 | ||
| --- a/third-party/folly/src/folly/Random.cpp | ||
| +++ b/third-party/folly/src/folly/Random.cpp | ||
| @@ -72,6 +72,7 @@ void readRandomDevice(void* data, size_t size) { | ||
|
|
||
| class BufferedRandomDevice { | ||
| public: | ||
| + static once_flag flag; | ||
| static constexpr size_t kDefaultBufferSize = 128; | ||
|
|
||
| explicit BufferedRandomDevice(size_t bufferSize = kDefaultBufferSize); | ||
| @@ -97,10 +98,28 @@ class BufferedRandomDevice { | ||
| unsigned char* ptr_; | ||
| }; | ||
|
|
||
| +once_flag BufferedRandomDevice::flag; | ||
| +struct RandomTag {}; | ||
| + | ||
| BufferedRandomDevice::BufferedRandomDevice(size_t bufferSize) | ||
| : bufferSize_(bufferSize), | ||
| buffer_(new unsigned char[bufferSize]), | ||
| ptr_(buffer_.get() + bufferSize) { // refill on first use | ||
| + call_once(flag, [this]() { | ||
| + detail::AtFork::registerHandler( | ||
| + this, | ||
| + /*prepare*/ []() { return true; }, | ||
| + /*parent*/ []() {}, | ||
| + /*child*/ | ||
| + []() { | ||
| + using Single = SingletonThreadLocal<BufferedRandomDevice, RandomTag>; | ||
| + auto& t = Single::get(); | ||
| + // Clear out buffered data on fork. | ||
| + // | ||
| + // Ensure child and parent do not share same entropy pool. | ||
| + t.ptr_ = t.buffer_.get() + t.bufferSize_; | ||
| + }); | ||
| + }); | ||
| } | ||
|
|
||
| void BufferedRandomDevice::getSlow(unsigned char* data, size_t size) { | ||
| @@ -124,8 +143,6 @@ void BufferedRandomDevice::getSlow(unsigned char* data, size_t size) { | ||
| ptr_ += size; | ||
| } | ||
|
|
||
| -struct RandomTag {}; | ||
| - | ||
| } // namespace | ||
|
|
||
| void Random::secureRandom(void* data, size_t size) { | ||
| diff --git a/third-party/folly/src/folly/detail/AtFork.cpp b/third-party/folly/src/folly/detail/AtFork.cpp | ||
| index 48c42fd3..12a6f934 100644 | ||
| --- a/third-party/folly/src/folly/detail/AtFork.cpp | ||
| +++ b/third-party/folly/src/folly/detail/AtFork.cpp | ||
| @@ -13,12 +13,14 @@ | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| + | ||
| #include <folly/detail/AtFork.h> | ||
|
|
||
| #include <list> | ||
| #include <mutex> | ||
|
|
||
| -#include <folly/Exception.h> | ||
| +#include <folly/lang/Exception.h> | ||
| +#include <folly/portability/PThread.h> | ||
|
|
||
| namespace folly { | ||
|
|
||
| @@ -72,7 +74,10 @@ class AtForkList { | ||
| #if FOLLY_HAVE_PTHREAD_ATFORK | ||
| int ret = pthread_atfork( | ||
| &AtForkList::prepare, &AtForkList::parent, &AtForkList::child); | ||
| - checkPosixError(ret, "pthread_atfork failed"); | ||
| + if (ret != 0) { | ||
| + throw_exception<std::system_error>( | ||
| + ret, std::generic_category(), "pthread_atfork failed"); | ||
| + } | ||
| #elif !__ANDROID__ && !defined(_MSC_VER) | ||
| // pthread_atfork is not part of the Android NDK at least as of n9d. If | ||
| // something is trying to call native fork() directly at all with Android's | ||
| diff --git a/third-party/folly/src/folly/test/RandomTest.cpp b/third-party/folly/src/folly/test/RandomTest.cpp | ||
| index 9c33159b..2ee74c6d 100644 | ||
| --- a/third-party/folly/src/folly/test/RandomTest.cpp | ||
| +++ b/third-party/folly/src/folly/test/RandomTest.cpp | ||
| @@ -138,3 +138,24 @@ TEST(Random, sanity) { | ||
| std::unordered_set<uint64_t>(vals.begin(), vals.end()).size()); | ||
| } | ||
| } | ||
| + | ||
| +TEST(Random, SecureFork) { | ||
| + unsigned char buffer = 0; | ||
| + // Init random buffer | ||
| + folly::Random::secureRandom(&buffer, 1); | ||
| + | ||
| + auto pid = fork(); | ||
| + EXPECT_NE(pid, -1); | ||
| + if (pid) { | ||
| + // parent | ||
| + int status = 0; | ||
| + folly::Random::secureRandom(&buffer, 1); | ||
| + auto pid2 = wait(&status); | ||
| + EXPECT_NE(WEXITSTATUS(status), buffer); | ||
| + EXPECT_EQ(pid, pid2); | ||
| + } else { | ||
| + // child | ||
| + folly::Random::secureRandom(&buffer, 1); | ||
| + exit(buffer); // Do not print gtest results | ||
| + } | ||
| +} |