Commit 6fc7dd10 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Use getrandom instead of /dev/urandom when available

Summary:
[Folly] Use `getrandom` instead of `/dev/urandom` when available.

The C library function `getrandom` is available on linux >= 3.17 and glibc >= 2.25.

Reviewed By: ot, simpkins, luciang

Differential Revision: D19211519

fbshipit-source-id: 07e7e856fc81d1f04efca4a6cfa0b76ada08f443
parent 44e0aff1
......@@ -89,6 +89,7 @@ check_symbol_exists(pthread_atfork pthread.h FOLLY_HAVE_PTHREAD_ATFORK)
# it fails complaining that there are multiple overloaded versions of memrchr()
check_function_exists(memrchr FOLLY_HAVE_MEMRCHR)
check_symbol_exists(accept4 sys/socket.h FOLLY_HAVE_ACCEPT4)
check_symbol_exists(getrandom sys/random.h FOLLY_HAVE_GETRANDOM)
check_symbol_exists(preadv sys/uio.h FOLLY_HAVE_PREADV)
check_symbol_exists(pwritev sys/uio.h FOLLY_HAVE_PWRITEV)
check_symbol_exists(clock_gettime time.h FOLLY_HAVE_CLOCK_GETTIME)
......
......@@ -44,6 +44,7 @@
#cmakedefine FOLLY_HAVE_MEMRCHR 1
#cmakedefine FOLLY_HAVE_ACCEPT4 1
#cmakedefine01 FOLLY_HAVE_GETRANDOM
#cmakedefine FOLLY_HAVE_PREADV 1
#cmakedefine FOLLY_HAVE_PWRITEV 1
#cmakedefine FOLLY_HAVE_CLOCK_GETTIME 1
......
......@@ -26,6 +26,8 @@
#include <folly/FileUtil.h>
#include <folly/SingletonThreadLocal.h>
#include <folly/ThreadLocal.h>
#include <folly/detail/FileUtilDetail.h>
#include <folly/portability/Config.h>
#include <folly/portability/SysTime.h>
#include <folly/portability/Unistd.h>
#include <glog/logging.h>
......@@ -34,6 +36,10 @@
#include <wincrypt.h> // @manual
#endif
#if FOLLY_HAVE_GETRANDOM
#include <sys/random.h>
#endif
namespace folly {
namespace {
......@@ -58,10 +64,24 @@ void readRandomDevice(void* data, size_t size) {
CHECK(size <= std::numeric_limits<DWORD>::max());
PCHECK(CryptGenRandom(cryptoProv, (DWORD)size, (BYTE*)data));
#else
// Keep the random device open for the duration of the program.
static int randomFd = ::open("/dev/urandom", O_RDONLY | O_CLOEXEC);
PCHECK(randomFd >= 0);
auto bytesRead = readFull(randomFd, data, size);
ssize_t bytesRead = 0;
auto gen = [](int, void* buf, size_t buflen) {
#if FOLLY_HAVE_GETRANDOM
auto flags = 0u;
return ::getrandom(buf, buflen, flags);
#else
[](...) {}(buf, buflen);
errno = ENOSYS;
return -1;
#endif
};
bytesRead = fileutil_detail::wrapFull(gen, -1, data, size);
if (bytesRead == -1 && errno == ENOSYS) {
// Keep the random device open for the duration of the program.
static int randomFd = ::open("/dev/urandom", O_RDONLY | O_CLOEXEC);
PCHECK(randomFd >= 0);
bytesRead = readFull(randomFd, data, size);
}
PCHECK(bytesRead >= 0);
CHECK_EQ(size_t(bytesRead), size);
#endif
......
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