Index: gnutls-3.4.17/lib/nettle/rnd-common.c
===================================================================
--- gnutls-3.4.17.orig/lib/nettle/rnd-common.c
+++ gnutls-3.4.17/lib/nettle/rnd-common.c
@@ -37,11 +38,6 @@
 #include <rnd-common.h>
 #include <hash-pjw-bare.h>
 
-#if defined(HAVE_LINUX_GETRANDOM)
-# include <linux/random.h>
-# define getentropy(x, size) getrandom(x, size, 0)
-# define HAVE_GETENTROPY
-#endif
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -103,11 +99,6 @@ int _rnd_get_system_entropy_win32(void*
 
 get_entropy_func _rnd_get_system_entropy = _rnd_get_system_entropy_win32;
 
-int _rnd_system_entropy_check(void)
-{
-	return 0;
-}
-
 int _rnd_system_entropy_init(void)
 {
 	int old;
@@ -142,8 +133,6 @@ void _rnd_system_entropy_deinit(void)
 #include "egd.h"
 
 static int _gnutls_urandom_fd = -1;
-static mode_t _gnutls_urandom_fd_mode = 0;
-
 
 get_entropy_func _rnd_get_system_entropy = NULL;
 
@@ -166,27 +155,86 @@ int _rnd_system_entropy_init(void)
 	return 0;
 }
 
-int _rnd_system_entropy_check(void)
+void _rnd_system_entropy_deinit(void)
 {
+	return;
+}
+
+#else /* /dev/urandom - egd approach */
+
+#if defined(__linux)
+# ifdef HAVE_LINUX_GETRANDOM
+#  include <linux/random.h>
+# else
+#  include <sys/syscall.h>
+#  undef getrandom
+#  define getrandom(dst,s,flags) syscall(__NR_getrandom, (void*)dst, (size_t)s, (unsigned int)flags)
+# endif
+
+static unsigned have_getrandom(void)
+{
+	char c;
+	if (getrandom(&c, 1, 0) == 1)
+		return 1;
 	return 0;
 }
 
-void _rnd_system_entropy_deinit(void)
+/* returns exactly the amount of bytes requested */
+static int force_getrandom(void *buf, size_t buflen, unsigned int flags)
 {
-	return;
+	int left = buflen;
+	int ret;
+	uint8_t *p = buf;
+
+	while (left > 0) {
+		ret = getrandom(p, left, flags);
+		if (ret == -1) {
+			if (errno != EINTR)
+				return ret;
+		}
+
+		if (ret > 0) {
+			left -= ret;
+			p += ret;
+		}
+	}
+
+	return buflen;
 }
 
-#else /* /dev/urandom - egd approach */
+static int _rnd_get_system_entropy_getrandom(void* _rnd, size_t size)
+{
+	int ret;
+	ret = force_getrandom(_rnd, size, 0);
+	if (ret == -1) {
+		gnutls_assert();
+		_gnutls_debug_log
+			("Failed to use getrandom: %s\n",
+					 strerror(errno));
+		return GNUTLS_E_RANDOM_DEVICE_ERROR;
+	}
+	return 0;
+}
+#else
+# define have_getrandom() 0
+#endif
 
 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) {
@@ -199,12 +247,14 @@ static int _rnd_get_system_entropy_urand
 					("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;
 }
 
@@ -232,42 +282,37 @@ int _rnd_get_system_entropy_egd(void* _r
 
 	return 0;
 }
-
-int _rnd_system_entropy_check(void)
-{
-	int ret;
-	struct stat st;
-
-	ret = fstat(_gnutls_urandom_fd, &st);
-	if (ret < 0 || st.st_mode != _gnutls_urandom_fd_mode) {
-		return _rnd_system_entropy_init();
-	}
-	return 0;
-}
-
 int _rnd_system_entropy_init(void)
 {
-	int old;
-	struct stat st;
+	int urandom_fd;
 
-	_gnutls_urandom_fd = open("/dev/urandom", O_RDONLY);
-	if (_gnutls_urandom_fd < 0) {
-		_gnutls_debug_log("Cannot open urandom!\n");
-		goto fallback;
+#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 selected\n");
+		return 0;
+	} else {
+		_gnutls_debug_log("getrandom is not available\n");
 	}
+#endif
 
-	old = fcntl(_gnutls_urandom_fd, F_GETFD);
-	if (old != -1)
-		fcntl(_gnutls_urandom_fd, F_SETFD, old | FD_CLOEXEC);
+	/* Fallback: /dev/urandom */
 
-	if (fstat(_gnutls_urandom_fd, &st) >= 0) {
-		_gnutls_urandom_fd_mode = st.st_mode;
+	/* 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;
 fallback:
+	/* Third fallback: EGD */
 	_gnutls_urandom_fd = _rndegd_connect_socket();
 	if (_gnutls_urandom_fd < 0) {
 		_gnutls_debug_log("Cannot open egd socket!\n");
@@ -276,10 +321,7 @@ fallback:
 			(GNUTLS_E_RANDOM_DEVICE_ERROR);
 	}
 
-	if (fstat(_gnutls_urandom_fd, &st) >= 0) {
-		_gnutls_urandom_fd_mode = st.st_mode;
-	}
-
+	_gnutls_debug_log("EGD random generator was detected\n");
 	_rnd_get_system_entropy = _rnd_get_system_entropy_egd;
 	
 	return 0;
@@ -287,10 +329,8 @@ fallback:
 
 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;
 }
 #endif /* GETENTROPY */
 
Index: gnutls-3.4.17/lib/random.h
===================================================================
--- gnutls-3.4.17.orig/lib/random.h
+++ gnutls-3.4.17/lib/random.h
@@ -25,6 +25,7 @@
 
 #include <gnutls/crypto.h>
 #include <crypto-backend.h>
+#include "nettle/rnd-common.h"
 
 extern int crypto_rnd_prio;
 extern void *gnutls_rnd_ctx;
@@ -48,14 +49,6 @@ inline static void _gnutls_rnd_refresh(v
 void _gnutls_rnd_deinit(void);
 int _gnutls_rnd_init(void);
 
-inline static int _gnutls_rnd_check(void)
-{
-	if (_gnutls_rnd_ops.check)
-		return _gnutls_rnd_ops.check(gnutls_rnd_ctx);
-	else
-		return 0;
-}
-
 #ifndef _WIN32
 extern int _gnutls_urandom_fd;
 #endif
Index: gnutls-3.4.17/lib/nettle/rnd-common.h
===================================================================
--- gnutls-3.4.17.orig/lib/nettle/rnd-common.h
+++ gnutls-3.4.17/lib/nettle/rnd-common.h
@@ -46,7 +46,6 @@ struct event_st {
 void _rnd_get_event(struct event_st *e);
 
 int _rnd_system_entropy_init(void);
-int _rnd_system_entropy_check(void);
 void _rnd_system_entropy_deinit(void);
 
 typedef int (*get_entropy_func)(void* rnd, size_t size);
Index: gnutls-3.4.17/lib/crypto-backend.h
===================================================================
--- gnutls-3.4.17.orig/lib/crypto-backend.h
+++ gnutls-3.4.17/lib/crypto-backend.h
@@ -73,8 +73,7 @@ typedef struct {
 } gnutls_crypto_digest_st;
 
 typedef struct gnutls_crypto_rnd {
-	int (*init) (void **ctx);
-	int (*check) (void **ctx);
+	int (*init) (void **ctx); /* called prior to first usage of randomness */
 	int (*rnd) (void *ctx, int level, void *data, size_t datasize);
 	void (*rnd_refresh) (void *ctx);
 	void (*deinit) (void *ctx);
Index: gnutls-3.4.17/lib/gnutls_global.c
===================================================================
--- gnutls-3.4.17.orig/lib/gnutls_global.c
+++ gnutls-3.4.17/lib/gnutls_global.c
@@ -224,16 +224,6 @@ int gnutls_global_init(void)
 
 	_gnutls_init++;
 	if (_gnutls_init > 1) {
-		if (_gnutls_init == 2 && _gnutls_init_ret == 0) {
-			/* some applications may close the urandom fd 
-			 * before calling gnutls_global_init(). in that
-			 * case reopen it */
-			ret = _gnutls_rnd_check();
-			if (ret < 0) {
-				gnutls_assert();
-				goto out;
-			}
-		}
 		ret = _gnutls_init_ret;
 		goto out;
 	}
Index: gnutls-3.4.17/lib/nettle/rnd-fips.c
===================================================================
--- gnutls-3.4.17.orig/lib/nettle/rnd-fips.c
+++ gnutls-3.4.17/lib/nettle/rnd-fips.c
@@ -226,15 +226,6 @@ static void _rngfips_deinit(void *_ctx)
 	free(ctx);
 }
 
-/* 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 */
-static int _rndfips_check(void **ctx)
-{
-	return _rnd_system_entropy_check();
-}
-
 static void _rngfips_refresh(void *_ctx)
 {
 	/* this is predictable RNG. Don't refresh */
@@ -260,7 +251,6 @@ static int selftest_kat(void)
 
 gnutls_crypto_rnd_st _gnutls_fips_rnd_ops = {
 	.init = _rngfips_init,
-	.check = _rndfips_check,
 	.deinit = _rngfips_deinit,
 	.rnd = _rngfips_rnd,
 	.rnd_refresh = _rngfips_refresh,
Index: gnutls-3.4.17/lib/nettle/rnd.c
===================================================================
--- gnutls-3.4.17.orig/lib/nettle/rnd.c
+++ gnutls-3.4.17/lib/nettle/rnd.c
@@ -257,15 +257,6 @@ static int wrap_nettle_rnd_init(void **c
 	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 */
-static int wrap_nettle_rnd_check(void **ctx)
-{
-	return _rnd_system_entropy_check();
-}
-
 static int
 wrap_nettle_rnd_nonce(void *_ctx, void *data, size_t datasize)
 {
@@ -373,7 +364,6 @@ int crypto_rnd_prio = INT_MAX;
 
 gnutls_crypto_rnd_st _gnutls_rnd_ops = {
 	.init = wrap_nettle_rnd_init,
-	.check = wrap_nettle_rnd_check,
 	.deinit = wrap_nettle_rnd_deinit,
 	.rnd = wrap_nettle_rnd,
 	.rnd_refresh = wrap_nettle_rnd_refresh,
