Avoid using PostmasterRandom() for DSM control segment ID.
authorTom Lane
Fri, 23 Sep 2016 13:54:11 +0000 (09:54 -0400)
committerTom Lane
Fri, 23 Sep 2016 13:54:11 +0000 (09:54 -0400)
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: <20789.1474390434@sss.pgh.pa.us>

src/backend/postmaster/postmaster.c
src/backend/storage/ipc/dsm.c
src/include/postmaster/postmaster.h

index e0a15e9f099786eed7a46832c7c1091f6b9ce86e..ee531868c8dae49f33921787c5cc34969af39d20 100644 (file)
@@ -400,6 +400,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 *md5Salt);
 static void signal_child(pid_t pid, int signal);
 static bool SignalSomeChildren(int signal, int targets);
@@ -559,6 +560,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.
@@ -5125,8 +5136,12 @@ RandomSalt(char *md5Salt)
 
 /*
  * 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)
 {
    /*
index 357e8a98e547efba691a141ea01aa84672160345..7ce45caaf9b0986cf7df794674e2f9cb4a40e00c 100644 (file)
@@ -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"
@@ -180,7 +179,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,
index 9cf9e5a61d2d48eaf06dd8321aac7b23fedb4d13..de4633278064af9d0efdefbaf9eb253e15b95e54 100644 (file)
@@ -48,7 +48,6 @@ extern const char *progname;
 
 extern void PostmasterMain(int argc, char *argv[]) __attribute__((noreturn));
 extern void ClosePostmasterPorts(bool am_syslogger);
-extern long PostmasterRandom(void);
 
 extern int MaxLivePostmasterChildren(void);