Commit 07d1edb9 authored by Robert Haas's avatar Robert Haas

Extend object access hook framework to support arguments, and DROP.

This allows loadable modules to get control at drop time, perhaps for the
purpose of performing additional security checks or to log the event.
The initial purpose of this code is to support sepgsql, but other
applications should be possible as well.

KaiGai Kohei, reviewed by me.
parent b1495393
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "catalog/heap.h" #include "catalog/heap.h"
#include "catalog/index.h" #include "catalog/index.h"
#include "catalog/namespace.h" #include "catalog/namespace.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_amop.h" #include "catalog/pg_amop.h"
#include "catalog/pg_amproc.h" #include "catalog/pg_amproc.h"
#include "catalog/pg_attrdef.h" #include "catalog/pg_attrdef.h"
...@@ -991,6 +992,15 @@ deleteOneObject(const ObjectAddress *object, Relation depRel, int flags) ...@@ -991,6 +992,15 @@ deleteOneObject(const ObjectAddress *object, Relation depRel, int flags)
SysScanDesc scan; SysScanDesc scan;
HeapTuple tup; HeapTuple tup;
/* DROP hook of the objects being removed */
if (object_access_hook)
{
ObjectAccessDrop drop_arg;
drop_arg.dropflags = flags;
InvokeObjectAccessHook(OAT_DROP, object->classId, object->objectId,
object->objectSubId, &drop_arg);
}
/* /*
* First remove any pg_depend records that link from this object to * First remove any pg_depend records that link from this object to
* others. (Any records linking to this object should be gone already.) * others. (Any records linking to this object should be gone already.)
......
...@@ -1286,7 +1286,8 @@ heap_create_with_catalog(const char *relname, ...@@ -1286,7 +1286,8 @@ heap_create_with_catalog(const char *relname,
} }
/* Post creation hook for new relation */ /* Post creation hook for new relation */
InvokeObjectAccessHook(OAT_POST_CREATE, RelationRelationId, relid, 0); InvokeObjectAccessHook(OAT_POST_CREATE,
RelationRelationId, relid, 0, NULL);
/* /*
* Store any supplied constraints and defaults. * Store any supplied constraints and defaults.
......
...@@ -136,7 +136,7 @@ CollationCreate(const char *collname, Oid collnamespace, ...@@ -136,7 +136,7 @@ CollationCreate(const char *collname, Oid collnamespace,
/* Post creation hook for new collation */ /* Post creation hook for new collation */
InvokeObjectAccessHook(OAT_POST_CREATE, InvokeObjectAccessHook(OAT_POST_CREATE,
CollationRelationId, oid, 0); CollationRelationId, oid, 0, NULL);
heap_freetuple(tup); heap_freetuple(tup);
heap_close(rel, RowExclusiveLock); heap_close(rel, RowExclusiveLock);
......
...@@ -366,7 +366,8 @@ CreateConstraintEntry(const char *constraintName, ...@@ -366,7 +366,8 @@ CreateConstraintEntry(const char *constraintName,
} }
/* Post creation hook for new constraint */ /* Post creation hook for new constraint */
InvokeObjectAccessHook(OAT_POST_CREATE, ConstraintRelationId, conOid, 0); InvokeObjectAccessHook(OAT_POST_CREATE,
ConstraintRelationId, conOid, 0, NULL);
return conOid; return conOid;
} }
......
...@@ -134,8 +134,8 @@ ConversionCreate(const char *conname, Oid connamespace, ...@@ -134,8 +134,8 @@ ConversionCreate(const char *conname, Oid connamespace,
recordDependencyOnCurrentExtension(&myself, false); recordDependencyOnCurrentExtension(&myself, false);
/* Post creation hook for new conversion */ /* Post creation hook for new conversion */
InvokeObjectAccessHook(OAT_POST_CREATE, InvokeObjectAccessHook(OAT_POST_CREATE, ConversionRelationId,
ConversionRelationId, HeapTupleGetOid(tup), 0); HeapTupleGetOid(tup), 0, NULL);
heap_freetuple(tup); heap_freetuple(tup);
heap_close(rel, RowExclusiveLock); heap_close(rel, RowExclusiveLock);
......
...@@ -95,7 +95,8 @@ NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp) ...@@ -95,7 +95,8 @@ NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp)
recordDependencyOnCurrentExtension(&myself, false); recordDependencyOnCurrentExtension(&myself, false);
/* Post creation hook for new schema */ /* Post creation hook for new schema */
InvokeObjectAccessHook(OAT_POST_CREATE, NamespaceRelationId, nspoid, 0); InvokeObjectAccessHook(OAT_POST_CREATE,
NamespaceRelationId, nspoid, 0, NULL);
return nspoid; return nspoid;
} }
...@@ -275,7 +275,7 @@ OperatorShellMake(const char *operatorName, ...@@ -275,7 +275,7 @@ OperatorShellMake(const char *operatorName,
/* Post creation hook for new shell operator */ /* Post creation hook for new shell operator */
InvokeObjectAccessHook(OAT_POST_CREATE, InvokeObjectAccessHook(OAT_POST_CREATE,
OperatorRelationId, operatorObjectId, 0); OperatorRelationId, operatorObjectId, 0, NULL);
/* /*
* Make sure the tuple is visible for subsequent lookups/updates. * Make sure the tuple is visible for subsequent lookups/updates.
...@@ -544,7 +544,7 @@ OperatorCreate(const char *operatorName, ...@@ -544,7 +544,7 @@ OperatorCreate(const char *operatorName,
/* Post creation hook for new operator */ /* Post creation hook for new operator */
InvokeObjectAccessHook(OAT_POST_CREATE, InvokeObjectAccessHook(OAT_POST_CREATE,
OperatorRelationId, operatorObjectId, 0); OperatorRelationId, operatorObjectId, 0, NULL);
heap_close(pg_operator_desc, RowExclusiveLock); heap_close(pg_operator_desc, RowExclusiveLock);
......
...@@ -655,7 +655,8 @@ ProcedureCreate(const char *procedureName, ...@@ -655,7 +655,8 @@ ProcedureCreate(const char *procedureName,
heap_freetuple(tup); heap_freetuple(tup);
/* Post creation hook for new function */ /* Post creation hook for new function */
InvokeObjectAccessHook(OAT_POST_CREATE, ProcedureRelationId, retval, 0); InvokeObjectAccessHook(OAT_POST_CREATE,
ProcedureRelationId, retval, 0, NULL);
heap_close(rel, RowExclusiveLock); heap_close(rel, RowExclusiveLock);
......
...@@ -162,7 +162,8 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId) ...@@ -162,7 +162,8 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
false); false);
/* Post creation hook for new shell type */ /* Post creation hook for new shell type */
InvokeObjectAccessHook(OAT_POST_CREATE, TypeRelationId, typoid, 0); InvokeObjectAccessHook(OAT_POST_CREATE,
TypeRelationId, typoid, 0, NULL);
/* /*
* clean up and return the type-oid * clean up and return the type-oid
...@@ -474,7 +475,8 @@ TypeCreate(Oid newTypeOid, ...@@ -474,7 +475,8 @@ TypeCreate(Oid newTypeOid,
rebuildDeps); rebuildDeps);
/* Post creation hook for new type */ /* Post creation hook for new type */
InvokeObjectAccessHook(OAT_POST_CREATE, TypeRelationId, typeObjectId, 0); InvokeObjectAccessHook(OAT_POST_CREATE,
TypeRelationId, typeObjectId, 0, NULL);
/* /*
* finish up * finish up
......
...@@ -515,7 +515,8 @@ createdb(const CreatedbStmt *stmt) ...@@ -515,7 +515,8 @@ createdb(const CreatedbStmt *stmt)
copyTemplateDependencies(src_dboid, dboid); copyTemplateDependencies(src_dboid, dboid);
/* Post creation hook for new database */ /* Post creation hook for new database */
InvokeObjectAccessHook(OAT_POST_CREATE, DatabaseRelationId, dboid, 0); InvokeObjectAccessHook(OAT_POST_CREATE,
DatabaseRelationId, dboid, 0, NULL);
/* /*
* Force a checkpoint before starting the copy. This will force dirty * Force a checkpoint before starting the copy. This will force dirty
...@@ -777,6 +778,15 @@ dropdb(const char *dbname, bool missing_ok) ...@@ -777,6 +778,15 @@ dropdb(const char *dbname, bool missing_ok)
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE, aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
dbname); dbname);
/* DROP hook for the database being removed */
if (object_access_hook)
{
ObjectAccessDrop drop_arg;
memset(&drop_arg, 0, sizeof(ObjectAccessDrop));
InvokeObjectAccessHook(OAT_DROP,
DatabaseRelationId, db_id, 0, &drop_arg);
}
/* /*
* Disallow dropping a DB that is marked istemplate. This is just to * Disallow dropping a DB that is marked istemplate. This is just to
* prevent people from accidentally dropping template0 or template1; they * prevent people from accidentally dropping template0 or template1; they
......
...@@ -1558,7 +1558,7 @@ InsertExtensionTuple(const char *extName, Oid extOwner, ...@@ -1558,7 +1558,7 @@ InsertExtensionTuple(const char *extName, Oid extOwner,
} }
/* Post creation hook for new extension */ /* Post creation hook for new extension */
InvokeObjectAccessHook(OAT_POST_CREATE, InvokeObjectAccessHook(OAT_POST_CREATE,
ExtensionRelationId, extensionOid, 0); ExtensionRelationId, extensionOid, 0, NULL);
return extensionOid; return extensionOid;
} }
......
...@@ -666,7 +666,7 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt) ...@@ -666,7 +666,7 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
/* Post creation hook for new foreign data wrapper */ /* Post creation hook for new foreign data wrapper */
InvokeObjectAccessHook(OAT_POST_CREATE, InvokeObjectAccessHook(OAT_POST_CREATE,
ForeignDataWrapperRelationId, fdwId, 0); ForeignDataWrapperRelationId, fdwId, 0, NULL);
heap_close(rel, RowExclusiveLock); heap_close(rel, RowExclusiveLock);
} }
...@@ -962,7 +962,8 @@ CreateForeignServer(CreateForeignServerStmt *stmt) ...@@ -962,7 +962,8 @@ CreateForeignServer(CreateForeignServerStmt *stmt)
recordDependencyOnCurrentExtension(&myself, false); recordDependencyOnCurrentExtension(&myself, false);
/* Post creation hook for new foreign server */ /* Post creation hook for new foreign server */
InvokeObjectAccessHook(OAT_POST_CREATE, ForeignServerRelationId, srvId, 0); InvokeObjectAccessHook(OAT_POST_CREATE,
ForeignServerRelationId, srvId, 0, NULL);
heap_close(rel, RowExclusiveLock); heap_close(rel, RowExclusiveLock);
} }
...@@ -1202,7 +1203,8 @@ CreateUserMapping(CreateUserMappingStmt *stmt) ...@@ -1202,7 +1203,8 @@ CreateUserMapping(CreateUserMappingStmt *stmt)
recordDependencyOnCurrentExtension(&myself, false); recordDependencyOnCurrentExtension(&myself, false);
/* Post creation hook for new user mapping */ /* Post creation hook for new user mapping */
InvokeObjectAccessHook(OAT_POST_CREATE, UserMappingRelationId, umId, 0); InvokeObjectAccessHook(OAT_POST_CREATE,
UserMappingRelationId, umId, 0, NULL);
heap_close(rel, RowExclusiveLock); heap_close(rel, RowExclusiveLock);
} }
......
...@@ -1759,7 +1759,8 @@ CreateCast(CreateCastStmt *stmt) ...@@ -1759,7 +1759,8 @@ CreateCast(CreateCastStmt *stmt)
recordDependencyOnCurrentExtension(&myself, false); recordDependencyOnCurrentExtension(&myself, false);
/* Post creation hook for new cast */ /* Post creation hook for new cast */
InvokeObjectAccessHook(OAT_POST_CREATE, CastRelationId, castid, 0); InvokeObjectAccessHook(OAT_POST_CREATE,
CastRelationId, castid, 0, NULL);
heap_freetuple(tuple); heap_freetuple(tuple);
......
...@@ -314,7 +314,7 @@ CreateOpFamily(char *amname, char *opfname, Oid namespaceoid, Oid amoid) ...@@ -314,7 +314,7 @@ CreateOpFamily(char *amname, char *opfname, Oid namespaceoid, Oid amoid)
/* Post creation hook for new operator family */ /* Post creation hook for new operator family */
InvokeObjectAccessHook(OAT_POST_CREATE, InvokeObjectAccessHook(OAT_POST_CREATE,
OperatorFamilyRelationId, opfamilyoid, 0); OperatorFamilyRelationId, opfamilyoid, 0, NULL);
heap_close(rel, RowExclusiveLock); heap_close(rel, RowExclusiveLock);
...@@ -717,7 +717,7 @@ DefineOpClass(CreateOpClassStmt *stmt) ...@@ -717,7 +717,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
/* Post creation hook for new operator class */ /* Post creation hook for new operator class */
InvokeObjectAccessHook(OAT_POST_CREATE, InvokeObjectAccessHook(OAT_POST_CREATE,
OperatorClassRelationId, opclassoid, 0); OperatorClassRelationId, opclassoid, 0, NULL);
heap_close(rel, RowExclusiveLock); heap_close(rel, RowExclusiveLock);
} }
......
...@@ -428,7 +428,7 @@ create_proc_lang(const char *languageName, bool replace, ...@@ -428,7 +428,7 @@ create_proc_lang(const char *languageName, bool replace,
/* Post creation hook for new procedural language */ /* Post creation hook for new procedural language */
InvokeObjectAccessHook(OAT_POST_CREATE, InvokeObjectAccessHook(OAT_POST_CREATE,
LanguageRelationId, myself.objectId, 0); LanguageRelationId, myself.objectId, 0, NULL);
heap_close(rel, RowExclusiveLock); heap_close(rel, RowExclusiveLock);
} }
......
...@@ -4382,7 +4382,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, ...@@ -4382,7 +4382,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
/* Post creation hook for new attribute */ /* Post creation hook for new attribute */
InvokeObjectAccessHook(OAT_POST_CREATE, InvokeObjectAccessHook(OAT_POST_CREATE,
RelationRelationId, myrelid, newattnum); RelationRelationId, myrelid, newattnum, NULL);
heap_close(pgclass, RowExclusiveLock); heap_close(pgclass, RowExclusiveLock);
......
...@@ -330,7 +330,7 @@ CreateTableSpace(CreateTableSpaceStmt *stmt) ...@@ -330,7 +330,7 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
/* Post creation hook for new tablespace */ /* Post creation hook for new tablespace */
InvokeObjectAccessHook(OAT_POST_CREATE, InvokeObjectAccessHook(OAT_POST_CREATE,
TableSpaceRelationId, tablespaceoid, 0); TableSpaceRelationId, tablespaceoid, 0, NULL);
create_tablespace_directories(location, tablespaceoid); create_tablespace_directories(location, tablespaceoid);
...@@ -434,6 +434,15 @@ DropTableSpace(DropTableSpaceStmt *stmt) ...@@ -434,6 +434,15 @@ DropTableSpace(DropTableSpaceStmt *stmt)
aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_TABLESPACE, aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_TABLESPACE,
tablespacename); tablespacename);
/* DROP hook for the tablespace being removed */
if (object_access_hook)
{
ObjectAccessDrop drop_arg;
memset(&drop_arg, 0, sizeof(ObjectAccessDrop));
InvokeObjectAccessHook(OAT_DROP, TableSpaceRelationId,
tablespaceoid, 0, &drop_arg);
}
/* /*
* Remove the pg_tablespace tuple (this will roll back if we fail below) * Remove the pg_tablespace tuple (this will roll back if we fail below)
*/ */
......
...@@ -756,7 +756,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString, ...@@ -756,7 +756,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
/* Post creation hook for new trigger */ /* Post creation hook for new trigger */
InvokeObjectAccessHook(OAT_POST_CREATE, InvokeObjectAccessHook(OAT_POST_CREATE,
TriggerRelationId, trigoid, 0); TriggerRelationId, trigoid, 0, NULL);
/* Keep lock on target rel until end of xact */ /* Keep lock on target rel until end of xact */
heap_close(rel, NoLock); heap_close(rel, NoLock);
......
...@@ -271,7 +271,8 @@ DefineTSParser(List *names, List *parameters) ...@@ -271,7 +271,8 @@ DefineTSParser(List *names, List *parameters)
makeParserDependencies(tup); makeParserDependencies(tup);
/* Post creation hook for new text search parser */ /* Post creation hook for new text search parser */
InvokeObjectAccessHook(OAT_POST_CREATE, TSParserRelationId, prsOid, 0); InvokeObjectAccessHook(OAT_POST_CREATE,
TSParserRelationId, prsOid, 0, NULL);
heap_freetuple(tup); heap_freetuple(tup);
...@@ -565,7 +566,7 @@ DefineTSDictionary(List *names, List *parameters) ...@@ -565,7 +566,7 @@ DefineTSDictionary(List *names, List *parameters)
/* Post creation hook for new text search dictionary */ /* Post creation hook for new text search dictionary */
InvokeObjectAccessHook(OAT_POST_CREATE, InvokeObjectAccessHook(OAT_POST_CREATE,
TSDictionaryRelationId, dictOid, 0); TSDictionaryRelationId, dictOid, 0, NULL);
heap_freetuple(tup); heap_freetuple(tup);
...@@ -1036,7 +1037,8 @@ DefineTSTemplate(List *names, List *parameters) ...@@ -1036,7 +1037,8 @@ DefineTSTemplate(List *names, List *parameters)
makeTSTemplateDependencies(tup); makeTSTemplateDependencies(tup);
/* Post creation hook for new text search template */ /* Post creation hook for new text search template */
InvokeObjectAccessHook(OAT_POST_CREATE, TSTemplateRelationId, dictOid, 0); InvokeObjectAccessHook(OAT_POST_CREATE,
TSTemplateRelationId, dictOid, 0, NULL);
heap_freetuple(tup); heap_freetuple(tup);
...@@ -1419,7 +1421,8 @@ DefineTSConfiguration(List *names, List *parameters) ...@@ -1419,7 +1421,8 @@ DefineTSConfiguration(List *names, List *parameters)
makeConfigurationDependencies(tup, false, mapRel); makeConfigurationDependencies(tup, false, mapRel);
/* Post creation hook for new text search configuration */ /* Post creation hook for new text search configuration */
InvokeObjectAccessHook(OAT_POST_CREATE, TSConfigRelationId, cfgOid, 0); InvokeObjectAccessHook(OAT_POST_CREATE,
TSConfigRelationId, cfgOid, 0, NULL);
heap_freetuple(tup); heap_freetuple(tup);
......
...@@ -425,7 +425,8 @@ CreateRole(CreateRoleStmt *stmt) ...@@ -425,7 +425,8 @@ CreateRole(CreateRoleStmt *stmt)
GetUserId(), false); GetUserId(), false);
/* Post creation hook for new role */ /* Post creation hook for new role */
InvokeObjectAccessHook(OAT_POST_CREATE, AuthIdRelationId, roleid, 0); InvokeObjectAccessHook(OAT_POST_CREATE,
AuthIdRelationId, roleid, 0, NULL);
/* /*
* Close pg_authid, but keep lock till commit. * Close pg_authid, but keep lock till commit.
...@@ -932,6 +933,15 @@ DropRole(DropRoleStmt *stmt) ...@@ -932,6 +933,15 @@ DropRole(DropRoleStmt *stmt)
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to drop superusers"))); errmsg("must be superuser to drop superusers")));
/* DROP hook for the role being removed */
if (object_access_hook)
{
ObjectAccessDrop drop_arg;
memset(&drop_arg, 0, sizeof(ObjectAccessDrop));
InvokeObjectAccessHook(OAT_DROP,
AuthIdRelationId, roleid, 0, &drop_arg);
}
/* /*
* Lock the role, so nobody can add dependencies to her while we drop * Lock the role, so nobody can add dependencies to her while we drop
* her. We keep the lock until the end of transaction. * her. We keep the lock until the end of transaction.
......
...@@ -178,7 +178,7 @@ InsertRule(char *rulname, ...@@ -178,7 +178,7 @@ InsertRule(char *rulname,
/* Post creation hook for new rule */ /* Post creation hook for new rule */
InvokeObjectAccessHook(OAT_POST_CREATE, InvokeObjectAccessHook(OAT_POST_CREATE,
RewriteRelationId, rewriteObjectId, 0); RewriteRelationId, rewriteObjectId, 0, NULL);
heap_close(pg_rewrite_desc, RowExclusiveLock); heap_close(pg_rewrite_desc, RowExclusiveLock);
......
...@@ -217,7 +217,7 @@ inv_create(Oid lobjId) ...@@ -217,7 +217,7 @@ inv_create(Oid lobjId)
/* Post creation hook for new large object */ /* Post creation hook for new large object */
InvokeObjectAccessHook(OAT_POST_CREATE, InvokeObjectAccessHook(OAT_POST_CREATE,
LargeObjectRelationId, lobjId_new, 0); LargeObjectRelationId, lobjId_new, 0, NULL);
/* /*
* Advance command counter to make new tuple visible to later operations. * Advance command counter to make new tuple visible to later operations.
......
...@@ -19,28 +19,45 @@ ...@@ -19,28 +19,45 @@
* Typically, this is done after inserting the primary catalog records and * Typically, this is done after inserting the primary catalog records and
* associated dependencies. * associated dependencies.
* *
* OAT_DROP should be invoked just before deletion of objects; typically
* deleteOneObject(). Its arguments are packed within ObjectAccessDrop.
*
* Other types may be added in the future. * Other types may be added in the future.
*/ */
typedef enum ObjectAccessType typedef enum ObjectAccessType
{ {
OAT_POST_CREATE, OAT_POST_CREATE,
OAT_DROP,
} ObjectAccessType; } ObjectAccessType;
/* /*
* Hook, and a macro to invoke it. * Arguments of OAT_DROP event
*/
typedef struct
{
/*
* Flags to inform extensions the context of this deletion.
* Also see PERFORM_DELETION_* in dependency.h
*/ */
int dropflags;
} ObjectAccessDrop;
/*
* Hook, and a macro to invoke it.
*/
typedef void (*object_access_hook_type) (ObjectAccessType access, typedef void (*object_access_hook_type) (ObjectAccessType access,
Oid classId, Oid classId,
Oid objectId, Oid objectId,
int subId); int subId,
void *arg);
extern PGDLLIMPORT object_access_hook_type object_access_hook; extern PGDLLIMPORT object_access_hook_type object_access_hook;
#define InvokeObjectAccessHook(access,classId,objectId,subId) \ #define InvokeObjectAccessHook(access,classId,objectId,subId,arg) \
do { \ do { \
if (object_access_hook) \ if (object_access_hook) \
(*object_access_hook)((access),(classId),(objectId),(subId)); \ (*object_access_hook)((access),(classId), \
(objectId),(subId),(arg)); \
} while(0) } while(0)
#endif /* OBJECTACCESS_H */ #endif /* OBJECTACCESS_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment