Skip to content

Commit d368e1a

Browse files
committed
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
1 parent 843a490 commit d368e1a

File tree

3 files changed

+61
-12
lines changed

3 files changed

+61
-12
lines changed

src/backend/optimizer/util/clauses.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3726,6 +3726,10 @@ inline_function(Oid funcid, Oid result_type, List *args,
37263726
if (pg_proc_aclcheck(funcid, GetUserId(), ACL_EXECUTE) != ACLCHECK_OK)
37273727
return NULL;
37283728

3729+
/* Check whether a plugin wants to hook function entry/exit */
3730+
if (FmgrHookIsNeeded(funcid))
3731+
return NULL;
3732+
37293733
/*
37303734
* Make a temporary memory context, so that we don't leak all the stuff
37313735
* that parsing might create.
@@ -4158,6 +4162,10 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
41584162
if (pg_proc_aclcheck(func_oid, GetUserId(), ACL_EXECUTE) != ACLCHECK_OK)
41594163
return NULL;
41604164

4165+
/* Check whether a plugin wants to hook function entry/exit */
4166+
if (FmgrHookIsNeeded(func_oid))
4167+
return NULL;
4168+
41614169
/*
41624170
* OK, let's take a look at the function's pg_proc entry.
41634171
*/

src/backend/utils/fmgr/fmgr.c

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@
3030
#include "utils/lsyscache.h"
3131
#include "utils/syscache.h"
3232

33+
/*
34+
* Hooks for function calls
35+
*/
36+
PGDLLIMPORT needs_fmgr_hook_type needs_fmgr_hook = NULL;
37+
PGDLLIMPORT fmgr_hook_type fmgr_hook = NULL;
3338

3439
/*
3540
* 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,
216221
finfo->fn_retset = procedureStruct->proretset;
217222

218223
/*
219-
* If it has prosecdef set, or non-null proconfig, use
220-
* fmgr_security_definer call handler --- unless we are being called again
221-
* by fmgr_security_definer.
224+
* If it has prosecdef set, non-null proconfig, or if a plugin wants to
225+
* hook function entry/exit, use fmgr_security_definer call handler ---
226+
* unless we are being called again by fmgr_security_definer.
222227
*
223228
* When using fmgr_security_definer, function stats tracking is always
224229
* 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,
230235
*/
231236
if (!ignore_security &&
232237
(procedureStruct->prosecdef ||
233-
!heap_attisnull(procedureTuple, Anum_pg_proc_proconfig)))
238+
!heap_attisnull(procedureTuple, Anum_pg_proc_proconfig) ||
239+
FmgrHookIsNeeded(functionId)))
234240
{
235241
finfo->fn_addr = fmgr_security_definer;
236242
finfo->fn_stats = TRACK_FUNC_ALL; /* ie, never track */
@@ -857,17 +863,18 @@ struct fmgr_security_definer_cache
857863
FmgrInfo flinfo; /* lookup info for target function */
858864
Oid userid; /* userid to set, or InvalidOid */
859865
ArrayType *proconfig; /* GUC values to set, or NULL */
866+
Datum private; /* private usage for plugin modules */
860867
};
861868

862869
/*
863-
* Function handler for security-definer/proconfig functions. We extract the
864-
* OID of the actual function and do a fmgr lookup again. Then we fetch the
865-
* pg_proc row and copy the owner ID and proconfig fields. (All this info
866-
* is cached for the duration of the current query.) To execute a call,
867-
* we temporarily replace the flinfo with the cached/looked-up one, while
868-
* keeping the outer fcinfo (which contains all the actual arguments, etc.)
869-
* intact. This is not re-entrant, but then the fcinfo itself can't be used
870-
* re-entrantly anyway.
870+
* Function handler for security-definer/proconfig/plugin-hooked functions.
871+
* We extract the OID of the actual function and do a fmgr lookup again.
872+
* Then we fetch the pg_proc row and copy the owner ID and proconfig fields.
873+
* (All this info is cached for the duration of the current query.)
874+
* To execute a call, we temporarily replace the flinfo with the cached
875+
* and looked-up one, while keeping the outer fcinfo (which contains all
876+
* the actual arguments, etc.) intact. This is not re-entrant, but then
877+
* the fcinfo itself can't be used re-entrantly anyway.
871878
*/
872879
static Datum
873880
fmgr_security_definer(PG_FUNCTION_ARGS)
@@ -940,6 +947,10 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
940947
GUC_ACTION_SAVE);
941948
}
942949

950+
/* function manager hook */
951+
if (fmgr_hook)
952+
(*fmgr_hook)(FHET_START, &fcache->flinfo, &fcache->private);
953+
943954
/*
944955
* We don't need to restore GUC or userid settings on error, because the
945956
* ensuing xact or subxact abort will do that. The PG_TRY block is only
@@ -968,6 +979,8 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
968979
PG_CATCH();
969980
{
970981
fcinfo->flinfo = save_flinfo;
982+
if (fmgr_hook)
983+
(*fmgr_hook)(FHET_ABORT, &fcache->flinfo, &fcache->private);
971984
PG_RE_THROW();
972985
}
973986
PG_END_TRY();
@@ -978,6 +991,8 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
978991
AtEOXact_GUC(true, save_nestlevel);
979992
if (OidIsValid(fcache->userid))
980993
SetUserIdAndSecContext(save_userid, save_sec_context);
994+
if (fmgr_hook)
995+
(*fmgr_hook)(FHET_END, &fcache->flinfo, &fcache->private);
981996

982997
return result;
983998
}

src/include/fmgr.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,32 @@ extern void **find_rendezvous_variable(const char *varName);
544544
extern int AggCheckCallContext(FunctionCallInfo fcinfo,
545545
MemoryContext *aggcontext);
546546

547+
/*
548+
* We allow plugin modules to hook function entry/exit. This is intended
549+
* as support for loadable security policy modules, which may want to
550+
* perform additional privilege checks on function entry or exit, or to do
551+
* other internal bookkeeping. To make this possible, such modules must be
552+
* able not only to support normal function entry and exit, but also to trap
553+
* the case where we bail out due to an error; and they must also be able to
554+
* prevent inlining.
555+
*/
556+
typedef enum FmgrHookEventType
557+
{
558+
FHET_START,
559+
FHET_END,
560+
FHET_ABORT
561+
} FmgrHookEventType;
562+
563+
typedef bool (*needs_fmgr_hook_type)(Oid fn_oid);
564+
565+
typedef void (*fmgr_hook_type)(FmgrHookEventType event,
566+
FmgrInfo *flinfo, Datum *private);
567+
568+
extern PGDLLIMPORT needs_fmgr_hook_type needs_fmgr_hook;
569+
extern PGDLLIMPORT fmgr_hook_type fmgr_hook;
570+
571+
#define FmgrHookIsNeeded(fn_oid) \
572+
(!needs_fmgr_hook ? false : (*needs_fmgr_hook)(fn_oid))
547573

548574
/*
549575
* !!! OLD INTERFACE !!!

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy