Permalink
Browse files

[security][CVE-2018-6337] Flush folly::secureRandom buffer on fork

D8109884 D8110240

CVE-2018-6337
  • Loading branch information...
fredemmott committed May 24, 2018
1 parent 1ef6d97 commit e2d10a1e32d01f71aaadd81169bcb9ae86c5d6b8
Showing with 111 additions and 0 deletions.
  1. +111 −0 patches/folly-CVE-2018-6337.patch
@@ -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
+ }
+}

0 comments on commit e2d10a1

Please sign in to comment.