components/python/python35/patches/27-getrandom.patch
author John Beck <John.Beck@Oracle.COM>
Tue, 29 Sep 2015 14:11:08 -0700
changeset 4912 0b79e9575718
permissions -rw-r--r--
PSARC 2015/414 Python 3.5 21918688 Python 3.5

This patch comes from upstream: http://bugs.python.org/issue25003

--- a/configure	Fri Sep 11 12:38:27 2015 +0200
+++ b/configure	Fri Sep 11 13:06:42 2015 +0200
@@ -16180,11 +16180,11 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_
     #include <sys/syscall.h>
 
     int main() {
+        char buffer[1];
+        const size_t buflen = sizeof(buffer);
         const int flags = 0;
-        char buffer[1];
-        int n;
         /* ignore the result, Python checks for ENOSYS at runtime */
-        (void)syscall(SYS_getrandom, buffer, sizeof(buffer), flags);
+        (void)syscall(SYS_getrandom, buffer, buflen, flags);
         return 0;
     }
 
@@ -16206,6 +16206,43 @@ if test "$have_getrandom_syscall" = yes;
 
 fi
 
+# check if the getrandom() function is available
+# the test was written for the Solaris function of <sys/random.h>
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the getrandom() function" >&5
+$as_echo_n "checking for the getrandom() function... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+    #include <sys/random.h>
+
+    int main() {
+        char buffer[1];
+        const size_t buflen = sizeof(buffer);
+        const int flags = 0;
+        /* ignore the result, Python checks for ENOSYS at runtime */
+        (void)getrandom(buffer, buflen, flags);
+        return 0;
+    }
+
+
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  have_getrandom=yes
+else
+  have_getrandom=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_getrandom" >&5
+$as_echo "$have_getrandom" >&6; }
+
+if test "$have_getrandom" = yes; then
+
+$as_echo "#define HAVE_GETRANDOM 1" >>confdefs.h
+
+fi
+
 # generate output files
 ac_config_files="$ac_config_files Makefile.pre Modules/Setup.config Misc/python.pc Misc/python-config.sh"
 
--- a/configure.ac	Fri Sep 11 12:38:27 2015 +0200
+++ b/configure.ac	Fri Sep 11 13:06:42 2015 +0200
@@ -5161,11 +5161,11 @@ AC_LINK_IFELSE(
     #include <sys/syscall.h>
 
     int main() {
+        char buffer[1];
+        const size_t buflen = sizeof(buffer);
         const int flags = 0;
-        char buffer[1];
-        int n;
         /* ignore the result, Python checks for ENOSYS at runtime */
-        (void)syscall(SYS_getrandom, buffer, sizeof(buffer), flags);
+        (void)syscall(SYS_getrandom, buffer, buflen, flags);
         return 0;
     }
   ]])
@@ -5177,6 +5177,31 @@ if test "$have_getrandom_syscall" = yes;
               [Define to 1 if the Linux getrandom() syscall is available])
 fi
 
+# check if the getrandom() function is available
+# the test was written for the Solaris function of <sys/random.h>
+AC_MSG_CHECKING(for the getrandom() function)
+AC_LINK_IFELSE(
+[
+  AC_LANG_SOURCE([[
+    #include <sys/random.h>
+
+    int main() {
+        char buffer[1];
+        const size_t buflen = sizeof(buffer);
+        const int flags = 0;
+        /* ignore the result, Python checks for ENOSYS at runtime */
+        (void)getrandom(buffer, buflen, flags);
+        return 0;
+    }
+  ]])
+],[have_getrandom=yes],[have_getrandom=no])
+AC_MSG_RESULT($have_getrandom)
+
+if test "$have_getrandom" = yes; then
+    AC_DEFINE(HAVE_GETRANDOM, 1,
+              [Define to 1 if the getrandom() function is available])
+fi
+
 # generate output files
 AC_CONFIG_FILES(Makefile.pre Modules/Setup.config Misc/python.pc Misc/python-config.sh)
 AC_CONFIG_FILES([Modules/ld_so_aix], [chmod +x Modules/ld_so_aix])
--- Python-3.5.0/Lib/test/test_os.py.~1~	2015-09-13 04:41:23.000000000 -0700
+++ Python-3.5.0/Lib/test/test_os.py	2015-09-14 13:43:47.884863398 -0700
@@ -1213,13 +1213,17 @@
         self.assertNotEqual(data1, data2)
 
 
-HAVE_GETENTROPY = (sysconfig.get_config_var('HAVE_GETENTROPY') == 1)
-HAVE_GETRANDOM = (sysconfig.get_config_var('HAVE_GETRANDOM_SYSCALL') == 1)
+USE_GETENTROPY = ((sysconfig.get_config_var('HAVE_GETENTROPY') == 1)
+                  and not sys.platform.startswith("sunos"))
+HAVE_GETRANDOM = (sysconfig.get_config_var('HAVE_GETRANDOM') == 1)
+HAVE_GETRANDOM_SYSCALL = (sysconfig.get_config_var('HAVE_GETRANDOM_SYSCALL') == 1)
 
