From cc1ed40d57aa68322e43a7b0a3320a6c5aff010a Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Thu, 25 Nov 2010 11:48:49 -0500 Subject: [PATCH] Object access hook framework, with post-creation hook. After a SQL object is created, we provide an opportunity for security or logging plugins to get control; for example, a security label provider could use this to assign an initial security label to newly created objects. The basic infrastructure is (hopefully) reusable for other types of events that might require similar treatment. KaiGai Kohei, with minor adjustments. --- src/backend/catalog/heap.c | 4 ++ src/backend/catalog/pg_constraint.c | 4 ++ src/backend/catalog/pg_conversion.c | 5 +++ src/backend/catalog/pg_namespace.c | 4 ++ src/backend/catalog/pg_operator.c | 9 +++++ src/backend/catalog/pg_proc.c | 4 ++ src/backend/catalog/pg_type.c | 7 ++++ src/backend/commands/dbcommands.c | 4 ++ src/backend/commands/foreigncmds.c | 11 ++++++ src/backend/commands/functioncmds.c | 5 +++ src/backend/commands/opclasscmds.c | 9 +++++ src/backend/commands/proclang.c | 5 +++ src/backend/commands/tablecmds.c | 5 +++ src/backend/commands/tablespace.c | 5 +++ src/backend/commands/trigger.c | 5 +++ src/backend/commands/tsearchcmds.c | 14 +++++++ src/backend/commands/user.c | 4 ++ src/backend/rewrite/rewriteDefine.c | 5 +++ src/backend/storage/large_object/inv_api.c | 5 +++ src/backend/utils/init/globals.c | 7 ++++ src/include/catalog/objectaccess.h | 46 ++++++++++++++++++++++ 21 files changed, 167 insertions(+) create mode 100644 src/include/catalog/objectaccess.h diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index dcc53e13a1a..9b7668c133e 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -40,6 +40,7 @@ #include "catalog/index.h" #include "catalog/indexing.h" #include "catalog/namespace.h" +#include "catalog/objectaccess.h" #include "catalog/pg_attrdef.h" #include "catalog/pg_constraint.h" #include "catalog/pg_inherits.h" @@ -1188,6 +1189,9 @@ heap_create_with_catalog(const char *relname, } } + /* Post creation hook for new relation */ + InvokeObjectAccessHook(OAT_POST_CREATE, RelationRelationId, relid, 0); + /* * Store any supplied constraints and defaults. * diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c index 8b4f8c636fc..db0507b8c73 100644 --- a/src/backend/catalog/pg_constraint.c +++ b/src/backend/catalog/pg_constraint.c @@ -18,6 +18,7 @@ #include "access/heapam.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_constraint.h" #include "catalog/pg_operator.h" #include "catalog/pg_type.h" @@ -360,6 +361,9 @@ CreateConstraintEntry(const char *constraintName, DEPENDENCY_NORMAL); } + /* Post creation hook for new constraint */ + InvokeObjectAccessHook(OAT_POST_CREATE, ConstraintRelationId, conOid, 0); + return conOid; } diff --git a/src/backend/catalog/pg_conversion.c b/src/backend/catalog/pg_conversion.c index 957818403ff..5f1f1de4518 100644 --- a/src/backend/catalog/pg_conversion.c +++ b/src/backend/catalog/pg_conversion.c @@ -18,6 +18,7 @@ #include "access/sysattr.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_conversion.h" #include "catalog/pg_conversion_fn.h" #include "catalog/pg_namespace.h" @@ -131,6 +132,10 @@ ConversionCreate(const char *conname, Oid connamespace, recordDependencyOnOwner(ConversionRelationId, HeapTupleGetOid(tup), conowner); + /* Post creation hook for new conversion */ + InvokeObjectAccessHook(OAT_POST_CREATE, + ConversionRelationId, HeapTupleGetOid(tup), 0); + heap_freetuple(tup); heap_close(rel, RowExclusiveLock); diff --git a/src/backend/catalog/pg_namespace.c b/src/backend/catalog/pg_namespace.c index 71ebd7aa827..0387423d9fb 100644 --- a/src/backend/catalog/pg_namespace.c +++ b/src/backend/catalog/pg_namespace.c @@ -17,6 +17,7 @@ #include "access/heapam.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_namespace.h" #include "utils/builtins.h" #include "utils/rel.h" @@ -75,5 +76,8 @@ NamespaceCreate(const char *nspName, Oid ownerId) /* Record dependency on owner */ recordDependencyOnOwner(NamespaceRelationId, nspoid, ownerId); + /* Post creation hook for new schema */ + InvokeObjectAccessHook(OAT_POST_CREATE, NamespaceRelationId, nspoid, 0); + return nspoid; } diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c index 73de6725200..3e973743716 100644 --- a/src/backend/catalog/pg_operator.c +++ b/src/backend/catalog/pg_operator.c @@ -22,6 +22,7 @@ #include "catalog/dependency.h" #include "catalog/indexing.h" #include "catalog/namespace.h" +#include "catalog/objectaccess.h" #include "catalog/pg_namespace.h" #include "catalog/pg_operator.h" #include "catalog/pg_proc.h" @@ -273,6 +274,10 @@ OperatorShellMake(const char *operatorName, heap_freetuple(tup); + /* Post creation hook for new shell operator */ + InvokeObjectAccessHook(OAT_POST_CREATE, + OperatorRelationId, operatorObjectId, 0); + /* * Make sure the tuple is visible for subsequent lookups/updates. */ @@ -539,6 +544,10 @@ OperatorCreate(const char *operatorName, /* Add dependencies for the entry */ makeOperatorDependencies(tup); + /* Post creation hook for new operator */ + InvokeObjectAccessHook(OAT_POST_CREATE, + OperatorRelationId, operatorObjectId, 0); + heap_close(pg_operator_desc, RowExclusiveLock); /* diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index 34cd862d27e..d464979bc74 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -18,6 +18,7 @@ #include "access/xact.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_language.h" #include "catalog/pg_namespace.h" #include "catalog/pg_proc.h" @@ -616,6 +617,9 @@ ProcedureCreate(const char *procedureName, heap_freetuple(tup); + /* Post creation hook for new function */ + InvokeObjectAccessHook(OAT_POST_CREATE, ProcedureRelationId, retval, 0); + heap_close(rel, RowExclusiveLock); /* Verify function body */ diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index d7fccdf07b1..85368202d8d 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -18,6 +18,7 @@ #include "access/xact.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_namespace.h" #include "catalog/pg_proc.h" #include "catalog/pg_type.h" @@ -155,6 +156,9 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId) NULL, false); + /* Post creation hook for new shell type */ + InvokeObjectAccessHook(OAT_POST_CREATE, TypeRelationId, typoid, 0); + /* * clean up and return the type-oid */ @@ -455,6 +459,9 @@ TypeCreate(Oid newTypeOid, NULL), rebuildDeps); + /* Post creation hook for new type */ + InvokeObjectAccessHook(OAT_POST_CREATE, TypeRelationId, typeObjectId, 0); + /* * finish up */ diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 8cbd7548f97..09c6632a3b7 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -32,6 +32,7 @@ #include "catalog/catalog.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_authid.h" #include "catalog/pg_database.h" #include "catalog/pg_db_role_setting.h" @@ -572,6 +573,9 @@ createdb(const CreatedbStmt *stmt) /* Create pg_shdepend entries for objects within database */ copyTemplateDependencies(src_dboid, dboid); + /* Post creation hook for new database */ + InvokeObjectAccessHook(OAT_POST_CREATE, DatabaseRelationId, dboid, 0); + /* * Force a checkpoint before starting the copy. This will force dirty * buffers out to disk, to ensure source database is up-to-date on disk diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c index 4e6367c5268..71ba806851b 100644 --- a/src/backend/commands/foreigncmds.c +++ b/src/backend/commands/foreigncmds.c @@ -18,6 +18,7 @@ #include "catalog/catalog.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_foreign_data_wrapper.h" #include "catalog/pg_foreign_server.h" #include "catalog/pg_proc.h" @@ -415,6 +416,10 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt) recordDependencyOnOwner(ForeignDataWrapperRelationId, fdwId, ownerId); + /* Post creation hook for new foreign data wrapper */ + InvokeObjectAccessHook(OAT_POST_CREATE, + ForeignDataWrapperRelationId, fdwId, 0); + heap_close(rel, NoLock); } @@ -696,6 +701,9 @@ CreateForeignServer(CreateForeignServerStmt *stmt) recordDependencyOnOwner(ForeignServerRelationId, srvId, ownerId); + /* Post creation hook for new foreign server */ + InvokeObjectAccessHook(OAT_POST_CREATE, ForeignServerRelationId, srvId, 0); + heap_close(rel, NoLock); } @@ -967,6 +975,9 @@ CreateUserMapping(CreateUserMappingStmt *stmt) /* Record the mapped user dependency */ recordDependencyOnOwner(UserMappingRelationId, umId, useId); + /* Post creation hook for new user mapping */ + InvokeObjectAccessHook(OAT_POST_CREATE, UserMappingRelationId, umId, 0); + heap_close(rel, NoLock); } diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 62a21102512..2347cad6941 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -37,6 +37,7 @@ #include "access/sysattr.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_aggregate.h" #include "catalog/pg_cast.h" #include "catalog/pg_language.h" @@ -1761,6 +1762,10 @@ CreateCast(CreateCastStmt *stmt) recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); } + /* Post creation hook for new cast */ + InvokeObjectAccessHook(OAT_POST_CREATE, + CastRelationId, myself.objectId, 0); + heap_freetuple(tuple); heap_close(relation, RowExclusiveLock); diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c index 132c4ee1e53..5055fb17cde 100644 --- a/src/backend/commands/opclasscmds.c +++ b/src/backend/commands/opclasscmds.c @@ -22,6 +22,7 @@ #include "access/sysattr.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_amop.h" #include "catalog/pg_amproc.h" #include "catalog/pg_namespace.h" @@ -307,6 +308,10 @@ CreateOpFamily(char *amname, char *opfname, Oid namespaceoid, Oid amoid) /* dependency on owner */ recordDependencyOnOwner(OperatorFamilyRelationId, opfamilyoid, GetUserId()); + /* Post creation hook for new operator family */ + InvokeObjectAccessHook(OAT_POST_CREATE, + OperatorFamilyRelationId, opfamilyoid, 0); + heap_close(rel, RowExclusiveLock); return opfamilyoid; @@ -703,6 +708,10 @@ DefineOpClass(CreateOpClassStmt *stmt) /* dependency on owner */ recordDependencyOnOwner(OperatorClassRelationId, opclassoid, GetUserId()); + /* Post creation hook for new operator class */ + InvokeObjectAccessHook(OAT_POST_CREATE, + OperatorClassRelationId, opclassoid, 0); + heap_close(rel, RowExclusiveLock); } diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c index a2e653af80a..9d0d3b21546 100644 --- a/src/backend/commands/proclang.c +++ b/src/backend/commands/proclang.c @@ -17,6 +17,7 @@ #include "access/heapam.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_language.h" #include "catalog/pg_namespace.h" #include "catalog/pg_pltemplate.h" @@ -425,6 +426,10 @@ create_proc_lang(const char *languageName, bool replace, recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); } + /* Post creation hook for new procedural language */ + InvokeObjectAccessHook(OAT_POST_CREATE, + LanguageRelationId, myself.objectId, 0); + heap_close(rel, RowExclusiveLock); } diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index e8808e28c68..937992ba585 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -26,6 +26,7 @@ #include "catalog/index.h" #include "catalog/indexing.h" #include "catalog/namespace.h" +#include "catalog/objectaccess.h" #include "catalog/pg_constraint.h" #include "catalog/pg_depend.h" #include "catalog/pg_inherits.h" @@ -4080,6 +4081,10 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel, heap_freetuple(reltup); + /* Post creation hook for new attribute */ + InvokeObjectAccessHook(OAT_POST_CREATE, + RelationRelationId, myrelid, newattnum); + heap_close(pgclass, RowExclusiveLock); /* Make the attribute's catalog entry visible */ diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c index 305ac46b407..5ba0f1ca9da 100644 --- a/src/backend/commands/tablespace.c +++ b/src/backend/commands/tablespace.c @@ -59,6 +59,7 @@ #include "catalog/catalog.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_tablespace.h" #include "commands/comment.h" #include "commands/defrem.h" @@ -333,6 +334,10 @@ CreateTableSpace(CreateTableSpaceStmt *stmt) /* Record dependency on owner */ recordDependencyOnOwner(TableSpaceRelationId, tablespaceoid, ownerId); + /* Post creation hook for new tablespace */ + InvokeObjectAccessHook(OAT_POST_CREATE, + TableSpaceRelationId, tablespaceoid, 0); + create_tablespace_directories(location, tablespaceoid); /* Record the filesystem change in XLOG */ diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index d69fdcf410a..8195392f169 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -20,6 +20,7 @@ #include "catalog/catalog.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_constraint.h" #include "catalog/pg_proc.h" #include "catalog/pg_trigger.h" @@ -735,6 +736,10 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString, recordDependencyOnExpr(&myself, whenClause, whenRtable, DEPENDENCY_NORMAL); + /* Post creation hook for new trigger */ + InvokeObjectAccessHook(OAT_POST_CREATE, + TriggerRelationId, trigoid, 0); + /* Keep lock on target rel until end of xact */ heap_close(rel, NoLock); diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c index 73b8c9248b0..412b1d278d5 100644 --- a/src/backend/commands/tsearchcmds.c +++ b/src/backend/commands/tsearchcmds.c @@ -23,6 +23,7 @@ #include "catalog/dependency.h" #include "catalog/indexing.h" #include "catalog/namespace.h" +#include "catalog/objectaccess.h" #include "catalog/pg_namespace.h" #include "catalog/pg_proc.h" #include "catalog/pg_ts_config.h" @@ -263,6 +264,9 @@ DefineTSParser(List *names, List *parameters) makeParserDependencies(tup); + /* Post creation hook for new text search parser */ + InvokeObjectAccessHook(OAT_POST_CREATE, TSParserRelationId, prsOid, 0); + heap_freetuple(tup); heap_close(prsRel, RowExclusiveLock); @@ -563,6 +567,10 @@ DefineTSDictionary(List *names, List *parameters) makeDictionaryDependencies(tup); + /* Post creation hook for new text search dictionary */ + InvokeObjectAccessHook(OAT_POST_CREATE, + TSDictionaryRelationId, dictOid, 0); + heap_freetuple(tup); heap_close(dictRel, RowExclusiveLock); @@ -1050,6 +1058,9 @@ DefineTSTemplate(List *names, List *parameters) makeTSTemplateDependencies(tup); + /* Post creation hook for new text search template */ + InvokeObjectAccessHook(OAT_POST_CREATE, TSTemplateRelationId, dictOid, 0); + heap_freetuple(tup); heap_close(tmplRel, RowExclusiveLock); @@ -1440,6 +1451,9 @@ DefineTSConfiguration(List *names, List *parameters) makeConfigurationDependencies(tup, false, mapRel); + /* Post creation hook for new text search configuration */ + InvokeObjectAccessHook(OAT_POST_CREATE, TSConfigRelationId, cfgOid, 0); + heap_freetuple(tup); if (mapRel) diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index f1ff8398773..2634ca10e64 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -17,6 +17,7 @@ #include "access/xact.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_auth_members.h" #include "catalog/pg_authid.h" #include "catalog/pg_database.h" @@ -402,6 +403,9 @@ CreateRole(CreateRoleStmt *stmt) rolemembers, roleNamesToIds(rolemembers), GetUserId(), false); + /* Post creation hook for new role */ + InvokeObjectAccessHook(OAT_POST_CREATE, AuthIdRelationId, roleid, 0); + /* * Close pg_authid, but keep lock till commit. */ diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c index 029a2888a72..4354897981a 100644 --- a/src/backend/rewrite/rewriteDefine.c +++ b/src/backend/rewrite/rewriteDefine.c @@ -19,6 +19,7 @@ #include "catalog/dependency.h" #include "catalog/indexing.h" #include "catalog/namespace.h" +#include "catalog/objectaccess.h" #include "catalog/pg_rewrite.h" #include "catalog/storage.h" #include "miscadmin.h" @@ -177,6 +178,10 @@ InsertRule(char *rulname, DEPENDENCY_NORMAL); } + /* Post creation hook for new rule */ + InvokeObjectAccessHook(OAT_POST_CREATE, + RewriteRelationId, rewriteObjectId, 0); + heap_close(pg_rewrite_desc, RowExclusiveLock); return rewriteObjectId; diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c index e2faf95d935..686770cd45e 100644 --- a/src/backend/storage/large_object/inv_api.c +++ b/src/backend/storage/large_object/inv_api.c @@ -38,6 +38,7 @@ #include "catalog/catalog.h" #include "catalog/dependency.h" #include "catalog/indexing.h" +#include "catalog/objectaccess.h" #include "catalog/pg_largeobject.h" #include "catalog/pg_largeobject_metadata.h" #include "commands/comment.h" @@ -218,6 +219,10 @@ inv_create(Oid lobjId) recordDependencyOnOwner(LargeObjectRelationId, lobjId_new, GetUserId()); + /* Post creation hook for new large object */ + InvokeObjectAccessHook(OAT_POST_CREATE, + LargeObjectRelationId, lobjId_new, 0); + /* * Advance command counter to make new tuple visible to later operations. */ diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c index 9aa2c0a498f..5855fe46663 100644 --- a/src/backend/utils/init/globals.c +++ b/src/backend/utils/init/globals.c @@ -18,6 +18,7 @@ */ #include "postgres.h" +#include "catalog/objectaccess.h" #include "libpq/pqcomm.h" #include "miscadmin.h" #include "storage/backendid.h" @@ -117,3 +118,9 @@ int VacuumCostBalance = 0; /* working state for vacuum */ bool VacuumCostActive = false; int GinFuzzySearchLimit = 0; + +/* + * Hook on object accesses. This is intended as infrastructure for security + * and logging plugins. + */ +PGDLLIMPORT object_access_hook_type object_access_hook = NULL; diff --git a/src/include/catalog/objectaccess.h b/src/include/catalog/objectaccess.h new file mode 100644 index 00000000000..88508b0103e --- /dev/null +++ b/src/include/catalog/objectaccess.h @@ -0,0 +1,46 @@ +/* + * objectaccess.h + * + * Object access hooks. + * + * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + */ + +#ifndef OBJECTACCESS_H +#define OBJECTACCESS_H + +/* + * Object access hooks are intended to be called just before or just after + * performing certain actions on a SQL object. This is intended as + * infrastructure for security or logging pluggins. + * + * OAT_POST_CREATE should be invoked just after the the object is created. + * Typically, this is done after inserting the primary catalog records and + * associated dependencies. + * + * Other types may be added in the future. + */ +typedef enum ObjectAccessType +{ + OAT_POST_CREATE, +} ObjectAccessType; + +/* + * Hook, and a macro to invoke it. + */ + +typedef void (*object_access_hook_type)(ObjectAccessType access, + Oid classId, + Oid objectId, + int subId); + +extern PGDLLIMPORT object_access_hook_type object_access_hook; + +#define InvokeObjectAccessHook(access,classId,objectId,subId) \ + do { \ + if (object_access_hook) \ + (*object_access_hook)((access),(classId),(objectId),(subId)); \ + } while(0) + +#endif /* OBJECTACCESS_H */