mirror of
https://github.com/postgres/postgres.git
synced 2025-08-30 06:01:21 +03:00
Revert "Replace PostmasterRandom() with a stronger way of generating randomness."
This reverts commit 9e083fd468
. That was a
few bricks shy of a load:
* Query cancel stopped working
* Buildfarm member pademelon stopped working, because the box doesn't have
/dev/urandom nor /dev/random.
This clearly needs some more discussion, and a quite different patch, so
revert for now.
This commit is contained in:
@@ -358,6 +358,14 @@ static volatile bool avlauncher_needs_signal = false;
|
||||
static volatile bool StartWorkerNeeded = true;
|
||||
static volatile bool HaveCrashedWorker = false;
|
||||
|
||||
/*
|
||||
* State for assigning random salts and cancel keys.
|
||||
* Also, the global MyCancelKey passes the cancel key assigned to a given
|
||||
* backend from the postmaster to that backend (via fork).
|
||||
*/
|
||||
static unsigned int random_seed = 0;
|
||||
static struct timeval random_start_time;
|
||||
|
||||
#ifdef USE_BONJOUR
|
||||
static DNSServiceRef bonjour_sdref = NULL;
|
||||
#endif
|
||||
@@ -395,6 +403,8 @@ 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);
|
||||
static void TerminateChildren(int signal);
|
||||
@@ -569,11 +579,9 @@ PostmasterMain(int argc, char *argv[])
|
||||
* 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 don't use random() for security-critical
|
||||
* random values (use pg_strong_random() instead). Backends select a
|
||||
* somewhat more random seed after forking, in BackendRun(), based on the
|
||||
* PID and session start timestamp, but that is still not suitable for
|
||||
* security-critical values.
|
||||
* 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));
|
||||
|
||||
@@ -1284,6 +1292,8 @@ PostmasterMain(int argc, char *argv[])
|
||||
* Remember postmaster startup time
|
||||
*/
|
||||
PgStartTime = GetCurrentTimestamp();
|
||||
/* PostmasterRandom wants its own copy */
|
||||
gettimeofday(&random_start_time, NULL);
|
||||
|
||||
/*
|
||||
* We're ready to rock and roll...
|
||||
@@ -2333,6 +2343,15 @@ ConnCreate(int serverFd)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Precompute password salt values to use for this connection. It's
|
||||
* slightly annoying to do this long in advance of knowing whether we'll
|
||||
* need 'em or not, but we must do the random() calls before we fork, not
|
||||
* after. Else the postmaster's random sequence won't get advanced, and
|
||||
* all backends would end up using the same salt...
|
||||
*/
|
||||
RandomSalt(port->md5Salt, sizeof(port->md5Salt));
|
||||
|
||||
/*
|
||||
* Allocate GSSAPI specific state struct
|
||||
*/
|
||||
@@ -3885,12 +3904,7 @@ BackendStartup(Port *port)
|
||||
* backend will have its own copy in the forked-off process' value of
|
||||
* MyCancelKey, so that it can transmit the key to the frontend.
|
||||
*/
|
||||
if (!pg_strong_random(&MyCancelKey, sizeof(MyCancelKey)))
|
||||
{
|
||||
ereport(LOG,
|
||||
(errmsg("could not generate random query cancel key")));
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
MyCancelKey = PostmasterRandom();
|
||||
bn->cancel_key = MyCancelKey;
|
||||
|
||||
/* Pass down canAcceptConnections state */
|
||||
@@ -4198,6 +4212,13 @@ BackendRun(Port *port)
|
||||
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.
|
||||
*/
|
||||
random_seed = 0;
|
||||
random_start_time.tv_usec = 0;
|
||||
/* slightly hacky way to convert timestamptz into integers */
|
||||
TimestampDifference(0, port->SessionStartTime, &secs, &usecs);
|
||||
srandom((unsigned int) (MyProcPid ^ (usecs << 12) ^ secs));
|
||||
@@ -5045,6 +5066,66 @@ StartupPacketTimeoutHandler(void)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* RandomSalt
|
||||
*/
|
||||
static void
|
||||
RandomSalt(char *salt, int len)
|
||||
{
|
||||
long rand;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* We use % 255, sacrificing one possible byte value, so as to ensure that
|
||||
* all bits of the random() value participate in the result. While at it,
|
||||
* add one to avoid generating any null bytes.
|
||||
*/
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
rand = PostmasterRandom();
|
||||
salt[i] = (rand % 255) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
static long
|
||||
PostmasterRandom(void)
|
||||
{
|
||||
/*
|
||||
* Select a random seed at the time of first receiving a request.
|
||||
*/
|
||||
if (random_seed == 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
struct timeval random_stop_time;
|
||||
|
||||
gettimeofday(&random_stop_time, NULL);
|
||||
|
||||
/*
|
||||
* We are not sure how much precision is in tv_usec, so we swap
|
||||
* the high and low 16 bits of 'random_stop_time' and XOR them
|
||||
* with 'random_start_time'. On the off chance that the result is
|
||||
* 0, we loop until it isn't.
|
||||
*/
|
||||
random_seed = random_start_time.tv_usec ^
|
||||
((random_stop_time.tv_usec << 16) |
|
||||
((random_stop_time.tv_usec >> 16) & 0xffff));
|
||||
}
|
||||
while (random_seed == 0);
|
||||
|
||||
srandom(random_seed);
|
||||
}
|
||||
|
||||
return random();
|
||||
}
|
||||
|
||||
/*
|
||||
* Count up number of child processes of specified types (dead_end chidren
|
||||
* are always excluded).
|
||||
@@ -5222,37 +5303,31 @@ StartAutovacuumWorker(void)
|
||||
* we'd better have something random in the field to prevent
|
||||
* unfriendly people from sending cancels to them.
|
||||
*/
|
||||
if (pg_strong_random(&MyCancelKey, sizeof(MyCancelKey)))
|
||||
MyCancelKey = PostmasterRandom();
|
||||
bn->cancel_key = MyCancelKey;
|
||||
|
||||
/* Autovac workers are not dead_end and need a child slot */
|
||||
bn->dead_end = false;
|
||||
bn->child_slot = MyPMChildSlot = AssignPostmasterChildSlot();
|
||||
bn->bgworker_notify = false;
|
||||
|
||||
bn->pid = StartAutoVacWorker();
|
||||
if (bn->pid > 0)
|
||||
{
|
||||
bn->cancel_key = MyCancelKey;
|
||||
|
||||
/* Autovac workers are not dead_end and need a child slot */
|
||||
bn->dead_end = false;
|
||||
bn->child_slot = MyPMChildSlot = AssignPostmasterChildSlot();
|
||||
bn->bgworker_notify = false;
|
||||
|
||||
bn->pid = StartAutoVacWorker();
|
||||
if (bn->pid > 0)
|
||||
{
|
||||
bn->bkend_type = BACKEND_TYPE_AUTOVAC;
|
||||
dlist_push_head(&BackendList, &bn->elem);
|
||||
bn->bkend_type = BACKEND_TYPE_AUTOVAC;
|
||||
dlist_push_head(&BackendList, &bn->elem);
|
||||
#ifdef EXEC_BACKEND
|
||||
ShmemBackendArrayAdd(bn);
|
||||
ShmemBackendArrayAdd(bn);
|
||||
#endif
|
||||
/* all OK */
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* fork failed, fall through to report -- actual error message
|
||||
* was logged by StartAutoVacWorker
|
||||
*/
|
||||
(void) ReleasePostmasterChildSlot(bn->child_slot);
|
||||
/* all OK */
|
||||
return;
|
||||
}
|
||||
else
|
||||
ereport(LOG,
|
||||
(errmsg("could not generate random query cancel key")));
|
||||
|
||||
/*
|
||||
* fork failed, fall through to report -- actual error message was
|
||||
* logged by StartAutoVacWorker
|
||||
*/
|
||||
(void) ReleasePostmasterChildSlot(bn->child_slot);
|
||||
free(bn);
|
||||
}
|
||||
else
|
||||
@@ -5540,11 +5615,7 @@ assign_backendlist_entry(RegisteredBgWorker *rw)
|
||||
* have something random in the field to prevent unfriendly people from
|
||||
* sending cancels to them.
|
||||
*/
|
||||
if (!pg_strong_random(&MyCancelKey, sizeof(MyCancelKey)))
|
||||
{
|
||||
rw->rw_crashed_at = GetCurrentTimestamp();
|
||||
return false;
|
||||
}
|
||||
MyCancelKey = PostmasterRandom();
|
||||
bn->cancel_key = MyCancelKey;
|
||||
|
||||
bn->child_slot = MyPMChildSlot = AssignPostmasterChildSlot();
|
||||
|
Reference in New Issue
Block a user