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.
This commit is contained in:
parent
258f17c96d
commit
3abf44e48f
|
@ -10,6 +10,11 @@ Release date: XXXX-XX-XX
|
||||||
Core and Builtins
|
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
|
- Issue #9232: Modify Python's grammar to allow trailing commas in the
|
||||||
argument list of a function declaration. For example, "def f(*, a =
|
argument list of a function declaration. For example, "def f(*, a =
|
||||||
3,): pass" is now legal. Patch from Mark Dickinson.
|
3,): pass" is now legal. Patch from Mark Dickinson.
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
# ifdef HAVE_SYS_STAT_H
|
# ifdef HAVE_SYS_STAT_H
|
||||||
# include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
# endif
|
# endif
|
||||||
# ifdef HAVE_GETRANDOM_SYSCALL
|
# ifdef HAVE_GETRANDOM
|
||||||
|
# include <sys/random.h>
|
||||||
|
# elif defined(HAVE_GETRANDOM_SYSCALL)
|
||||||
# include <sys/syscall.h>
|
# include <sys/syscall.h>
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
@ -70,7 +72,9 @@ win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif HAVE_GETENTROPY
|
#elif defined(HAVE_GETENTROPY) && !defined(sun)
|
||||||
|
#define PY_GETENTROPY
|
||||||
|
|
||||||
/* Fill buffer with size pseudo-random bytes generated by 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 on success, or raise an exception and return -1 on error.
|
||||||
|
|
||||||
|
@ -105,16 +109,19 @@ py_getentropy(unsigned char *buffer, Py_ssize_t size, int fatal)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* !HAVE_GETENTROPY */
|
#else
|
||||||
|
|
||||||
|
#if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
|
||||||
|
#define PY_GETRANDOM
|
||||||
|
|
||||||
#ifdef HAVE_GETRANDOM_SYSCALL
|
|
||||||
static int
|
static int
|
||||||
py_getrandom(void *buffer, Py_ssize_t size, int raise)
|
py_getrandom(void *buffer, Py_ssize_t size, int raise)
|
||||||
{
|
{
|
||||||
/* is getrandom() supported by the running kernel?
|
/* Is getrandom() supported by the running kernel?
|
||||||
* need Linux kernel 3.17 or later */
|
* Need Linux kernel 3.17 or newer, or Solaris 11.3 or newer */
|
||||||
static int getrandom_works = 1;
|
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;
|
const int flags = 0;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
|
@ -124,7 +131,18 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise)
|
||||||
while (0 < size) {
|
while (0 < size) {
|
||||||
errno = 0;
|
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 */
|
* https://sourceware.org/bugzilla/show_bug.cgi?id=17252 */
|
||||||
if (raise) {
|
if (raise) {
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
|
@ -134,6 +152,7 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise)
|
||||||
else {
|
else {
|
||||||
n = syscall(SYS_getrandom, buffer, size, flags);
|
n = syscall(SYS_getrandom, buffer, size, flags);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
if (errno == ENOSYS) {
|
if (errno == ENOSYS) {
|
||||||
|
@ -182,7 +201,7 @@ dev_urandom_noraise(unsigned char *buffer, Py_ssize_t size)
|
||||||
|
|
||||||
assert (0 < size);
|
assert (0 < size);
|
||||||
|
|
||||||
#ifdef HAVE_GETRANDOM_SYSCALL
|
#ifdef PY_GETRANDOM
|
||||||
if (py_getrandom(buffer, size, 0) == 1)
|
if (py_getrandom(buffer, size, 0) == 1)
|
||||||
return;
|
return;
|
||||||
/* getrandom() is not supported by the running kernel, fall back
|
/* getrandom() is not supported by the running kernel, fall back
|
||||||
|
@ -218,14 +237,14 @@ dev_urandom_python(char *buffer, Py_ssize_t size)
|
||||||
int fd;
|
int fd;
|
||||||
Py_ssize_t n;
|
Py_ssize_t n;
|
||||||
struct _Py_stat_struct st;
|
struct _Py_stat_struct st;
|
||||||
#ifdef HAVE_GETRANDOM_SYSCALL
|
#ifdef PY_GETRANDOM
|
||||||
int res;
|
int res;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (size <= 0)
|
if (size <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#ifdef HAVE_GETRANDOM_SYSCALL
|
#ifdef PY_GETRANDOM
|
||||||
res = py_getrandom(buffer, size, 1);
|
res = py_getrandom(buffer, size, 1);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -304,7 +323,7 @@ dev_urandom_close(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HAVE_GETENTROPY */
|
#endif
|
||||||
|
|
||||||
/* Fill buffer with pseudo-random bytes generated by a linear congruent
|
/* Fill buffer with pseudo-random bytes generated by a linear congruent
|
||||||
generator (LCG):
|
generator (LCG):
|
||||||
|
@ -345,7 +364,7 @@ _PyOS_URandom(void *buffer, Py_ssize_t size)
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
return win32_urandom((unsigned char *)buffer, size, 1);
|
return win32_urandom((unsigned char *)buffer, size, 1);
|
||||||
#elif HAVE_GETENTROPY
|
#elif PY_GETENTROPY
|
||||||
return py_getentropy(buffer, size, 0);
|
return py_getentropy(buffer, size, 0);
|
||||||
#else
|
#else
|
||||||
return dev_urandom_python((char*)buffer, size);
|
return dev_urandom_python((char*)buffer, size);
|
||||||
|
@ -392,7 +411,7 @@ _PyRandom_Init(void)
|
||||||
else {
|
else {
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
(void)win32_urandom(secret, secret_size, 0);
|
(void)win32_urandom(secret, secret_size, 0);
|
||||||
#elif HAVE_GETENTROPY
|
#elif PY_GETENTROPY
|
||||||
(void)py_getentropy(secret, secret_size, 1);
|
(void)py_getentropy(secret, secret_size, 1);
|
||||||
#else
|
#else
|
||||||
dev_urandom_noraise(secret, secret_size);
|
dev_urandom_noraise(secret, secret_size);
|
||||||
|
@ -408,7 +427,7 @@ _PyRandom_Fini(void)
|
||||||
CryptReleaseContext(hCryptProv, 0);
|
CryptReleaseContext(hCryptProv, 0);
|
||||||
hCryptProv = 0;
|
hCryptProv = 0;
|
||||||
}
|
}
|
||||||
#elif HAVE_GETENTROPY
|
#elif PY_GETENTROPY
|
||||||
/* nothing to clean */
|
/* nothing to clean */
|
||||||
#else
|
#else
|
||||||
dev_urandom_close();
|
dev_urandom_close();
|
||||||
|
|
|
@ -16005,11 +16005,11 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
const int flags = 0;
|
|
||||||
char buffer[1];
|
char buffer[1];
|
||||||
int n;
|
const size_t buflen = sizeof(buffer);
|
||||||
|
const int flags = 0;
|
||||||
/* ignore the result, Python checks for ENOSYS at runtime */
|
/* 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16031,6 +16031,43 @@ $as_echo "#define HAVE_GETRANDOM_SYSCALL 1" >>confdefs.h
|
||||||
|
|
||||||
fi
|
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
|
# generate output files
|
||||||
ac_config_files="$ac_config_files Makefile.pre Modules/Setup.config Misc/python.pc Misc/python-config.sh"
|
ac_config_files="$ac_config_files Makefile.pre Modules/Setup.config Misc/python.pc Misc/python-config.sh"
|
||||||
|
|
||||||
|
|
31
configure.ac
31
configure.ac
|
@ -5111,11 +5111,11 @@ AC_LINK_IFELSE(
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
const int flags = 0;
|
|
||||||
char buffer[1];
|
char buffer[1];
|
||||||
int n;
|
const size_t buflen = sizeof(buffer);
|
||||||
|
const int flags = 0;
|
||||||
/* ignore the result, Python checks for ENOSYS at runtime */
|
/* 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;
|
return 0;
|
||||||
}
|
}
|
||||||
]])
|
]])
|
||||||
|
@ -5127,6 +5127,31 @@ if test "$have_getrandom_syscall" = yes; then
|
||||||
[Define to 1 if the Linux getrandom() syscall is available])
|
[Define to 1 if the Linux getrandom() syscall is available])
|
||||||
fi
|
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
|
# generate output files
|
||||||
AC_CONFIG_FILES(Makefile.pre Modules/Setup.config Misc/python.pc Misc/python-config.sh)
|
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])
|
AC_CONFIG_FILES([Modules/ld_so_aix], [chmod +x Modules/ld_so_aix])
|
||||||
|
|
|
@ -395,6 +395,9 @@
|
||||||
/* Define to 1 if you have the `getpwent' function. */
|
/* Define to 1 if you have the `getpwent' function. */
|
||||||
#undef HAVE_GETPWENT
|
#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 */
|
/* Define to 1 if the Linux getrandom() syscall is available */
|
||||||
#undef HAVE_GETRANDOM_SYSCALL
|
#undef HAVE_GETRANDOM_SYSCALL
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue