Core and Builtins
-----------------
+- Issue #25003: On Solaris 11.3 or newer, os.urandom() now uses the
+ getrandom() function instead of the getentropy() function. The getentropy()
+ function is blocking to generate very good quality entropy, os.urandom()
+ doesn't need such high-quality entropy.
+
- Issue #9232: Modify Python's grammar to allow trailing commas in the
argument list of a function declaration. For example, "def f(*, a =
3,): pass" is now legal. Patch from Mark Dickinson.
# 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
return 0;
}
-#elif HAVE_GETENTROPY
+#elif defined(HAVE_GETENTROPY) && !defined(sun)
+#define PY_GETENTROPY
+
/* Fill buffer with size pseudo-random bytes generated by getentropy().
Return 0 on success, or raise an exception and return -1 on error.
return 0;
}
-#else /* !HAVE_GETENTROPY */
+#else
+
+#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;
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
else {
n = syscall(SYS_getrandom, buffer, size, flags);
}
+#endif
if (n < 0) {
if (errno == ENOSYS) {
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
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;
}
}
-#endif /* HAVE_GETENTROPY */
+#endif
/* Fill buffer with pseudo-random bytes generated by a linear congruent
generator (LCG):
#ifdef MS_WINDOWS
return win32_urandom((unsigned char *)buffer, size, 1);
-#elif HAVE_GETENTROPY
+#elif PY_GETENTROPY
return py_getentropy(buffer, size, 0);
#else
return dev_urandom_python((char*)buffer, size);
else {
#ifdef MS_WINDOWS
(void)win32_urandom(secret, secret_size, 0);
-#elif HAVE_GETENTROPY
+#elif PY_GETENTROPY
(void)py_getentropy(secret, secret_size, 1);
#else
dev_urandom_noraise(secret, secret_size);
CryptReleaseContext(hCryptProv, 0);
hCryptProv = 0;
}
-#elif HAVE_GETENTROPY
+#elif PY_GETENTROPY
/* nothing to clean */
#else
dev_urandom_close();
#include <sys/syscall.h>
int main() {
- const int flags = 0;
char buffer[1];
- int n;
+ const size_t buflen = sizeof(buffer);
+ const int flags = 0;
/* 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;
}
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"
#include <sys/syscall.h>
int main() {
- const int flags = 0;
char buffer[1];
- int n;
+ const size_t buflen = sizeof(buffer);
+ const int flags = 0;
/* 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;
}
]])
[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])
/* 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