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:
parent
843a490f0a
commit
d368e1a2a7
@ -3726,6 +3726,10 @@ inline_function(Oid funcid, Oid result_type, List *args,
|
||||
if (pg_proc_aclcheck(funcid, GetUserId(), ACL_EXECUTE) != ACLCHECK_OK)
|
||||
return NULL;
|
||||
|
||||
/* Check whether a plugin wants to hook function entry/exit */
|
||||
if (FmgrHookIsNeeded(funcid))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Make a temporary memory context, so that we don't leak all the stuff
|
||||
* that parsing might create.
|
||||
@ -4158,6 +4162,10 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
|
||||
if (pg_proc_aclcheck(func_oid, GetUserId(), ACL_EXECUTE) != ACLCHECK_OK)
|
||||
return NULL;
|
||||
|
||||
/* Check whether a plugin wants to hook function entry/exit */
|
||||
if (FmgrHookIsNeeded(func_oid))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* OK, let's take a look at the function's pg_proc entry.
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -544,6 +544,32 @@ extern void **find_rendezvous_variable(const char *varName);
|
||||
extern int AggCheckCallContext(FunctionCallInfo fcinfo,
|
||||
MemoryContext *aggcontext);
|
||||
|
||||
/*
|
||||
* We allow plugin modules to hook function entry/exit. This is intended
|
||||
* as support for loadable security policy modules, which may want to
|
||||
* perform additional privilege checks on function entry or exit, or to do
|
||||
* other internal bookkeeping. To make this possible, such modules must be
|
||||
* able not only to support normal function entry and exit, but also to trap
|
||||
* the case where we bail out due to an error; and they must also be able to
|
||||
* prevent inlining.
|
||||
*/
|
||||
typedef enum FmgrHookEventType
|
||||
{
|
||||
FHET_START,
|
||||
FHET_END,
|
||||
FHET_ABORT
|
||||
} FmgrHookEventType;
|
||||
|
||||
typedef bool (*needs_fmgr_hook_type)(Oid fn_oid);
|
||||
|
||||
typedef void (*fmgr_hook_type)(FmgrHookEventType event,
|
||||
FmgrInfo *flinfo, Datum *private);
|
||||
|
||||
extern PGDLLIMPORT needs_fmgr_hook_type needs_fmgr_hook;
|
||||
extern PGDLLIMPORT fmgr_hook_type fmgr_hook;
|
||||
|
||||
#define FmgrHookIsNeeded(fn_oid) \
|
||||
(!needs_fmgr_hook ? false : (*needs_fmgr_hook)(fn_oid))
|
||||
|
||||
/*
|
||||
* !!! OLD INTERFACE !!!
|
||||
|
Loading…
x
Reference in New Issue
Block a user