1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-30 06:01:21 +03:00

Don't use bgw_main even to specify in-core bgworker entrypoints.

On EXEC_BACKEND builds, this can fail if ASLR is in use.

Backpatch to 9.5.  On master, completely remove the bgw_main field
completely, since there is no situation in which it is safe for an
EXEC_BACKEND build.  On 9.6 and 9.5, leave the field intact to avoid
breaking things for third-party code that doesn't care about working
under EXEC_BACKEND.  Prior to 9.5, there are no in-core bgworker
entrypoints.

Petr Jelinek, reviewed by me.

Discussion: http://postgr.es/m/09d8ad33-4287-a09b-a77f-77f8761adb5e@2ndquadrant.com
This commit is contained in:
Robert Haas
2017-03-31 20:35:51 -04:00
parent c281cd5fe1
commit 2113ac4cbb
8 changed files with 75 additions and 66 deletions

View File

@@ -110,7 +110,6 @@ static dlist_head pcxt_list = DLIST_STATIC_INIT(pcxt_list);
/* Private functions. */
static void HandleParallelMessage(ParallelContext *pcxt, int i, StringInfo msg);
static void ParallelExtensionTrampoline(dsm_segment *seg, shm_toc *toc);
static void ParallelWorkerMain(Datum main_arg);
static void WaitForParallelWorkersToExit(ParallelContext *pcxt);
@@ -458,7 +457,8 @@ LaunchParallelWorkers(ParallelContext *pcxt)
| BGWORKER_CLASS_PARALLEL;
worker.bgw_start_time = BgWorkerStart_ConsistentState;
worker.bgw_restart_time = BGW_NEVER_RESTART;
worker.bgw_main = ParallelWorkerMain;
sprintf(worker.bgw_library_name, "postgres");
sprintf(worker.bgw_function_name, "ParallelWorkerMain");
worker.bgw_main_arg = UInt32GetDatum(dsm_segment_handle(pcxt->seg));
worker.bgw_notify_pid = MyProcPid;
memset(&worker.bgw_extra, 0, BGW_EXTRALEN);
@@ -931,7 +931,7 @@ AtEOXact_Parallel(bool isCommit)
/*
* Main entrypoint for parallel workers.
*/
static void
void
ParallelWorkerMain(Datum main_arg)
{
dsm_segment *seg;

View File

@@ -15,12 +15,14 @@
#include <unistd.h>
#include "libpq/pqsignal.h"
#include "access/parallel.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "port/atomics.h"
#include "postmaster/bgworker_internals.h"
#include "postmaster/postmaster.h"
#include "replication/logicallauncher.h"
#include "replication/logicalworker.h"
#include "storage/dsm.h"
#include "storage/ipc.h"
#include "storage/latch.h"
@@ -109,14 +111,26 @@ struct BackgroundWorkerHandle
static BackgroundWorkerArray *BackgroundWorkerData;
/*
* List of workers that are allowed to be started outside of
* shared_preload_libraries.
* List of internal background workers. These are used for mapping the
* function name to actual function when building with EXEC_BACKEND and also
* to allow these to be loaded outside of shared_preload_libraries.
*/
static const bgworker_main_type InternalBGWorkers[] = {
ApplyLauncherMain,
NULL
typedef struct InternalBGWorkerMain
{
char *bgw_function_name;
bgworker_main_type bgw_main;
} InternalBGWorkerMain;
static const InternalBGWorkerMain InternalBGWorkers[] = {
{"ParallelWorkerMain", ParallelWorkerMain},
{"ApplyLauncherMain", ApplyLauncherMain},
{"ApplyWorkerMain", ApplyWorkerMain},
/* Dummy entry marking end of the array. */
{NULL, NULL}
};
static bgworker_main_type GetInternalBgWorkerMain(BackgroundWorker *worker);
/*
* Calculate shared memory needed.
*/
@@ -341,7 +355,6 @@ BackgroundWorkerStateChange(void)
rw->rw_worker.bgw_flags = slot->worker.bgw_flags;
rw->rw_worker.bgw_start_time = slot->worker.bgw_start_time;
rw->rw_worker.bgw_restart_time = slot->worker.bgw_restart_time;
rw->rw_worker.bgw_main = slot->worker.bgw_main;
rw->rw_worker.bgw_main_arg = slot->worker.bgw_main_arg;
memcpy(rw->rw_worker.bgw_extra, slot->worker.bgw_extra, BGW_EXTRALEN);
@@ -763,17 +776,14 @@ StartBackgroundWorker(void)
}
/*
* If bgw_main is set, we use that value as the initial entrypoint.
* However, if the library containing the entrypoint wasn't loaded at
* postmaster startup time, passing it as a direct function pointer is not
* possible. To work around that, we allow callers for whom a function
* pointer is not available to pass a library name (which will be loaded,
* if necessary) and a function name (which will be looked up in the named
* library).
* For internal workers set the entry point to known function address.
* Otherwise use the entry point specified by library name (which will
* be loaded, if necessary) and a function name (which will be looked up
* in the named library).
*/
if (worker->bgw_main != NULL)
entrypt = worker->bgw_main;
else
entrypt = GetInternalBgWorkerMain(worker);
if (entrypt == NULL)
entrypt = (bgworker_main_type)
load_external_function(worker->bgw_library_name,
worker->bgw_function_name,
@@ -806,23 +816,13 @@ RegisterBackgroundWorker(BackgroundWorker *worker)
{
RegisteredBgWorker *rw;
static int numworkers = 0;
bool internal = false;
int i;
if (!IsUnderPostmaster)
ereport(DEBUG1,
(errmsg("registering background worker \"%s\"", worker->bgw_name)));
for (i = 0; InternalBGWorkers[i]; i++)
{
if (worker->bgw_main == InternalBGWorkers[i])
{
internal = true;
break;
}
}
if (!process_shared_preload_libraries_in_progress && !internal)
if (!process_shared_preload_libraries_in_progress &&
GetInternalBgWorkerMain(worker) == NULL)
{
if (!IsUnderPostmaster)
ereport(LOG,
@@ -1152,3 +1152,28 @@ TerminateBackgroundWorker(BackgroundWorkerHandle *handle)
if (signal_postmaster)
SendPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE);
}
/*
* Search the known internal worker array and return its main function
* pointer if found.
*
* Returns NULL if not known internal worker.
*/
static bgworker_main_type
GetInternalBgWorkerMain(BackgroundWorker *worker)
{
int i;
/* Internal workers always have to use postgres as library name. */
if (strncmp(worker->bgw_library_name, "postgres", BGW_MAXLEN) != 0)
return NULL;
for (i = 0; InternalBGWorkers[i].bgw_function_name; i++)
{
if (strncmp(InternalBGWorkers[i].bgw_function_name,
worker->bgw_function_name, BGW_MAXLEN) == 0)
return InternalBGWorkers[i].bgw_main;
}
return NULL;
}

View File

@@ -295,7 +295,8 @@ logicalrep_worker_launch(Oid dbid, Oid subid, const char *subname, Oid userid,
bgw.bgw_flags = BGWORKER_SHMEM_ACCESS |
BGWORKER_BACKEND_DATABASE_CONNECTION;
bgw.bgw_start_time = BgWorkerStart_RecoveryFinished;
bgw.bgw_main = ApplyWorkerMain;
snprintf(bgw.bgw_library_name, BGW_MAXLEN, "postgres");
snprintf(bgw.bgw_function_name, BGW_MAXLEN, "ApplyWorkerMain");
if (OidIsValid(relid))
snprintf(bgw.bgw_name, BGW_MAXLEN,
"logical replication worker for subscription %u sync %u", subid, relid);
@@ -553,7 +554,8 @@ ApplyLauncherRegister(void)
bgw.bgw_flags = BGWORKER_SHMEM_ACCESS |
BGWORKER_BACKEND_DATABASE_CONNECTION;
bgw.bgw_start_time = BgWorkerStart_RecoveryFinished;
bgw.bgw_main = ApplyLauncherMain;
snprintf(bgw.bgw_library_name, BGW_MAXLEN, "postgres");
snprintf(bgw.bgw_function_name, BGW_MAXLEN, "ApplyLauncherMain");
snprintf(bgw.bgw_name, BGW_MAXLEN,
"logical replication launcher");
bgw.bgw_restart_time = 5;