From 41af44eba113c59dc43764d1d240397616e85b82 Mon Sep 17 00:00:00 2001 From: Felipe Franciosi Date: Fri, 5 Oct 2018 15:09:07 +0100 Subject: [PATCH] iscsi_create_context: call srand() only once iscsi_create_context() calls srand() every time a new context is generated. That practice is questionable, as the seed does not need to change before each call to rand(). As a matter of fact, doing so defeats the purpose of using rand() altogether. Furthermore, the current implementation is not thread safe. This improves ISID generation by using /dev/urandom (when available) as a seed, and calling srand() only once. In case of errors, fallback to using something similar to the previous implementation (albeit thread-safe). Signed-off-by: Felipe Franciosi --- lib/init.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/lib/init.c b/lib/init.c index 0c8dc7b..34b88e6 100644 --- a/lib/init.c +++ b/lib/init.c @@ -28,6 +28,8 @@ #include #endif +#include +#include #include #include #include @@ -148,12 +150,58 @@ void iscsi_sfree(struct iscsi_context *iscsi, void* ptr) { } } +static bool rd_set = false; +static pthread_mutex_t rd_mutex = PTHREAD_MUTEX_INITIALIZER; + +static void +iscsi_srand_init(struct iscsi_context *iscsi) { + unsigned int seed; + int urand_fd; + ssize_t rc; + int err; + + if (rd_set) { + /* fast case, seed has been set */ + return; + } + + err = pthread_mutex_lock(&rd_mutex); + assert(err == 0); + + if (rd_set) { + /* another thread initialized it in the meantime */ + goto out; + } + + urand_fd = open("/dev/urandom", O_RDONLY); + if (urand_fd == -1) { + goto fallback; + } + + rc = read(urand_fd, &seed, sizeof(seed)); + close(urand_fd); + if (rc == -1) { + goto fallback; + } + + srand(seed); + goto out; + +fallback: + /* seed based on @iscsi */ + srand(getpid() ^ (uint32_t)((uintptr_t) iscsi)); + +out: + rd_set = true; + err = pthread_mutex_unlock(&rd_mutex); + assert(err == 0); +} + struct iscsi_context * iscsi_create_context(const char *initiator_name) { struct iscsi_context *iscsi; size_t required = ISCSI_RAW_HEADER_SIZE + ISCSI_DIGEST_SIZE; - static uint32_t ctx_seq = 0; char *ca; if (!initiator_name[0]) { @@ -177,9 +225,8 @@ iscsi_create_context(const char *initiator_name) iscsi->fd = -1; - srand(time(NULL) ^ getpid() ^ (uint32_t) ((uintptr_t) iscsi) ^ ctx_seq++); - /* initialize to a "random" isid */ + iscsi_srand_init(iscsi); iscsi_set_isid_random(iscsi, rand(), 0); /* assume we start in security negotiation phase */