summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2016-09-23 13:54:11 +0000
committerTom Lane2016-09-23 13:54:11 +0000
commit49a91b88e6c4afb840745c78942dd99ce125a6d6 (patch)
tree2bf1cf5f1336c5a275c11da0941af3ce6860c3e1
parent6fa51c79c7a645248a63205ce17af98ed404790d (diff)
Avoid using PostmasterRandom() for DSM control segment ID.
Commits 470d886c3 et al intended to fix the problem that the postmaster selected the same "random" DSM control segment ID on every start. But using PostmasterRandom() for that destroys the intended property that the delay between random_start_time and random_stop_time will be unpredictable. (Said delay is probably already more predictable than we could wish, but that doesn't mean that reducing it by a couple orders of magnitude is OK.) Revert the previous patch and add a comment warning against misuse of PostmasterRandom. Fix the original problem by calling srandom() early in PostmasterMain, using a low-security seed that will later be overwritten by PostmasterRandom. Discussion: <[email protected]>
-rw-r--r--src/backend/postmaster/postmaster.c17
-rw-r--r--src/backend/storage/ipc/dsm.c3
-rw-r--r--src/include/postmaster/postmaster.h1
3 files changed, 17 insertions, 4 deletions
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 67ccdce764..40995580af 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -403,6 +403,7 @@ static void processCancelRequest(Port *port, void *pkt);
static int initMasks(fd_set *rmask);
static void report_fork_failure_to_client(Port *port, int errnum);
static CAC_state canAcceptConnections(void);
+static long PostmasterRandom(void);
static void RandomSalt(char *salt, int len);
static void signal_child(pid_t pid, int signal);
static bool SignalSomeChildren(int signal, int targets);
@@ -575,6 +576,16 @@ PostmasterMain(int argc, char *argv[])
umask(S_IRWXG | S_IRWXO);
/*
+ * Initialize random(3) so we don't get the same values in every run.
+ *
+ * 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.
+ */
+ srandom((unsigned int) (MyProcPid ^ MyStartTime));
+
+ /*
* By default, palloc() requests in the postmaster will be allocated in
* the PostmasterContext, which is space that can be recycled by backends.
* Allocated data that needs to be available to backends should be
@@ -5099,8 +5110,12 @@ RandomSalt(char *salt, int len)
/*
* PostmasterRandom
+ *
+ * Caution: use this only for values needed during connection-request
+ * processing. Otherwise, the intended property of having an unpredictable
+ * delay between random_start_time and random_stop_time will be broken.
*/
-long
+static long
PostmasterRandom(void)
{
/*
diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c
index edafe4a3b9..d8066647a0 100644
--- a/src/backend/storage/ipc/dsm.c
+++ b/src/backend/storage/ipc/dsm.c
@@ -36,7 +36,6 @@
#include "lib/ilist.h"
#include "miscadmin.h"
-#include "postmaster/postmaster.h"
#include "storage/dsm.h"
#include "storage/ipc.h"
#include "storage/lwlock.h"
@@ -182,7 +181,7 @@ dsm_postmaster_startup(PGShmemHeader *shim)
{
Assert(dsm_control_address == NULL);
Assert(dsm_control_mapped_size == 0);
- dsm_control_handle = (dsm_handle) PostmasterRandom();
+ dsm_control_handle = random();
if (dsm_control_handle == 0)
continue;
if (dsm_impl_op(DSM_OP_CREATE, dsm_control_handle, segsize,
diff --git a/src/include/postmaster/postmaster.h b/src/include/postmaster/postmaster.h
index ef06d5d04c..b2d7776f2a 100644
--- a/src/include/postmaster/postmaster.h
+++ b/src/include/postmaster/postmaster.h
@@ -48,7 +48,6 @@ extern const char *progname;
extern void PostmasterMain(int argc, char *argv[]) pg_attribute_noreturn();
extern void ClosePostmasterPorts(bool am_syslogger);
-extern long PostmasterRandom(void);
extern int MaxLivePostmasterChildren(void);