Thread

  1. [PATCH v4] Support getentropy() as source of pg_strong_random() where available

    Dagfinn Ilmari Mannsåker <ilmari@ilmari.org> — 2025-07-30T11:36:46Z

    ---
     configure                   | 24 ++++++++++++++++++-
     configure.ac                |  8 ++++++-
     meson.build                 |  9 ++++++++
     src/include/pg_config.h.in  |  6 +++++
     src/port/pg_strong_random.c | 46 ++++++++++++++++++++++++++++++++++---
     5 files changed, 88 insertions(+), 5 deletions(-)
    
    diff --git a/configure b/configure
    index 507a2437c33..f11cd4265bf 100755
    --- a/configure
    +++ b/configure
    @@ -16243,6 +16243,25 @@ cat >>confdefs.h <<_ACEOF
     _ACEOF
     
     
    +ac_fn_c_check_header_mongrel "$LINENO" "sys/random.h" "ac_cv_header_sys_random_h" "$ac_includes_default"
    +if test "x$ac_cv_header_sys_random_h" = xyes; then :
    +  for ac_func in getentropy
    +do :
    +  ac_fn_c_check_func "$LINENO" "getentropy" "ac_cv_func_getentropy"
    +if test "x$ac_cv_func_getentropy" = xyes; then :
    +  cat >>confdefs.h <<_ACEOF
    +#define HAVE_GETENTROPY 1
    +_ACEOF
    +
    +$as_echo "#define HAVE_GETENTROPY 1" >>confdefs.h
    +
    +fi
    +done
    +
    +fi
    +
    +
    +
     ac_fn_c_check_func "$LINENO" "explicit_bzero" "ac_cv_func_explicit_bzero"
     if test "x$ac_cv_func_explicit_bzero" = xyes; then :
       $as_echo "#define HAVE_EXPLICIT_BZERO 1" >>confdefs.h
    @@ -18479,6 +18498,9 @@ $as_echo "Windows native" >&6; }
     elif test x"$cross_compiling" = x"yes"; then
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: assuming /dev/urandom" >&5
     $as_echo "assuming /dev/urandom" >&6; }
    +elif test x"$ac_cv_func_getentropy" = x"yes"; then
    +  { $as_echo "$as_me:${as_lineno-$LINENO}: result: getentropy" >&5
    +$as_echo "getentropy" >&6; }
     else
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: /dev/urandom" >&5
     $as_echo "/dev/urandom" >&6; }
    @@ -18505,7 +18527,7 @@ fi
       if test x"$ac_cv_file__dev_urandom" = x"no" ; then
         as_fn_error $? "
     no source of strong random numbers was found
    -PostgreSQL can use OpenSSL, native Windows API or /dev/urandom as a source of random numbers." "$LINENO" 5
    +PostgreSQL can use OpenSSL, native Windows API, getentropy function, or /dev/urandom as a source of random numbers." "$LINENO" 5
       fi
     fi
     
    diff --git a/configure.ac b/configure.ac
    index 5f4548adc5c..9cf453fcd23 100644
    --- a/configure.ac
    +++ b/configure.ac
    @@ -1850,6 +1850,10 @@ AC_CHECK_DECLS([memset_s], [], [], [#define __STDC_WANT_LIB_EXT1__ 1
     # This is probably only present on macOS, but may as well check always
     AC_CHECK_DECLS(F_FULLFSYNC, [], [], [#include <fcntl.h>])
     
    +AC_CHECK_HEADER([sys/random.h],
    + [AC_CHECK_FUNCS([getentropy],
    +  [AC_DEFINE(HAVE_GETENTROPY, 1, [Define to 1 if you have getentropy])])])
    +
     AC_REPLACE_FUNCS(m4_normalize([
     	explicit_bzero
     	getopt
    @@ -2314,6 +2318,8 @@ elif test x"$PORTNAME" = x"win32" ; then
       AC_MSG_RESULT([Windows native])
     elif test x"$cross_compiling" = x"yes"; then
       AC_MSG_RESULT([assuming /dev/urandom])
    +elif test x"$ac_cv_func_getentropy" = x"yes"; then
    +  AC_MSG_RESULT(getentropy)
     else
       AC_MSG_RESULT([/dev/urandom])
       AC_CHECK_FILE([/dev/urandom], [], [])
    @@ -2321,7 +2327,7 @@ else
       if test x"$ac_cv_file__dev_urandom" = x"no" ; then
         AC_MSG_ERROR([
     no source of strong random numbers was found
    -PostgreSQL can use OpenSSL, native Windows API or /dev/urandom as a source of random numbers.])
    +PostgreSQL can use OpenSSL, native Windows API, getentropy function, or /dev/urandom as a source of random numbers.])
       fi
     fi
     
    diff --git a/meson.build b/meson.build
    index ca423dc8e12..70f5d6494cb 100644
    --- a/meson.build
    +++ b/meson.build
    @@ -2627,6 +2627,7 @@ header_checks = [
       'sys/personality.h',
       'sys/prctl.h',
       'sys/procctl.h',
    +  'sys/random.h',
       'sys/signalfd.h',
       'sys/ucred.h',
       'termios.h',
    @@ -2705,6 +2706,14 @@ return 0;
        don't.'''.format(func))
     endforeach
     
    +if cc.has_function('getentropy',
    +    args: test_c_args,
    +    prefix: '''
    +#include <unistd.h>
    +@0@
    +'''.format('@0@'.format(cdata.get('HAVE_SYS_RANDOM_H')) == '1' ? '#include <sys/random.h>' : ''))
    +  cdata.set('HAVE_GETENTROPY', 1)
    +endif
     
     if cc.has_type('struct option',
         args: test_c_args, include_directories: postgres_inc,
    diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
    index c4dc5d72bdb..147ab293518 100644
    --- a/src/include/pg_config.h.in
    +++ b/src/include/pg_config.h.in
    @@ -172,6 +172,9 @@
     /* Define to 1 if you have the `getauxval' function. */
     #undef HAVE_GETAUXVAL
     
    +/* Define to 1 if you have getentropy */
    +#undef HAVE_GETENTROPY
    +
     /* Define to 1 if you have the `getifaddrs' function. */
     #undef HAVE_GETIFADDRS
     
    @@ -448,6 +451,9 @@
     /* Define to 1 if you have the <sys/procctl.h> header file. */
     #undef HAVE_SYS_PROCCTL_H
     
    +/* Define to 1 if you have the <sys/random.h> header file. */
    +#undef HAVE_SYS_RANDOM_H
    +
     /* Define to 1 if you have the <sys/signalfd.h> header file. */
     #undef HAVE_SYS_SIGNALFD_H
     
    diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c
    index ea6780dcc9f..da482e96ae7 100644
    --- a/src/port/pg_strong_random.c
    +++ b/src/port/pg_strong_random.c
    @@ -40,7 +40,8 @@
      *
      * 1. OpenSSL's RAND_bytes()
      * 2. Windows' CryptGenRandom() function
    - * 3. /dev/urandom
    + * 3. getentropy() function
    + * 4. /dev/urandom
      *
      * Returns true on success, and false if none of the sources
      * were available. NB: It is important to check the return value!
    @@ -134,10 +135,49 @@ pg_strong_random(void *buf, size_t len)
     	return false;
     }
     
    -#else							/* not USE_OPENSSL or WIN32 */
    +#elif HAVE_GETENTROPY
    +
    +#include <limits.h>
    +
    +#ifdef HAVE_SYS_RANDOM_H
    +#include <sys/random.h>
    +#endif
    +
    +#ifndef GETENTROPY_MAX
    +#define GETENTROPY_MAX	256
    +#endif
    +
    +void
    +pg_strong_random_init(void)
    +{
    +	/* No initialization needed */
    +}
    +
    +bool
    +pg_strong_random(void *buf, size_t len)
    +{
    +	char	   *p = buf;
    +	ssize_t		res;
    +
    +	while (len)
    +	{
    +		size_t		l = Min(len, GETENTROPY_MAX);
    +
    +		res = getentropy(p, l);
    +		if (res < 0)
    +			return false;
    +
    +		p += l;
    +		len -= l;
    +	}
    +
    +	return true;
    +}
    +
    +#else							/* not USE_OPENSSL, WIN32, or HAVE_GETENTROPY */
     
     /*
    - * Without OpenSSL or Win32 support, just read /dev/urandom ourselves.
    + * Without OpenSSL, Win32, or getentropy() support, just read /dev/urandom ourselves.
      */
     
     void
    -- 
    2.50.1
    
    
    --=-=-=--