Do ClosePostmasterPorts() earlier in SubPostmasterMain().

In standard Unix builds, postmaster child processes do ClosePostmasterPorts
immediately after InitPostmasterChild, that is almost immediately after
being spawned.  This is important because we don't want children holding
open the postmaster's end of the postmaster death watch pipe.

However, in EXEC_BACKEND builds, SubPostmasterMain was postponing this
responsibility significantly, in order to make it slightly more convenient
to pass the right flag value to ClosePostmasterPorts.  This is bad,
particularly seeing that process_shared_preload_libraries() might invoke
nearly-arbitrary code.  Rearrange so that we do it as soon as we've
fetched the socket FDs via read_backend_variables().

Also move the comment explaining about randomize_va_space to before the
call of PGSharedMemoryReAttach, which is where it's relevant.  The old
placement was appropriate when the reattach happened inside
CreateSharedMemoryAndSemaphores, but that was a long time ago.

Back-patch to 9.3; the patch doesn't apply cleanly before that, and
it doesn't seem worth a lot of effort given that we've had no actual
field complaints traceable to this.

Discussion: <4157.1475178360@sss.pgh.pa.us>
This commit is contained in:
Tom Lane 2016-10-01 17:15:09 -04:00
parent 9a109452da
commit 3b90e38c5d
1 changed files with 18 additions and 39 deletions

View File

@ -4635,10 +4635,17 @@ SubPostmasterMain(int argc, char *argv[])
/* Setup essential subsystems (to ensure elog() behaves sanely) */
InitializeGUCOptions();
/* Check we got appropriate args */
if (argc < 3)
elog(FATAL, "invalid subpostmaster invocation");
/* Read in the variables file */
memset(&port, 0, sizeof(Port));
read_backend_variables(argv[2], &port);
/* Close the postmaster's sockets (as soon as we know them) */
ClosePostmasterPorts(strcmp(argv[1], "--forklog") == 0);
/*
* Set reference point for stack-depth checking
*/
@ -4656,15 +4663,21 @@ SubPostmasterMain(int argc, char *argv[])
errmsg("out of memory")));
#endif
/* Check we got appropriate args */
if (argc < 3)
elog(FATAL, "invalid subpostmaster invocation");
/*
* If appropriate, physically re-attach to shared memory segment. We want
* to do this before going any further to ensure that we can attach at the
* same address the postmaster used. On the other hand, if we choose not
* to re-attach, we may have other cleanup to do.
*
* If testing EXEC_BACKEND on Linux, you should run this as root before
* starting the postmaster:
*
* echo 0 >/proc/sys/kernel/randomize_va_space
*
* This prevents using randomized stack and code addresses that cause the
* child process's memory map to be different from the parent's, making it
* sometimes impossible to attach to shared memory at the desired address.
* Return the setting to its old value (usually '1' or '2') when finished.
*/
if (strcmp(argv[1], "--forkbackend") == 0 ||
strcmp(argv[1], "--forkavlauncher") == 0 ||
@ -4710,9 +4723,6 @@ SubPostmasterMain(int argc, char *argv[])
{
Assert(argc == 3); /* shouldn't be any more args */
/* Close the postmaster's sockets */
ClosePostmasterPorts(false);
/*
* Need to reinitialize the SSL library in the backend, since the
* context structures contain function pointers and cannot be passed
@ -4743,17 +4753,7 @@ SubPostmasterMain(int argc, char *argv[])
/* Need a PGPROC to run CreateSharedMemoryAndSemaphores */
InitProcess();
/*
* Attach process to shared data structures. If testing EXEC_BACKEND
* on Linux, you must run this as root before starting the postmaster:
*
* echo 0 >/proc/sys/kernel/randomize_va_space
*
* This prevents a randomized stack base address that causes child
* shared memory to be at a different address than the parent, making
* it impossible to attached to shared memory. Return the value to
* '1' when finished.
*/
/* Attach process to shared data structures */
CreateSharedMemoryAndSemaphores(false, 0);
/* And run the backend */
@ -4761,9 +4761,6 @@ SubPostmasterMain(int argc, char *argv[])
}
if (strcmp(argv[1], "--forkboot") == 0)
{
/* Close the postmaster's sockets */
ClosePostmasterPorts(false);
/* Restore basic shared memory pointers */
InitShmemAccess(UsedShmemSegAddr);
@ -4777,9 +4774,6 @@ SubPostmasterMain(int argc, char *argv[])
}
if (strcmp(argv[1], "--forkavlauncher") == 0)
{
/* Close the postmaster's sockets */
ClosePostmasterPorts(false);
/* Restore basic shared memory pointers */
InitShmemAccess(UsedShmemSegAddr);
@ -4793,9 +4787,6 @@ SubPostmasterMain(int argc, char *argv[])
}
if (strcmp(argv[1], "--forkavworker") == 0)
{
/* Close the postmaster's sockets */
ClosePostmasterPorts(false);
/* Restore basic shared memory pointers */
InitShmemAccess(UsedShmemSegAddr);
@ -4814,9 +4805,6 @@ SubPostmasterMain(int argc, char *argv[])
/* do this as early as possible; in particular, before InitProcess() */
IsBackgroundWorker = true;
/* Close the postmaster's sockets */
ClosePostmasterPorts(false);
/* Restore basic shared memory pointers */
InitShmemAccess(UsedShmemSegAddr);
@ -4834,27 +4822,18 @@ SubPostmasterMain(int argc, char *argv[])
}
if (strcmp(argv[1], "--forkarch") == 0)
{
/* Close the postmaster's sockets */
ClosePostmasterPorts(false);
/* Do not want to attach to shared memory */
PgArchiverMain(argc, argv); /* does not return */
}
if (strcmp(argv[1], "--forkcol") == 0)
{
/* Close the postmaster's sockets */
ClosePostmasterPorts(false);
/* Do not want to attach to shared memory */
PgstatCollectorMain(argc, argv); /* does not return */
}
if (strcmp(argv[1], "--forklog") == 0)
{
/* Close the postmaster's sockets */
ClosePostmasterPorts(true);
/* Do not want to attach to shared memory */
SysLoggerMain(argc, argv); /* does not return */