Switch Linux getrandom() usage to non-blocking mode, continuing to
authorbeck <beck@openbsd.org>
Sat, 29 Apr 2017 18:43:31 +0000 (18:43 +0000)
committerbeck <beck@openbsd.org>
Sat, 29 Apr 2017 18:43:31 +0000 (18:43 +0000)
use fallback mechanims if unsuccessful.

The design of Linux getrandom is broken.  It has an
uninitialized phase coupled with blocking behaviour, which
is unacceptable from within a library at boot time without
possible recovery.
ok deraadt@ jsing@

lib/libcrypto/arc4random/getentropy_linux.c

index ac97658..a845239 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: getentropy_linux.c,v 1.43 2016/08/07 03:27:21 tb Exp $        */
+/*     $OpenBSD: getentropy_linux.c,v 1.44 2017/04/29 18:43:31 beck Exp $      */
 
 /*
  * Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
@@ -96,13 +96,16 @@ getentropy(void *buf, size_t len)
 
 #ifdef SYS_getrandom
        /*
-        * Try descriptor-less getrandom()
+        * Try descriptor-less getrandom(), in non-blocking mode.
+        *
+        * The design of Linux getrandom is broken.  It has an
+        * uninitialized phase coupled with blocking behaviour, which
+        * is unacceptable from within a library at boot time without
+        * possible recovery. See http://bugs.python.org/issue26839#msg267745
         */
        ret = getentropy_getrandom(buf, len);
        if (ret != -1)
                return (ret);
-       if (errno != ENOSYS)
-               return (-1);
 #endif
 
        /*
@@ -156,7 +159,7 @@ getentropy(void *buf, size_t len)
         *     - Do the best under the circumstances....
         *
         * This code path exists to bring light to the issue that Linux
-        * does not provide a failsafe API for entropy collection.
+        * still does not provide a failsafe API for entropy collection.
         *
         * We hope this demonstrates that Linux should either retain their
         * sysctl ABI, or consider providing a new failsafe API which
@@ -199,7 +202,7 @@ getentropy_getrandom(void *buf, size_t len)
        if (len > 256)
                return (-1);
        do {
-               ret = syscall(SYS_getrandom, buf, len, 0);
+               ret = syscall(SYS_getrandom, buf, len, GRND_NONBLOCK);
        } while (ret == -1 && errno == EINTR);
 
        if (ret != len)