Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cassconfig.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@
#cmakedefine HAVE_BOOST_ATOMIC
#cmakedefine HAVE_NOSIGPIPE
#cmakedefine HAVE_SIGTIMEDWAIT
#cmakedefine HAVE_ARC4RANDOM
#cmakedefine HAVE_GETRANDOM

#endif
5 changes: 5 additions & 0 deletions cmake/modules/CppDriver.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
71 changes: 49 additions & 22 deletions src/random.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include "random.hpp"

#include "cassconfig.hpp"
#include "cassandra.h"
#include "logger.hpp"
#include "scoped_lock.hpp"
Expand All @@ -27,9 +28,14 @@
#include <Windows.h>
#include <WinCrypt.h>
#else
#if defined(HAVE_GETRANDOM)
#include <syscall.h>
#include <linux/random.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/uio.h>
Expand Down Expand Up @@ -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<ssize_t>(syscall(SYS_getrandom, &seed,
sizeof(seed), GRND_NONBLOCK));
if (num_bytes < static_cast<ssize_t>(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<unsigned int>(sizeof(seed)), err,
static_cast<unsigned int>(num_bytes));
} else {
readurandom = false;
}

ssize_t num_bytes = read(fd, reinterpret_cast<char*>(&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<unsigned int>(sizeof(seed)),
static_cast<unsigned int>(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<char*>(&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<unsigned int>(sizeof(seed)),
static_cast<unsigned int>(num_bytes),
device, err);
}

close(fd);
}

close(fd);
#endif // defined(HAVE_ARC4RANDOM)

return seed;
}
Expand Down