rand: add support for getrandom() (#526)

glibc provides arc4random_buf() but musl does not and /dev/urandom is
not always available.
pull/529/head
Ben Noordhuis 2 years ago committed by GitHub
parent 66d0c013fa
commit 69950390b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      CMakeLists.txt
  2. 1
      configure.ac
  3. 5
      include/ares_build.h.cmake
  4. 102
      m4/cares-functions.m4
  5. 3
      src/lib/ares_config.h.cmake
  6. 17
      src/lib/ares_rand.c
  7. 4
      src/lib/setup_once.h

@ -164,6 +164,7 @@ CARES_FUNCTION_IN_LIBRARY (clock_gettime rt HAVE_LIBRT)
# Look for necessary includes
CHECK_INCLUDE_FILES (sys/types.h HAVE_SYS_TYPES_H)
CHECK_INCLUDE_FILES (sys/random.h HAVE_SYS_RANDOM_H)
CHECK_INCLUDE_FILES (sys/socket.h HAVE_SYS_SOCKET_H)
CHECK_INCLUDE_FILES (sys/sockio.h HAVE_SYS_SOCKIO_H)
CHECK_INCLUDE_FILES (arpa/inet.h HAVE_ARPA_INET_H)
@ -281,6 +282,7 @@ CARES_EXTRAINCLUDE_IFSET (HAVE_STDLIB_H stdlib.h)
CARES_EXTRAINCLUDE_IFSET (HAVE_STRING_H string.h)
CARES_EXTRAINCLUDE_IFSET (HAVE_STRINGS_H strings.h)
CARES_EXTRAINCLUDE_IFSET (HAVE_SYS_IOCTL_H sys/ioctl.h)
CARES_EXTRAINCLUDE_IFSET (HAVE_SYS_RANDOM_H sys/random.h)
CARES_EXTRAINCLUDE_IFSET (HAVE_SYS_SELECT_H sys/select.h)
CARES_EXTRAINCLUDE_IFSET (HAVE_SYS_SOCKET_H sys/socket.h)
CARES_EXTRAINCLUDE_IFSET (HAVE_SYS_SOCKIO_H sys/sockio.h)
@ -365,6 +367,7 @@ CHECK_SYMBOL_EXISTS (gethostbyaddr "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_GETHOST
CHECK_SYMBOL_EXISTS (gethostbyname "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_GETHOSTBYNAME)
CHECK_SYMBOL_EXISTS (gethostname "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_GETHOSTNAME)
CHECK_SYMBOL_EXISTS (getnameinfo "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_GETNAMEINFO)
CHECK_SYMBOL_EXISTS (getrandom "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_GETRANDOM)
CHECK_SYMBOL_EXISTS (getservbyport_r "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_GETSERVBYPORT_R)
CHECK_SYMBOL_EXISTS (getservbyname_r "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_GETSERVBYNAME_R)
CHECK_SYMBOL_EXISTS (gettimeofday "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_GETTIMEOFDAY)
@ -562,6 +565,9 @@ ENDIF ()
IF (HAVE_SYS_TYPES_H)
SET (CARES_HAVE_SYS_TYPES_H 1)
ENDIF ()
IF (HAVE_SYS_RANDOM_H)
SET (CARES_HAVE_SYS_RANDOM_H 1)
ENDIF()
IF (HAVE_SYS_SOCKET_H)
SET (CARES_HAVE_SYS_SOCKET_H 1)
ENDIF()

@ -666,6 +666,7 @@ CARES_CHECK_FUNC_GETENV
CARES_CHECK_FUNC_GETHOSTBYADDR
CARES_CHECK_FUNC_GETHOSTBYNAME
CARES_CHECK_FUNC_GETHOSTNAME
CARES_CHECK_FUNC_GETRANDOM
CARES_CHECK_FUNC_GETSERVBYPORT_R
CARES_CHECK_FUNC_INET_NET_PTON
CARES_CHECK_FUNC_INET_NTOP

@ -8,6 +8,7 @@
* files. We need to include some dependent headers that may be system specific
* for C-Ares */
#cmakedefine CARES_HAVE_SYS_TYPES_H
#cmakedefine CARES_HAVE_SYS_RANDOM_H
#cmakedefine CARES_HAVE_SYS_SOCKET_H
#cmakedefine CARES_HAVE_WINDOWS_H
#cmakedefine CARES_HAVE_WS2TCPIP_H
@ -20,6 +21,10 @@
# include <sys/types.h>
#endif
#ifdef CARES_HAVE_SYS_RANDOM_H
# include <sys/random.h>
#endif
#ifdef CARES_HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif

@ -186,6 +186,24 @@ cares_includes_stropts="\
])
dnl CARES_INCLUDES_SYS_RANDOM
dnl -------------------------------------------------
dnl Set up variable with list of headers that must be
dnl included when sys/random.h is to be included.
AC_DEFUN([CARES_INCLUDES_SYS_RANDOM], [
cares_includes_sys_random="\
/* includes start */
#ifdef HAVE_SYS_RANDOM_H
# include <sys/random.h>
#endif
/* includes end */"
AC_CHECK_HEADERS(
sys/random.h,
[], [], [$cares_includes_sys_random])
])
dnl CARES_INCLUDES_SYS_SOCKET
dnl -------------------------------------------------
dnl Set up variable with list of headers that must be
@ -1520,6 +1538,90 @@ AC_DEFUN([CARES_CHECK_FUNC_GETHOSTNAME], [
fi
])
dnl CARES_CHECK_FUNC_GETRANDOM
dnl -------------------------------------------------
dnl Verify if getrandom is available, prototyped, and
dnl can be compiled. If all of these are true, and
dnl usage has not been previously disallowed with
dnl shell variable cares_disallow_getrandom, then
dnl HAVE_GETRANDOM will be defined.
AC_DEFUN([CARES_CHECK_FUNC_GETRANDOM], [
AC_REQUIRE([CARES_INCLUDES_SYS_RANDOM])dnl
#
tst_links_getrandom="unknown"
tst_proto_getrandom="unknown"
tst_compi_getrandom="unknown"
tst_allow_getrandom="unknown"
#
AC_MSG_CHECKING([if getrandom can be linked])
AC_LINK_IFELSE([
AC_LANG_FUNC_LINK_TRY([getrandom])
],[
AC_MSG_RESULT([yes])
tst_links_getrandom="yes"
],[
AC_MSG_RESULT([no])
tst_links_getrandom="no"
])
#
if test "$tst_links_getrandom" = "yes"; then
AC_MSG_CHECKING([if getrandom is prototyped])
AC_EGREP_CPP([getrandom],[
$cares_includes_sys_random
],[
AC_MSG_RESULT([yes])
tst_proto_getrandom="yes"
],[
AC_MSG_RESULT([no])
tst_proto_getrandom="no"
])
fi
#
if test "$tst_proto_getrandom" = "yes"; then
AC_MSG_CHECKING([if getrandom is compilable])
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
$cares_includes_sys_random
]],[[
if(0 != getrandom(0, 0, 0))
return 1;
]])
],[
AC_MSG_RESULT([yes])
tst_compi_getrandom="yes"
],[
AC_MSG_RESULT([no])
tst_compi_getrandom="no"
])
fi
#
if test "$tst_compi_getrandom" = "yes"; then
AC_MSG_CHECKING([if getrandom usage allowed])
if test "x$cares_disallow_getrandom" != "xyes"; then
AC_MSG_RESULT([yes])
tst_allow_getrandom="yes"
else
AC_MSG_RESULT([no])
tst_allow_getrandom="no"
fi
fi
#
AC_MSG_CHECKING([if getrandom might be used])
if test "$tst_links_getrandom" = "yes" &&
test "$tst_proto_getrandom" = "yes" &&
test "$tst_compi_getrandom" = "yes" &&
test "$tst_allow_getrandom" = "yes"; then
AC_MSG_RESULT([yes])
AC_DEFINE_UNQUOTED(HAVE_GETRANDOM, 1,
[Define to 1 if you have the getrandom function.])
ac_cv_func_getrandom="yes"
else
AC_MSG_RESULT([no])
ac_cv_func_getrandom="no"
fi
])
dnl CARES_CHECK_FUNC_GETSERVBYPORT_R
dnl -------------------------------------------------

@ -123,6 +123,9 @@
/* Define to 1 if you have the getnameinfo function. */
#cmakedefine HAVE_GETNAMEINFO
/* Define to 1 if you have the getrandom function. */
#cmakedefine HAVE_GETRANDOM
/* Define to 1 if you have the getservbyport_r function. */
#cmakedefine HAVE_GETSERVBYPORT_R

@ -155,7 +155,7 @@ static int ares__init_rand_engine(ares_rand_state *state)
{
memset(state, 0, sizeof(*state));
#if defined(HAVE_ARC4RANDOM_BUF) || defined(_WIN32)
#if defined(HAVE_ARC4RANDOM_BUF) || defined(HAVE_GETRANDOM) || defined(_WIN32)
state->type = ARES_RAND_OS;
return 1;
#elif defined(CARES_RANDOM_FILE)
@ -241,6 +241,21 @@ static void ares__rand_bytes(ares_rand_state *state, unsigned char *buf, size_t
#elif defined(HAVE_ARC4RANDOM_BUF)
arc4random_buf(buf, len);
return;
#elif defined(HAVE_GETRANDOM)
while (1) {
size_t n = len - bytes_read;
/* getrandom() on Linux always succeeds and is never
* interrupted by a signal when requesting <= 256 bytes.
*/
ssize_t rv = getrandom(buf + bytes_read, n > 256 ? 256 : n, 0);
if (rv <= 0)
continue; /* Just retry. */
bytes_read += rv;
if (bytes_read == len)
return;
}
break;
#else
/* Shouldn't be possible to be here */
break;

@ -91,6 +91,10 @@
# endif
#endif
#ifdef HAVE_SYS_RANDOM_H
#include <sys/random.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif

Loading…
Cancel
Save