]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- in compat/arc4random call getentropy_urandom when getentropy fails
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 29 May 2018 07:48:58 +0000 (07:48 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 29 May 2018 07:48:58 +0000 (07:48 +0000)
  with ENOSYS.

git-svn-id: file:///svn/unbound/trunk@4699 be551aaa-1e26-0410-a405-d3ace91eadb9

compat/arc4random.c
doc/Changelog

index a09665c5df224b5a7340a647c2197c4b70bf6565..28e8041d8e0c2f203b9dd207724a5b398b8e7ccf 100644 (file)
@@ -71,6 +71,70 @@ static struct {
 
 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 @@ _rs_stir(void)
        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)
index 1fe32cee6058e17c7773a2d845178017730be823..189e4f9fd2a15f5af696267a56cff3b3bc448a2c 100644 (file)
@@ -1,3 +1,7 @@
+29 May 2018: Wouter
+       - in compat/arc4random call getentropy_urandom when getentropy fails
+         with ENOSYS.
+
 28 May 2018: Wouter
        - Fix windows tcp and tls spin on events.
        - Add routine from getdns to add windows cert store to the SSL_CTX.