[email protected](HAVE_GETENTROPY,
[email protected](USE_GETENTROPY,
                  "getentropy() does not use a file descriptor")
 @unittest.skipIf(HAVE_GETRANDOM,
                  "getrandom() does not use a file descriptor")
[email protected](HAVE_GETRANDOM_SYSCALL,
+                 "getrandom() does not use a file descriptor")
 class URandomFDTests(unittest.TestCase):
     @unittest.skipUnless(resource, "test requires the resource module")
     def test_urandom_failure(self):
--- Python-3.5.0/Python/random.c.~2~	2015-09-14 14:11:43.377801246 -0700
+++ Python-3.5.0/Python/random.c	2015-09-14 14:19:35.124606276 -0700
@@ -6,11 +6,20 @@
 #  ifdef HAVE_SYS_STAT_H
 #    include <sys/stat.h>
 #  endif
-#  ifdef HAVE_GETRANDOM_SYSCALL
+#  ifdef HAVE_GETRANDOM
+#    include <sys/random.h>
+#  elif defined(HAVE_GETRANDOM_SYSCALL)
 #    include <sys/syscall.h>
 #  endif
 #endif
 
+/* Solaris 11.3 provides getrandom() and getentropy(). getentropy() cannot be
+   used for os.urandom() because it is blocking, it. Use
+   getrandom(GRND_NONBLOCK) instead, it is non-blocking. */
+#if defined(HAVE_GETENTROPY) && !defined(sun)
+#  define USE_GETENTROPY
+#endif
+
 #ifdef Py_DEBUG
 int _Py_HashSecret_Initialized = 0;
 #else
@@ -70,7 +79,7 @@
     return 0;
 }
 
-#elif HAVE_GETENTROPY
+#elif defined(USE_GETENTROPY)
 /* Fill buffer with size pseudo-random bytes generated by getentropy().
    Return 0 on success, or raise an exception and return -1 on error.
 
@@ -105,16 +114,19 @@
     return 0;
 }
 
-#else   /* !HAVE_GETENTROPY */
+#else   /* !USE_GETENTROPY */
+
+#if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
+#define PY_GETRANDOM
 
-#ifdef HAVE_GETRANDOM_SYSCALL
 static int
 py_getrandom(void *buffer, Py_ssize_t size, int raise)
 {
-    /* is getrandom() supported by the running kernel?
-     * need Linux kernel 3.17 or later */
+    /* Is getrandom() supported by the running kernel?
+     * Need Linux kernel 3.17 or newer, or Solaris 11.3 or newer */
     static int getrandom_works = 1;
-    /* Use /dev/urandom, block if the kernel has no entropy */
+    /* Use non-blocking /dev/urandom device. On Linux at boot, the getrandom()
+     * syscall blocks until /dev/urandom is initialized with enough entropy. */
     const int flags = 0;
     int n;
 
@@ -124,7 +136,18 @@
     while (0 < size) {
         errno = 0;
 
-        /* Use syscall() because the libc doesn't expose getrandom() yet, see:
+#ifdef HAVE_GETRANDOM
+        if (raise) {
+            Py_BEGIN_ALLOW_THREADS
+            n = getrandom(buffer, size, flags);
+            Py_END_ALLOW_THREADS
+        }
+        else {
+            n = getrandom(buffer, size, flags);
+        }
+#else
+        /* On Linux, use the syscall() function because the GNU libc doesn't
+         * expose the Linux getrandom() syscall yet. See:
          * https://sourceware.org/bugzilla/show_bug.cgi?id=17252 */
         if (raise) {
             Py_BEGIN_ALLOW_THREADS
@@ -134,6 +157,7 @@
         else {
             n = syscall(SYS_getrandom, buffer, size, flags);
         }
+#endif
 
         if (n < 0) {
             if (errno == ENOSYS || errno == EINVAL) {
@@ -182,7 +206,7 @@
 
     assert (0 < size);
 
-#ifdef HAVE_GETRANDOM_SYSCALL
+#ifdef PY_GETRANDOM
     if (py_getrandom(buffer, size, 0) == 1)
         return;
     /* getrandom() is not supported by the running kernel, fall back
@@ -218,14 +242,14 @@
     int fd;
     Py_ssize_t n;
     struct _Py_stat_struct st;
-#ifdef HAVE_GETRANDOM_SYSCALL
+#ifdef PY_GETRANDOM
     int res;
 #endif
 
     if (size <= 0)
         return 0;
 
-#ifdef HAVE_GETRANDOM_SYSCALL
+#ifdef PY_GETRANDOM
     res = py_getrandom(buffer, size, 1);
     if (res < 0)
         return -1;
@@ -304,7 +328,7 @@
     }
 }
 
-#endif /* HAVE_GETENTROPY */
+#endif
 
 /* Fill buffer with pseudo-random bytes generated by a linear congruent
    generator (LCG):
@@ -345,7 +369,7 @@
 
 #ifdef MS_WINDOWS
     return win32_urandom((unsigned char *)buffer, size, 1);
-#elif HAVE_GETENTROPY
+#elif defined(USE_GETENTROPY)
     return py_getentropy(buffer, size, 0);
 #else
     return dev_urandom_python((char*)buffer, size);
@@ -392,7 +416,7 @@
     else {
 #ifdef MS_WINDOWS
         (void)win32_urandom(secret, secret_size, 0);
-#elif HAVE_GETENTROPY
+#elif defined(USE_GETENTROPY)
         (void)py_getentropy(secret, secret_size, 1);
 #else
         dev_urandom_noraise(secret, secret_size);
@@ -408,7 +432,7 @@
         CryptReleaseContext(hCryptProv, 0);
         hCryptProv = 0;
     }
-#elif HAVE_GETENTROPY
+#elif defined(USE_GETENTROPY)
     /* nothing to clean */
 #else
     dev_urandom_close();
--- a/pyconfig.h.in	Fri Sep 11 12:38:27 2015 +0200
+++ b/pyconfig.h.in	Fri Sep 11 13:06:42 2015 +0200
@@ -395,6 +395,9 @@
 /* Define to 1 if you have the `getpwent' function. */
 #undef HAVE_GETPWENT
 
+/* Define to 1 if the getrandom() function is available */
+#undef HAVE_GETRANDOM
+
 /* Define to 1 if the Linux getrandom() syscall is available */
 #undef HAVE_GETRANDOM_SYSCALL