diff --git a/cassconfig.hpp.in b/cassconfig.hpp.in index b931b9ed8..9ddf22a32 100644 --- a/cassconfig.hpp.in +++ b/cassconfig.hpp.in @@ -6,5 +6,7 @@ #cmakedefine HAVE_BOOST_ATOMIC #cmakedefine HAVE_NOSIGPIPE #cmakedefine HAVE_SIGTIMEDWAIT +#cmakedefine HAVE_ARC4RANDOM +#cmakedefine HAVE_GETRANDOM #endif diff --git a/cmake/modules/CppDriver.cmake b/cmake/modules/CppDriver.cmake index 1ad77f665..0fa727a89 100644 --- a/cmake/modules/CppDriver.cmake +++ b/cmake/modules/CppDriver.cmake @@ -511,6 +511,11 @@ macro(CassFindSourceFiles) endmacro() macro(CassConfigure) + if(CMAKE_SYSTEM_NAME MATCHES "Linux") + check_symbol_exists(GRND_NONBLOCK "linux/random.h" HAVE_GETRANDOM) + else() + check_symbol_exists(arc4random_buf "stdlib.h" HAVE_ARC4RANDOM) + endif() check_symbol_exists(SO_NOSIGPIPE "sys/socket.h;sys/types.h" HAVE_NOSIGPIPE) check_symbol_exists(sigtimedwait "signal.h" HAVE_SIGTIMEDWAIT) if (NOT WIN32 AND NOT HAVE_NOSIGPIPE AND NOT HAVE_SIGTIMEDWAIT) diff --git a/src/random.cpp b/src/random.cpp index a22019bdf..4723505d5 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -16,6 +16,7 @@ #include "random.hpp" +#include "cassconfig.hpp" #include "cassandra.h" #include "logger.hpp" #include "scoped_lock.hpp" @@ -27,9 +28,14 @@ #include #include #else +#if defined(HAVE_GETRANDOM) +#include +#include +#endif #include #include #include +#include #include #include #include @@ -84,33 +90,54 @@ uint64_t Random::next(uint64_t max) { #endif uint64_t get_random_seed(uint64_t seed) { +#if defined(HAVE_ARC4RANDOM) + arc4random_buf(&seed, sizeof(seed)); +#else static const char* device = "/dev/urandom"; - - int fd = open(device, O_RDONLY); - - if (fd < 0) { + ssize_t num_bytes; + bool readurandom = true; +#if defined(HAVE_GETRANDOM) + num_bytes = static_cast(syscall(SYS_getrandom, &seed, + sizeof(seed), GRND_NONBLOCK)); + if (num_bytes < static_cast(sizeof(seed))) { char buf[STRERROR_BUFSIZE_]; char* err = STRERROR_R_(errno, buf, sizeof(buf)); - LOG_CRITICAL("Unable to open random device (%s): %s", device, err); - return seed; + LOG_WARN("Unable to read %u random bytes (%s): %u read", + static_cast(sizeof(seed)), err, + static_cast(num_bytes)); + } else { + readurandom = false; } - - ssize_t num_bytes = read(fd, reinterpret_cast(&seed), sizeof(seed)); - if (num_bytes < 0) { - char buf[STRERROR_BUFSIZE_]; - char* err = STRERROR_R_(errno, buf, sizeof(buf)); - LOG_CRITICAL("Unable to read from random device (%s): %s", device, err); - } else if (num_bytes != sizeof(seed)) { - char buf[STRERROR_BUFSIZE_]; - char* err = STRERROR_R_(errno, buf, sizeof(buf)); - LOG_CRITICAL("Unable to read full seed value (expected: %u read: %u) " - "from random device (%s): %s", - static_cast(sizeof(seed)), - static_cast(num_bytes), - device, err); +#endif // defined(HAVE_GETRANDOM) + + if (readurandom) { + int fd = open(device, O_RDONLY); + + if (fd < 0) { + char buf[STRERROR_BUFSIZE_]; + char* err = STRERROR_R_(errno, buf, sizeof(buf)); + LOG_CRITICAL("Unable to open random device (%s): %s", device, err); + return seed; + } + + num_bytes = read(fd, reinterpret_cast(&seed), sizeof(seed)); + if (num_bytes < 0) { + char buf[STRERROR_BUFSIZE_]; + char* err = STRERROR_R_(errno, buf, sizeof(buf)); + LOG_CRITICAL("Unable to read from random device (%s): %s", device, err); + } else if (num_bytes != sizeof(seed)) { + char buf[STRERROR_BUFSIZE_]; + char* err = STRERROR_R_(errno, buf, sizeof(buf)); + LOG_CRITICAL("Unable to read full seed value (expected: %u read: %u) " + "from random device (%s): %s", + static_cast(sizeof(seed)), + static_cast(num_bytes), + device, err); + } + + close(fd); } - - close(fd); +#endif // defined(HAVE_ARC4RANDOM) return seed; }