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