From b607bfdc51ebe6401f32d01d3b614b818be1c645 Mon Sep 17 00:00:00 2001 From: Masahiko Sawada Date: Tue, 23 Sep 2025 00:24:12 -0700 Subject: [PATCH 2/2] PoC: Support getrandom() as the source of pg_strong_random(). getrandom() is the default random generation function when random_source_type is set to 'system'. Author: Reviewed-by: Discussion: https://postgr.es/m/ Backpatch-through: --- configure | 19 +++++++++++++++++++ configure.ac | 4 ++++ meson.build | 6 ++++++ src/include/pg_config.h.in | 3 +++ src/include/port.h | 4 ++-- src/port/pg_strong_random.c | 38 ++++++++++++++++++++++++++++++++++++- 6 files changed, 71 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 22cd866147b..08b8f04285f 100755 --- a/configure +++ b/configure @@ -18321,6 +18321,25 @@ PostgreSQL can use OpenSSL, native Windows API or /dev/urandom as a source of ra fi fi +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 getrandom +do : + ac_fn_c_check_func "$LINENO" "getrandom" "ac_cv_func_getrandom" +if test "x$ac_cv_func_getrandom" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GETRANDOM 1 +_ACEOF + +$as_echo "#define HAVE_GETRANDOM 1" >>confdefs.h + +fi +done + +fi + + + # If not set in template file, set bytes to use libc memset() if test x"$MEMSET_LOOP_LIMIT" = x"" ; then MEMSET_LOOP_LIMIT=1024 diff --git a/configure.ac b/configure.ac index e44943aa6fe..71be1318be6 100644 --- a/configure.ac +++ b/configure.ac @@ -2317,6 +2317,10 @@ PostgreSQL can use OpenSSL, native Windows API or /dev/urandom as a source of ra fi fi +AC_CHECK_HEADER([sys/random.h], + [AC_CHECK_FUNCS([getrandom], + [AC_DEFINE(HAVE_GETRANDOM, 1, [Define to 1 if you have getrandom])])]) + # If not set in template file, set bytes to use libc memset() if test x"$MEMSET_LOOP_LIMIT" = x"" ; then MEMSET_LOOP_LIMIT=1024 diff --git a/meson.build b/meson.build index 395416a6060..3d9a9ce2e9a 100644 --- a/meson.build +++ b/meson.build @@ -2713,6 +2713,12 @@ int main(void) endif endforeach +if cc.has_header('sys/random.h') and cc.has_function('getrandom', + args: test_c_args, prefix: ''' +#include ''') + cdata.set('HAVE_GETRANDOM', 1) +endif + if cc.has_type('socklen_t', args: test_c_args, include_directories: postgres_inc, prefix: ''' diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index c4dc5d72bdb..aa742d20b18 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -190,6 +190,9 @@ /* Define to 1 if you have the `getpeerucred' function. */ #undef HAVE_GETPEERUCRED +/* Define to 1 if you have the `getrandom' function. */ +#undef HAVE_GETRANDOM + /* Define to 1 if you have the header file. */ #undef HAVE_GSSAPI_EXT_H diff --git a/src/include/port.h b/src/include/port.h index d7464c231a5..af1ebce15de 100644 --- a/src/include/port.h +++ b/src/include/port.h @@ -520,8 +520,8 @@ typedef void (*pg_strong_random_init_fn) (void); typedef bool (*pg_strong_random_fn) (void *buf, size_t len); /* Function pointers to the random data generation implementations */ -extern pg_strong_random_init_fn pg_strong_random_init_impl; -extern pg_strong_random_fn pg_strong_random_impl; +extern PGDLLIMPORT pg_strong_random_init_fn pg_strong_random_init_impl; +extern PGDLLIMPORT pg_strong_random_fn pg_strong_random_impl; /* * Public functions to generate strong random data. The functions invoked diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c index 231995e42af..6024efd0bbd 100644 --- a/src/port/pg_strong_random.c +++ b/src/port/pg_strong_random.c @@ -151,7 +151,43 @@ pg_strong_random_system(void *buf, size_t len) return false; } -#else /* not WIN32 */ +#elif HAVE_GETRANDOM + +#include + +void +pg_strong_random_init_system(void) +{ + /* No initialization needed */ +} + +bool +pg_strong_random_system(void *buf, size_t len) +{ + char *p = buf; + ssize_t res; + + while (len) + { + /* Get random data from the urandom source in blocking mode */ + res = getrandom(p, len, 0); + + if (res <= 0) + { + if (errno == EINTR) + continue; /* interrupted by signal, just retry */ + + return false; + } + + p += res; + len -= res; + } + + return true; +} + +#else /* * On Unix-like platforms, just read /dev/urandom ourselves. -- 2.47.3