From 9eb57c5fa50ed2f57d9320bb575371868316b5f2 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 19 Mar 2015 22:21:49 +0100 Subject: [PATCH] Issue #22181: The availability of the getrandom() is now checked in configure, and stored in pyconfig.h as the new HAVE_GETRANDOM_SYSCALL define. Fix os.urandom() tests using file descriptors if os.urandom() uses getrandom(). --- Lib/test/test_os.py | 3 + Python/random.c | 13 ++-- configure | 170 ++++++++++---------------------------------- configure.ac | 24 +++++++ pyconfig.h.in | 3 + 5 files changed, 73 insertions(+), 140 deletions(-) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index ab0fe94bd07..70734ab7926 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -1199,9 +1199,12 @@ class URandomTests(unittest.TestCase): HAVE_GETENTROPY = (sysconfig.get_config_var('HAVE_GETENTROPY') == 1) +HAVE_GETRANDOM = (sysconfig.get_config_var('HAVE_GETRANDOM_SYSCALL') == 1) @unittest.skipIf(HAVE_GETENTROPY, "getentropy() does not use a file descriptor") +@unittest.skipIf(HAVE_GETRANDOM, + "getrandom() does not use a file descriptor") class URandomFDTests(unittest.TestCase): @unittest.skipUnless(resource, "test requires the resource module") def test_urandom_failure(self): diff --git a/Python/random.c b/Python/random.c index dcc3aab79f4..10fc505e0fa 100644 --- a/Python/random.c +++ b/Python/random.c @@ -6,11 +6,8 @@ # ifdef HAVE_SYS_STAT_H # include # endif -# ifdef HAVE_SYS_SYSCALL_H +# ifdef HAVE_GETRANDOM_SYSCALL # include -# if defined(__linux__) && defined(SYS_getrandom) -# define HAVE_GETRANDOM -# endif # endif #endif @@ -102,7 +99,7 @@ py_getentropy(unsigned char *buffer, Py_ssize_t size, int fatal) #else /* !HAVE_GETENTROPY */ -#ifdef HAVE_GETRANDOM +#ifdef HAVE_GETRANDOM_SYSCALL static int py_getrandom(void *buffer, Py_ssize_t size, int raise) { @@ -173,7 +170,7 @@ dev_urandom_noraise(unsigned char *buffer, Py_ssize_t size) if (fd < 0) Py_FatalError("Failed to open /dev/urandom"); -#ifdef HAVE_GETRANDOM +#ifdef HAVE_GETRANDOM_SYSCALL if (py_getrandom(buffer, size, 0) == 1) return; /* getrandom() is not supported by the running kernel, fall back @@ -205,14 +202,14 @@ dev_urandom_python(char *buffer, Py_ssize_t size) int fd; Py_ssize_t n; struct _Py_stat_struct st; -#ifdef HAVE_GETRANDOM +#ifdef HAVE_GETRANDOM_SYSCALL int res; #endif if (size <= 0) return 0; -#ifdef HAVE_GETRANDOM +#ifdef HAVE_GETRANDOM_SYSCALL res = py_getrandom(buffer, size, 1); if (res < 0) return -1; diff --git a/configure b/configure index d91a9c7cbc4..a49ba69549c 100755 --- a/configure +++ b/configure @@ -650,9 +650,6 @@ USE_SIGNAL_MODULE TCLTK_LIBS TCLTK_INCLUDES LIBFFI_INCLUDEDIR -PKG_CONFIG_LIBDIR -PKG_CONFIG_PATH -PKG_CONFIG SHLIBS CFLAGSFORSHARED LINKFORSHARED @@ -832,10 +829,7 @@ CFLAGS LDFLAGS LIBS CPPFLAGS -CPP -PKG_CONFIG -PKG_CONFIG_PATH -PKG_CONFIG_LIBDIR' +CPP' # Initialize some variables set by options. @@ -1523,11 +1517,6 @@ Some influential environment variables: CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor - PKG_CONFIG path to pkg-config utility - PKG_CONFIG_PATH - directories to add to pkg-config's search path - PKG_CONFIG_LIBDIR - path overriding pkg-config's built-in search path Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -9434,126 +9423,7 @@ $as_echo "no" >&6; } fi - - - - - - - -if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. -set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_PKG_CONFIG+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $PKG_CONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -PKG_CONFIG=$ac_cv_path_PKG_CONFIG -if test -n "$PKG_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 -$as_echo "$PKG_CONFIG" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_path_PKG_CONFIG"; then - ac_pt_PKG_CONFIG=$PKG_CONFIG - # Extract the first word of "pkg-config", so it can be a program name with args. -set dummy pkg-config; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $ac_pt_PKG_CONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG -if test -n "$ac_pt_PKG_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 -$as_echo "$ac_pt_PKG_CONFIG" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_pt_PKG_CONFIG" = x; then - PKG_CONFIG="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - PKG_CONFIG=$ac_pt_PKG_CONFIG - fi -else - PKG_CONFIG="$ac_cv_path_PKG_CONFIG" -fi - -fi -if test -n "$PKG_CONFIG"; then - _pkg_min_version=0.9.0 - { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 -$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } - if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - PKG_CONFIG="" - fi -fi +PKG_PROG_PKG_CONFIG # Check for use of the system expat library { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-system-expat" >&5 @@ -15838,6 +15708,42 @@ $as_echo "#define HAVE_DIRENT_D_TYPE 1" >>confdefs.h fi +# check if the Linux getrandom() syscall is available +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the Linux getrandom() syscall" >&5 +$as_echo_n "checking for the Linux getrandom() syscall... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + + #include + + int main() { + 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); + return 0; + } + + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + have_getrandom_syscall=yes +else + have_getrandom_syscall=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_syscall" >&5 +$as_echo "$have_getrandom_syscall" >&6; } + +if test "$have_getrandom_syscall" = yes; then + +$as_echo "#define HAVE_GETRANDOM_SYSCALL 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" diff --git a/configure.ac b/configure.ac index c9bb90bd0be..a6eaadc1e4d 100644 --- a/configure.ac +++ b/configure.ac @@ -4972,6 +4972,30 @@ if test "$have_dirent_d_type" = yes; then [Define to 1 if the dirent structure has a d_type field]) fi +# check if the Linux getrandom() syscall is available +AC_MSG_CHECKING(for the Linux getrandom() syscall) +AC_LINK_IFELSE( +[ + AC_LANG_SOURCE([[ + #include + + int main() { + 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); + return 0; + } + ]]) +],[have_getrandom_syscall=yes],[have_getrandom_syscall=no]) +AC_MSG_RESULT($have_getrandom_syscall) + +if test "$have_getrandom_syscall" = yes; then + AC_DEFINE(HAVE_GETRANDOM_SYSCALL, 1, + [Define to 1 if the Linux getrandom() syscall 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]) diff --git a/pyconfig.h.in b/pyconfig.h.in index 10426c7cd3e..c8ce9760451 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -395,6 +395,9 @@ /* Define to 1 if you have the `getpwent' function. */ #undef HAVE_GETPWENT +/* Define to 1 if the Linux getrandom() syscall is available */ +#undef HAVE_GETRANDOM_SYSCALL + /* Define to 1 if you have the `getresgid' function. */ #undef HAVE_GETRESGID