From 2e1f3ef7233f9ecafc0f4bfccdb1195bdebbf256 Mon Sep 17 00:00:00 2001 From: Masahiko Sawada Date: Mon, 22 Sep 2025 23:20:06 -0700 Subject: [PATCH 1/2] PoC: Select random source type. --- src/backend/utils/misc/Makefile | 1 + src/backend/utils/misc/guc_parameters.dat | 8 +++ src/backend/utils/misc/guc_tables.c | 1 + src/backend/utils/misc/meson.build | 1 + src/backend/utils/misc/postgresql.conf.sample | 1 + src/backend/utils/misc/random_source.c | 59 +++++++++++++++++++ src/bin/initdb/initdb.c | 13 ++++ src/include/port.h | 31 +++++++++- src/include/utils/guc.h | 1 + src/include/utils/guc_hooks.h | 1 + src/include/utils/random_source.h | 32 ++++++++++ src/port/pg_strong_random.c | 37 ++++++++---- 12 files changed, 174 insertions(+), 12 deletions(-) create mode 100644 src/backend/utils/misc/random_source.c create mode 100644 src/include/utils/random_source.h diff --git a/src/backend/utils/misc/Makefile b/src/backend/utils/misc/Makefile index b362ae43771..96686c50e5f 100644 --- a/src/backend/utils/misc/Makefile +++ b/src/backend/utils/misc/Makefile @@ -27,6 +27,7 @@ OBJS = \ pg_rusage.o \ ps_status.o \ queryenvironment.o \ + random_source.o \ rls.o \ sampling.o \ stack_depth.o \ diff --git a/src/backend/utils/misc/guc_parameters.dat b/src/backend/utils/misc/guc_parameters.dat index 6bc6be13d2a..22e9aa7dbab 100644 --- a/src/backend/utils/misc/guc_parameters.dat +++ b/src/backend/utils/misc/guc_parameters.dat @@ -3475,4 +3475,12 @@ assign_hook => 'assign_io_method', }, +{ name => 'random_source_type', type => 'enum', context => 'PGC_BACKEND', group => 'RESOURCES_KERNEL', + short_desc => 'Selects the random data generation function.', + variable => 'random_source_type', + boot_val => 'DEFAULT_RANDOM_SOURCE_TYPE', + options => 'random_source_type_options', + assign_hook => 'assign_random_source_type', +}, + ] diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c index 00c8376cf4d..0bdc144a155 100644 --- a/src/backend/utils/misc/guc_tables.c +++ b/src/backend/utils/misc/guc_tables.c @@ -99,6 +99,7 @@ #include "utils/pg_locale.h" #include "utils/plancache.h" #include "utils/ps_status.h" +#include "utils/random_source.h" #include "utils/rls.h" #include "utils/xml.h" diff --git a/src/backend/utils/misc/meson.build b/src/backend/utils/misc/meson.build index 9e389a00d05..6b03998b942 100644 --- a/src/backend/utils/misc/meson.build +++ b/src/backend/utils/misc/meson.build @@ -12,6 +12,7 @@ backend_sources += files( 'pg_rusage.c', 'ps_status.c', 'queryenvironment.c', + 'random_source.c', 'rls.c', 'sampling.c', 'stack_depth.c', diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index c36fcb9ab61..c148b06bd27 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -772,6 +772,7 @@ autovacuum_worker_slots = 16 # autovacuum worker slots to allocate #gin_pending_list_limit = 4MB #createrole_self_grant = '' # set and/or inherit #event_triggers = on +#random_source_type = 'system' # - Locale and Formatting - diff --git a/src/backend/utils/misc/random_source.c b/src/backend/utils/misc/random_source.c new file mode 100644 index 00000000000..8ae67cf8d85 --- /dev/null +++ b/src/backend/utils/misc/random_source.c @@ -0,0 +1,59 @@ +/*------------------------------------------------------------------------- + * + * random_source.c + * + * Dynamically setup random generation function based on random_source_type + * GUC parameter. + * + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994-5, Regents of the University of California + * + * + * IDENTIFICATION + * src/backend/utils/misc/random_source.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "port.h" +#include "utils/random_source.h" +#include "utils/guc.h" +#include "utils/guc_hooks.h" + +const struct config_enum_entry random_source_type_options[] = { + {"system", RANDOM_SOURCE_TYPE_SYSTEM, false}, +#ifdef USE_OPENSSL + {"openssl", RANDOM_SOURCE_TYPE_OSSL, false}, +#endif + {NULL, 0, false} +}; + +static const struct +{ + pg_strong_random_init_fn initfn; + pg_strong_random_fn genfn; +} random_source_type_table[] = { + + [RANDOM_SOURCE_TYPE_SYSTEM] = { + .initfn = pg_strong_random_init_system, + .genfn = pg_strong_random_system, + }, +#ifdef USE_OPENSSL + [RANDOM_SOURCE_TYPE_OSSL] = { + .initfn = pg_strong_random_init_openssl, + .genfn = pg_strong_random_openssl, + }, +#endif +}; + +int random_source_type = DEFAULT_RANDOM_SOURCE_TYPE; + +/* Assign hook for random_source_type */ +void +assign_random_source_type(int newval, void *extra) +{ + pg_strong_random_init_impl = random_source_type_table[newval].initfn; + pg_strong_random_impl = random_source_type_table[newval].genfn; +} diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index 92fe2f531f7..bcf7fb0f20c 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -1109,6 +1109,16 @@ choose_dsm_implementation(void) #endif } +static const char * +choose_random_source_type(void) +{ +#ifdef USE_OPENSSL + return "openssl"; +#else + return "system"; +#endif +} + /* * Determine platform-specific config settings * @@ -1356,6 +1366,9 @@ setup_config(void) conflines = replace_guc_value(conflines, "dynamic_shared_memory_type", dynamic_shared_memory_type, false); + conflines = replace_guc_value(conflines, "random_source_type", + choose_random_source_type(), false); + /* Caution: these depend on wal_segment_size_mb, they're not constants */ conflines = replace_guc_value(conflines, "min_wal_size", pretty_wal_size(DEFAULT_MIN_WAL_SEGS), false); diff --git a/src/include/port.h b/src/include/port.h index 3964d3b1293..d7464c231a5 100644 --- a/src/include/port.h +++ b/src/include/port.h @@ -509,8 +509,35 @@ extern char *pg_inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size); /* port/pg_strong_random.c */ -extern void pg_strong_random_init(void); -extern bool pg_strong_random(void *buf, size_t len); +extern void pg_strong_random_init_system(void); +extern bool pg_strong_random_system(void *buf, size_t len); +#ifdef USE_OPENSSL +extern void pg_strong_random_init_openssl(void); +extern bool pg_strong_random_openssl(void *buf, size_t len); +#endif + +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; + +/* + * Public functions to generate strong random data. The functions invoked + * from these function can be replaced by setting function pointers. + */ +static pg_attribute_always_inline void +pg_strong_random_init(void) +{ + (*pg_strong_random_init_impl) (); +} + +static pg_attribute_always_inline bool +pg_strong_random(void *buf, size_t len) +{ + return (*pg_strong_random_impl) (buf, len); +} /* * pg_backend_random used to be a wrapper for pg_strong_random before diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index f21ec37da89..c64e99318fa 100644 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -343,6 +343,7 @@ extern PGDLLIMPORT bool optimize_bounded_sort; extern PGDLLIMPORT const struct config_enum_entry archive_mode_options[]; extern PGDLLIMPORT const struct config_enum_entry dynamic_shared_memory_options[]; extern PGDLLIMPORT const struct config_enum_entry io_method_options[]; +extern PGDLLIMPORT const struct config_enum_entry random_source_type_options[]; extern PGDLLIMPORT const struct config_enum_entry recovery_target_action_options[]; extern PGDLLIMPORT const struct config_enum_entry wal_level_options[]; extern PGDLLIMPORT const struct config_enum_entry wal_sync_method_options[]; diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h index 82ac8646a8d..7bc8f6217ce 100644 --- a/src/include/utils/guc_hooks.h +++ b/src/include/utils/guc_hooks.h @@ -96,6 +96,7 @@ extern bool check_primary_slot_name(char **newval, void **extra, GucSource source); extern bool check_random_seed(double *newval, void **extra, GucSource source); extern void assign_random_seed(double newval, void *extra); +extern void assign_random_source_type(int newval, void *extra); extern const char *show_random_seed(void); extern bool check_recovery_prefetch(int *new_value, void **extra, GucSource source); diff --git a/src/include/utils/random_source.h b/src/include/utils/random_source.h new file mode 100644 index 00000000000..b4f8a88db43 --- /dev/null +++ b/src/include/utils/random_source.h @@ -0,0 +1,32 @@ +/*------------------------------------------------------------------------- + * + * random_source.h + * + * Copyright (c) 2007-2025, PostgreSQL Global Development Group + * + * src/include/utils/random_source.h + * + *------------------------------------------------------------------------- + */ + +#ifndef RANDOM_SOURCE_H +#define RANDOM_SOURCE_H + +typedef enum RandomSourceType +{ + RANDOM_SOURCE_TYPE_SYSTEM = 0, +#ifdef USE_OPENSSL + RANDOM_SOURCE_TYPE_OSSL, +#endif +} RandomSourceType; + +#ifdef USE_OPENSSL +#define DEFAULT_RANDOM_SOURCE_TYPE RANDOM_SOURCE_TYPE_OSSL +#else +#define DEFAULT_RANDOM_SOURCE_TYPE RANDOM_SOURCE_TYPE_SYSTEM +#endif + +/* GUC */ +extern PGDLLIMPORT int random_source_type; + +#endif /* RANDOM_SOURCE_H */ diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c index ea6780dcc9f..231995e42af 100644 --- a/src/port/pg_strong_random.c +++ b/src/port/pg_strong_random.c @@ -25,7 +25,7 @@ #include /* - * pg_strong_random & pg_strong_random_init + * pg_strong_random & pg_strong_random_init implementations. * * Generate requested number of random bytes. The returned bytes are * cryptographically secure, suitable for use e.g. in authentication. @@ -48,6 +48,21 @@ * would lead to predictable keys and security issues. */ +/* + * Set default implementations. + * + * The pg_strong_random and pg_strong_random_init implementations are fixed to + * the implementations follows in FRONTEND builds. On non-FRONTEND builds (i.e., + * backends) the implementations could be replaced by random_source_type GUC + * parameter. + */ +#ifdef USE_OPENSSL +pg_strong_random_init_fn pg_strong_random_init_impl = pg_strong_random_init_openssl; +pg_strong_random_fn pg_strong_random_impl = pg_strong_random_openssl; +#else +pg_strong_random_init_fn pg_strong_random_init_impl = pg_strong_random_init_system; +pg_strong_random_fn pg_strong_random_impl = pg_strong_random_system; +#endif #ifdef USE_OPENSSL @@ -55,13 +70,13 @@ #include void -pg_strong_random_init(void) +pg_strong_random_init_openssl(void) { /* No initialization needed */ } bool -pg_strong_random(void *buf, size_t len) +pg_strong_random_openssl(void *buf, size_t len) { int i; @@ -92,7 +107,9 @@ pg_strong_random(void *buf, size_t len) return false; } -#elif WIN32 +#endif + +#if WIN32 #include /* @@ -102,13 +119,13 @@ pg_strong_random(void *buf, size_t len) static HCRYPTPROV hProvider = 0; void -pg_strong_random_init(void) +pg_strong_random_init_system(void) { /* No initialization needed on WIN32 */ } bool -pg_strong_random(void *buf, size_t len) +pg_strong_random_system(void *buf, size_t len) { if (hProvider == 0) { @@ -134,20 +151,20 @@ pg_strong_random(void *buf, size_t len) return false; } -#else /* not USE_OPENSSL or WIN32 */ +#else /* not WIN32 */ /* - * Without OpenSSL or Win32 support, just read /dev/urandom ourselves. + * On Unix-like platforms, just read /dev/urandom ourselves. */ void -pg_strong_random_init(void) +pg_strong_random_init_system(void) { /* No initialization needed */ } bool -pg_strong_random(void *buf, size_t len) +pg_strong_random_system(void *buf, size_t len) { int f; char *p = buf; -- 2.47.3