Hi Andreas,

On 29/05/18 09:07, A. Schulze via Unbound-users wrote:
> 
> 
> Am 28.05.2018 um 23:01 schrieb James Cloos via Unbound-users:
>>
>> I don't have the configure output; this is debian's compile
> I'll try to recompile the Debian package to catch configure output ...
> @James: which Debian Version?

Here is a patch you can use to fix the problem for him, it calls the
urandom fallback when ENOSYS is returns in _rs_stir().

Hopefully that will alleviate the problems.  The configure output that
would match this patch is one where getentropy is provided by the
system, not arc4random, and that getentropy then returns ENOSYS.

Best regards, Wouter

> 
> Andreas
> 

Index: compat/arc4random.c
===================================================================
--- compat/arc4random.c	(revision 4698)
+++ compat/arc4random.c	(working copy)
@@ -71,6 +71,70 @@
 
 static inline void _rs_rekey(u_char *dat, size_t datlen);
 
+/*
+ * Basic sanity checking; wish we could do better.
+ */
+static int
+fallback_gotdata(char *buf, size_t len)
+{
+	char	any_set = 0;
+	size_t	i;
+
+	for (i = 0; i < len; ++i)
+		any_set |= buf[i];
+	if (any_set == 0)
+		return -1;
+	return 0;
+}
+
+/* fallback for getentropy in case libc returns failure */
+static int
+fallback_getentropy_urandom(void *buf, size_t len)
+{
+	size_t i;
+	int fd, flags;
+	int save_errno = errno;
+
+start:
+
+	flags = O_RDONLY;
+#ifdef O_NOFOLLOW
+	flags |= O_NOFOLLOW;
+#endif
+#ifdef O_CLOEXEC
+	flags |= O_CLOEXEC;
+#endif
+	fd = open("/dev/urandom", flags, 0);
+	if (fd == -1) {
+		if (errno == EINTR)
+			goto start;
+		goto nodevrandom;
+	}
+#ifndef O_CLOEXEC
+	fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+#endif
+	for (i = 0; i < len; ) {
+		size_t wanted = len - i;
+		ssize_t ret = read(fd, (char*)buf + i, wanted);
+
+		if (ret == -1) {
+			if (errno == EAGAIN || errno == EINTR)
+				continue;
+			close(fd);
+			goto nodevrandom;
+		}
+		i += ret;
+	}
+	close(fd);
+	if (fallback_gotdata(buf, len) == 0) {
+		errno = save_errno;
+		return 0;		/* satisfied */
+	}
+nodevrandom:
+	errno = EIO;
+	return -1;
+}
+
 static inline void
 _rs_init(u_char *buf, size_t n)
 {
@@ -114,11 +178,14 @@
 	u_char rnd[KEYSZ + IVSZ];
 
 	if (getentropy(rnd, sizeof rnd) == -1) {
+		if(errno != ENOSYS ||
+			fallback_getentropy_urandom(rnd, sizeof rnd) == -1) {
 #ifdef SIGKILL
-		raise(SIGKILL);
+			raise(SIGKILL);
 #else
-		exit(9); /* windows */
+			exit(9); /* windows */
 #endif
+		}
 	}
 
 	if (!rs)

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to