From 76efc715ade5c35e7b618d370b7a9e0045ae3dc0 Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Tue, 9 Oct 2018 14:32:47 +1300 Subject: [PATCH] Use different random() seeds in all backends. Background workers, including parallel workers, were generating the same sequence of numbers in various code paths that use random(). This was noticed by harmless DSM handle collisions during execution of Parallel Hash, but any code that calls random() in background workers could be affected if it cares about different backends generating different numbers. Repair by refactoring the seed initialization code so that all backends run it. Use the same function for the postmaster, its children and also standalone processes, for consistency. Back-patch only to 11, because that's where Parallel Hash landed, making this obvious to anyone tracing syscalls. Author: Thomas Munro Reviewed-by: Tom Lane Discussion: https://postgr.es/m/CAEepm%3D2eJj_6%3DB%2B2tEpGu2nf1BjthCf9nXXUouYvJJ4C5WSwhg%40mail.gmail.com --- src/backend/postmaster/postmaster.c | 43 +++++++++++++++++------------ src/backend/utils/init/miscinit.c | 4 ++- src/include/postmaster/postmaster.h | 1 + 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 41de140ae01..9e90306f411 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -602,10 +602,10 @@ PostmasterMain(int argc, char *argv[]) * * Note: the seed is pretty predictable from externally-visible facts such * as postmaster start time, so avoid using random() for security-critical - * random values during postmaster startup. At the time of first - * connection, PostmasterRandom will select a hopefully-more-random seed. + * random values during postmaster startup. InitPostmasterChild() will + * do this again to set a new seed in child processes. */ - srandom((unsigned int) (MyProcPid ^ MyStartTime)); + InitRandomSeeds(); /* * By default, palloc() requests in the postmaster will be allocated in @@ -2513,6 +2513,28 @@ ClosePostmasterPorts(bool am_syslogger) } +/* + * InitRandomSeeds -- initialize seeds for random number generators + * + * Called in every backend after MyProcPid and MyStartTime have been assigned. + */ +void +InitRandomSeeds(void) +{ + /* + * Don't want backend to be able to see the postmaster random number + * generator state. We have to clobber the static random_seed. + */ +#ifndef HAVE_STRONG_RANDOM + random_seed = 0; + random_start_time.tv_usec = 0; +#endif + + /* Set a different seed for random() in every backend. */ + srandom((unsigned int) (MyProcPid ^ MyStartTime)); +} + + /* * reset_shared -- reset shared memory and semaphores */ @@ -4315,23 +4337,8 @@ BackendRun(Port *port) char **av; int maxac; int ac; - long secs; - int usecs; int i; - /* - * Don't want backend to be able to see the postmaster random number - * generator state. We have to clobber the static random_seed *and* start - * a new random sequence in the random() library function. - */ -#ifndef HAVE_STRONG_RANDOM - random_seed = 0; - random_start_time.tv_usec = 0; -#endif - /* slightly hacky way to convert timestamptz into integers */ - TimestampDifference(0, port->SessionStartTime, &secs, &usecs); - srandom((unsigned int) (MyProcPid ^ (usecs << 12) ^ secs)); - /* * Now, build the argv vector that will be given to PostgresMain. * diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index f590ecb25e8..f35bfe813f9 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -278,6 +278,8 @@ InitPostmasterChild(void) MyStartTime = time(NULL); /* set our start time in case we call elog */ + InitRandomSeeds(); /* set up per-backend random seeds */ + /* * make sure stderr is in binary mode before anything can possibly be * written to it, in case it's actually the syslogger pipe, so the pipe @@ -331,7 +333,7 @@ InitStandaloneProcess(const char *argv0) * high-entropy seed before any user query. Fewer distinct initial seeds * can occur here. */ - srandom((unsigned int) (MyProcPid ^ MyStartTime)); + InitRandomSeeds(); /* Initialize process-local latch support */ InitializeLatchSupport(); diff --git a/src/include/postmaster/postmaster.h b/src/include/postmaster/postmaster.h index 1877eef2391..217ef4490f4 100644 --- a/src/include/postmaster/postmaster.h +++ b/src/include/postmaster/postmaster.h @@ -48,6 +48,7 @@ extern PGDLLIMPORT const char *progname; extern void PostmasterMain(int argc, char *argv[]) pg_attribute_noreturn(); extern void ClosePostmasterPorts(bool am_syslogger); +extern void InitRandomSeeds(void); extern int MaxLivePostmasterChildren(void); -- 2.17.1 (Apple Git-112)