diff options
author | Robert Haas <rhaas@postgresql.org> | 2017-03-31 20:35:51 -0400 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2017-03-31 20:50:31 -0400 |
commit | 0ef26bb394abedb2745bd838c26ecb3131682bda (patch) | |
tree | 5980b908346fc3c53e89f047111aa140e51c8755 /src | |
parent | 86f0e538955ebacf6b79655807b635ca23ed6d28 (diff) | |
download | postgresql-0ef26bb394abedb2745bd838c26ecb3131682bda.tar.gz postgresql-0ef26bb394abedb2745bd838c26ecb3131682bda.zip |
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
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/access/transam/parallel.c | 7 | ||||
-rw-r--r-- | src/backend/postmaster/bgworker.c | 76 | ||||
-rw-r--r-- | src/include/access/parallel.h | 2 | ||||
-rw-r--r-- | src/test/modules/worker_spi/worker_spi.c | 6 |
4 files changed, 73 insertions, 18 deletions
diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/transam/parallel.c index 3a6047f76ae..bf2fbd69982 100644 --- a/src/backend/access/transam/parallel.c +++ b/src/backend/access/transam/parallel.c @@ -106,7 +106,6 @@ static dlist_head pcxt_list = DLIST_STATIC_INIT(pcxt_list); static void HandleParallelMessage(ParallelContext *pcxt, int i, StringInfo msg); static void ParallelErrorContext(void *arg); static void ParallelExtensionTrampoline(dsm_segment *seg, shm_toc *toc); -static void ParallelWorkerMain(Datum main_arg); /* @@ -401,7 +400,9 @@ LaunchParallelWorkers(ParallelContext *pcxt) BGWORKER_SHMEM_ACCESS | BGWORKER_BACKEND_DATABASE_CONNECTION; worker.bgw_start_time = BgWorkerStart_ConsistentState; worker.bgw_restart_time = BGW_NEVER_RESTART; - worker.bgw_main = ParallelWorkerMain; + worker.bgw_main = NULL; + 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); @@ -834,7 +835,7 @@ AtEOXact_Parallel(bool isCommit) /* * Main entrypoint for parallel workers. */ -static void +void ParallelWorkerMain(Datum main_arg) { dsm_segment *seg; diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index e32eb3e6669..8b524a24255 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -16,6 +16,7 @@ #include "miscadmin.h" #include "libpq/pqsignal.h" +#include "access/parallel.h" #include "postmaster/bgworker_internals.h" #include "postmaster/postmaster.h" #include "storage/barrier.h" @@ -94,6 +95,25 @@ struct BackgroundWorkerHandle static BackgroundWorkerArray *BackgroundWorkerData; /* + * 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. + */ +typedef struct InternalBGWorkerMain +{ + char *bgw_function_name; + bgworker_main_type bgw_main; +} InternalBGWorkerMain; + +static const InternalBGWorkerMain InternalBGWorkers[] = { + {"ParallelWorkerMain", ParallelWorkerMain}, + /* Dummy entry marking end of the array. */ + {NULL, NULL} +}; + +static bgworker_main_type GetInternalBgWorkerMain(BackgroundWorker *worker); + +/* * Calculate shared memory needed. */ Size @@ -695,22 +715,27 @@ StartBackgroundWorker(void) #endif } + /* For internal workers set the entry point to known function address. */ + entrypt = GetInternalBgWorkerMain(worker); + /* - * 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 + * Otherwise, if bgw_main is set, we use that value as the initial + * entrypoint. This does not work well EXEC_BACKEND outside Windows but + * we keep the logic for backwards compatibility. In other cases 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 = (bgworker_main_type) - load_external_function(worker->bgw_library_name, - worker->bgw_function_name, - true, NULL); + if (entrypt == NULL) + { + if (worker->bgw_main != NULL) + entrypt = worker->bgw_main; + else + entrypt = (bgworker_main_type) + load_external_function(worker->bgw_library_name, + worker->bgw_function_name, + true, NULL); + } /* * Note that in normal processes, we would call InitPostgres here. For a @@ -1078,3 +1103,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; +} diff --git a/src/include/access/parallel.h b/src/include/access/parallel.h index 4ac46fce57a..0651d1f208e 100644 --- a/src/include/access/parallel.h +++ b/src/include/access/parallel.h @@ -65,4 +65,6 @@ extern void AtEOXact_Parallel(bool isCommit); extern void AtEOSubXact_Parallel(bool isCommit, SubTransactionId mySubId); extern void ParallelWorkerReportLastRecEnd(XLogRecPtr last_xlog_end); +extern void ParallelWorkerMain(Datum main_arg); + #endif /* PARALLEL_H */ diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c index 7c655f90211..1b131854109 100644 --- a/src/test/modules/worker_spi/worker_spi.c +++ b/src/test/modules/worker_spi/worker_spi.c @@ -346,7 +346,9 @@ _PG_init(void) BGWORKER_BACKEND_DATABASE_CONNECTION; worker.bgw_start_time = BgWorkerStart_RecoveryFinished; worker.bgw_restart_time = BGW_NEVER_RESTART; - worker.bgw_main = worker_spi_main; + worker.bgw_main = NULL; + sprintf(worker.bgw_library_name, "worker_spi"); + sprintf(worker.bgw_function_name, "worker_spi_main"); worker.bgw_notify_pid = 0; /* @@ -377,7 +379,7 @@ worker_spi_launch(PG_FUNCTION_ARGS) BGWORKER_BACKEND_DATABASE_CONNECTION; worker.bgw_start_time = BgWorkerStart_RecoveryFinished; worker.bgw_restart_time = BGW_NEVER_RESTART; - worker.bgw_main = NULL; /* new worker might not have library loaded */ + worker.bgw_main = NULL; sprintf(worker.bgw_library_name, "worker_spi"); sprintf(worker.bgw_function_name, "worker_spi_main"); snprintf(worker.bgw_name, BGW_MAXLEN, "worker %d", i); |