1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-29 23:43:17 +03:00

Allow plugins to suppress inlining and hook function entry/exit/abort.

This is intended as infrastructure to allow an eventual SE-Linux plugin to
support trusted procedures.

KaiGai Kohei
This commit is contained in:
Robert Haas
2010-12-13 18:58:31 -05:00
parent 843a490f0a
commit d368e1a2a7
3 changed files with 61 additions and 12 deletions

View File

@@ -30,6 +30,11 @@
#include "utils/lsyscache.h"
#include "utils/syscache.h"
/*
* Hooks for function calls
*/
PGDLLIMPORT needs_fmgr_hook_type needs_fmgr_hook = NULL;
PGDLLIMPORT fmgr_hook_type fmgr_hook = NULL;
/*
* Declaration for old-style function pointer type. This is now used only
@@ -216,9 +221,9 @@ fmgr_info_cxt_security(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt,
finfo->fn_retset = procedureStruct->proretset;
/*
* If it has prosecdef set, or non-null proconfig, use
* fmgr_security_definer call handler --- unless we are being called again
* by fmgr_security_definer.
* If it has prosecdef set, non-null proconfig, or if a plugin wants to
* hook function entry/exit, use fmgr_security_definer call handler ---
* unless we are being called again by fmgr_security_definer.
*
* When using fmgr_security_definer, function stats tracking is always
* disabled at the outer level, and instead we set the flag properly in
@@ -230,7 +235,8 @@ fmgr_info_cxt_security(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt,
*/
if (!ignore_security &&
(procedureStruct->prosecdef ||
!heap_attisnull(procedureTuple, Anum_pg_proc_proconfig)))
!heap_attisnull(procedureTuple, Anum_pg_proc_proconfig) ||
FmgrHookIsNeeded(functionId)))
{
finfo->fn_addr = fmgr_security_definer;
finfo->fn_stats = TRACK_FUNC_ALL; /* ie, never track */
@@ -857,17 +863,18 @@ struct fmgr_security_definer_cache
FmgrInfo flinfo; /* lookup info for target function */
Oid userid; /* userid to set, or InvalidOid */
ArrayType *proconfig; /* GUC values to set, or NULL */
Datum private; /* private usage for plugin modules */
};
/*
* Function handler for security-definer/proconfig functions. We extract the
* OID of the actual function and do a fmgr lookup again. Then we fetch the
* pg_proc row and copy the owner ID and proconfig fields. (All this info
* is cached for the duration of the current query.) To execute a call,
* we temporarily replace the flinfo with the cached/looked-up one, while
* keeping the outer fcinfo (which contains all the actual arguments, etc.)
* intact. This is not re-entrant, but then the fcinfo itself can't be used
* re-entrantly anyway.
* Function handler for security-definer/proconfig/plugin-hooked functions.
* We extract the OID of the actual function and do a fmgr lookup again.
* Then we fetch the pg_proc row and copy the owner ID and proconfig fields.
* (All this info is cached for the duration of the current query.)
* To execute a call, we temporarily replace the flinfo with the cached
* and looked-up one, while keeping the outer fcinfo (which contains all
* the actual arguments, etc.) intact. This is not re-entrant, but then
* the fcinfo itself can't be used re-entrantly anyway.
*/
static Datum
fmgr_security_definer(PG_FUNCTION_ARGS)
@@ -940,6 +947,10 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
GUC_ACTION_SAVE);
}
/* function manager hook */
if (fmgr_hook)
(*fmgr_hook)(FHET_START, &fcache->flinfo, &fcache->private);
/*
* We don't need to restore GUC or userid settings on error, because the
* ensuing xact or subxact abort will do that. The PG_TRY block is only
@@ -968,6 +979,8 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
PG_CATCH();
{
fcinfo->flinfo = save_flinfo;
if (fmgr_hook)
(*fmgr_hook)(FHET_ABORT, &fcache->flinfo, &fcache->private);
PG_RE_THROW();
}
PG_END_TRY();
@@ -978,6 +991,8 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
AtEOXact_GUC(true, save_nestlevel);
if (OidIsValid(fcache->userid))
SetUserIdAndSecContext(save_userid, save_sec_context);
if (fmgr_hook)
(*fmgr_hook)(FHET_END, &fcache->flinfo, &fcache->private);
return result;
}