From: Alexander Sosedkin Date: Thu, 4 Mar 2021 09:54:44 +0000 (+0100) Subject: sysrng-linux: re-open /dev/urandom every time X-Git-Tag: 3.7.2~36^2~2 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=b20bd42bc2f07b58f912c8899f7eb5bf2340fc4d;p=thirdparty%2Fgnutls.git sysrng-linux: re-open /dev/urandom every time Prompted by the following comment of Daiki Ueno: > I also wonder why we keep the fd open for such a long time in the first > place. Both OpenSSL and NSS have a similar fallback to /dev/urandom > if getrandom is not available, but opens the device in one-shot, > when reseeding is needed (and that's pretty rare). https://gitlab.com/gnutls/gnutls/-/merge_requests/1383#note_521749519 Signed-off-by: Alexander Sosedkin --- diff --git a/lib/nettle/sysrng-linux.c b/lib/nettle/sysrng-linux.c index 2e17ecdd0c..62024b121f 100644 --- a/lib/nettle/sysrng-linux.c +++ b/lib/nettle/sysrng-linux.c @@ -46,10 +46,6 @@ #include #include -static int _gnutls_urandom_fd = -1; -static ino_t _gnutls_urandom_fd_ino = 0; -static dev_t _gnutls_urandom_fd_rdev = 0; - get_entropy_func _rnd_get_system_entropy = NULL; #if defined(__linux__) @@ -127,11 +123,18 @@ static int _rnd_get_system_entropy_urandom(void* _rnd, size_t size) { uint8_t* rnd = _rnd; uint32_t done; + int urandom_fd; + + urandom_fd = open("/dev/urandom", O_RDONLY); + if (urandom_fd < 0) { + _gnutls_debug_log("Cannot open /dev/urandom!\n"); + return GNUTLS_E_RANDOM_DEVICE_ERROR; + } for (done = 0; done < size;) { int res; do { - res = read(_gnutls_urandom_fd, rnd + done, size - done); + res = read(urandom_fd, rnd + done, size - done); } while (res < 0 && errno == EINTR); if (res <= 0) { @@ -145,74 +148,57 @@ static int _rnd_get_system_entropy_urandom(void* _rnd, size_t size) ("Failed to read /dev/urandom: end of file\n"); } + close(urandom_fd); return GNUTLS_E_RANDOM_DEVICE_ERROR; } done += res; } + close(urandom_fd); return 0; } -/* This is called when gnutls_global_init() is called for second time. - * It must check whether any resources are still available. - * The particular problem it solves is to verify that the urandom fd is still - * open (for applications that for some reason closed all fds */ int _rnd_system_entropy_check(void) { - int ret; - struct stat st; - - if (_gnutls_urandom_fd == -1) /* not using urandom */ - return 0; - - ret = fstat(_gnutls_urandom_fd, &st); - if (ret < 0 || st.st_ino != _gnutls_urandom_fd_ino || st.st_rdev != _gnutls_urandom_fd_rdev) { - return _rnd_system_entropy_init(); - } + /* A no-op now when we open and close /dev/urandom every time */ return 0; } int _rnd_system_entropy_init(void) { - int old; - struct stat st; + int urandom_fd; #if defined(__linux__) /* Enable getrandom() usage if available */ if (have_getrandom()) { _rnd_get_system_entropy = _rnd_get_system_entropy_getrandom; - _gnutls_debug_log("getrandom random generator was detected\n"); + _gnutls_debug_log("getrandom random generator was selected\n"); return 0; + } else { + _gnutls_debug_log("getrandom is not available\n"); } #endif - /* First fallback: /dev/unrandom */ - _gnutls_urandom_fd = open("/dev/urandom", O_RDONLY); - if (_gnutls_urandom_fd < 0) { - _gnutls_debug_log("Cannot open urandom!\n"); - return gnutls_assert_val(GNUTLS_E_RANDOM_DEVICE_ERROR); - } + /* Fallback: /dev/urandom */ - old = fcntl(_gnutls_urandom_fd, F_GETFD); - if (old != -1) - fcntl(_gnutls_urandom_fd, F_SETFD, old | FD_CLOEXEC); - - if (fstat(_gnutls_urandom_fd, &st) >= 0) { - _gnutls_urandom_fd_ino = st.st_ino; - _gnutls_urandom_fd_rdev = st.st_rdev; + /* Check that we can open it */ + urandom_fd = open("/dev/urandom", O_RDONLY); + if (urandom_fd < 0) { + _gnutls_debug_log("Cannot open /dev/urandom during initialization!\n"); + return gnutls_assert_val(GNUTLS_E_RANDOM_DEVICE_ERROR); } + close(urandom_fd); _rnd_get_system_entropy = _rnd_get_system_entropy_urandom; + _gnutls_debug_log("/dev/urandom random generator was selected\n"); return 0; } void _rnd_system_entropy_deinit(void) { - if (_gnutls_urandom_fd >= 0) { - close(_gnutls_urandom_fd); - _gnutls_urandom_fd = -1; - } + /* A no-op now when we open and close /dev/urandom every time */ + return; }