aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/catalog/Makefile2
-rw-r--r--src/backend/catalog/aclchk.c149
-rw-r--r--src/backend/catalog/dependency.c46
3 files changed, 193 insertions, 4 deletions
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index 25130ecf124..1ce76100497 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -40,7 +40,7 @@ POSTGRES_BKI_SRCS = $(addprefix $(top_srcdir)/src/include/catalog/,\
pg_ts_parser.h pg_ts_template.h pg_extension.h \
pg_foreign_data_wrapper.h pg_foreign_server.h pg_user_mapping.h \
pg_foreign_table.h pg_policy.h pg_replication_origin.h \
- pg_default_acl.h pg_seclabel.h pg_shseclabel.h \
+ pg_default_acl.h pg_init_privs.h pg_seclabel.h pg_shseclabel.h \
pg_collation.h pg_range.h pg_transform.h \
toasting.h indexing.h \
)
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 0f3bc074e1f..ffb6678c6a4 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -35,6 +35,7 @@
#include "catalog/pg_extension.h"
#include "catalog/pg_foreign_data_wrapper.h"
#include "catalog/pg_foreign_server.h"
+#include "catalog/pg_init_privs.h"
#include "catalog/pg_language.h"
#include "catalog/pg_largeobject.h"
#include "catalog/pg_largeobject_metadata.h"
@@ -49,6 +50,7 @@
#include "catalog/pg_ts_dict.h"
#include "commands/dbcommands.h"
#include "commands/event_trigger.h"
+#include "commands/extension.h"
#include "commands/proclang.h"
#include "commands/tablespace.h"
#include "foreign/foreign.h"
@@ -119,6 +121,8 @@ static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions,
AttrNumber att_number, const char *colname);
static AclMode pg_aclmask(AclObjectKind objkind, Oid table_oid, AttrNumber attnum,
Oid roleid, AclMode mask, AclMaskHow how);
+static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid,
+ Acl *new_acl);
#ifdef ACLDEBUG
@@ -1678,6 +1682,10 @@ ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname,
/* keep the catalog indexes up to date */
CatalogUpdateIndexes(attRelation, newtuple);
+ /* Update initial privileges for extensions */
+ recordExtensionInitPriv(relOid, RelationRelationId, attnum,
+ ACL_NUM(new_acl) > 0 ? new_acl : NULL);
+
/* Update the shared dependency ACL info */
updateAclDependencies(RelationRelationId, relOid, attnum,
ownerId,
@@ -1939,6 +1947,9 @@ ExecGrant_Relation(InternalGrant *istmt)
/* keep the catalog indexes up to date */
CatalogUpdateIndexes(relation, newtuple);
+ /* Update initial privileges for extensions */
+ recordExtensionInitPriv(relOid, RelationRelationId, 0, new_acl);
+
/* Update the shared dependency ACL info */
updateAclDependencies(RelationRelationId, relOid, 0,
ownerId,
@@ -2254,6 +2265,10 @@ ExecGrant_Fdw(InternalGrant *istmt)
/* keep the catalog indexes up to date */
CatalogUpdateIndexes(relation, newtuple);
+ /* Update initial privileges for extensions */
+ recordExtensionInitPriv(fdwid, ForeignDataWrapperRelationId, 0,
+ new_acl);
+
/* Update the shared dependency ACL info */
updateAclDependencies(ForeignDataWrapperRelationId,
HeapTupleGetOid(tuple), 0,
@@ -2379,6 +2394,9 @@ ExecGrant_ForeignServer(InternalGrant *istmt)
/* keep the catalog indexes up to date */
CatalogUpdateIndexes(relation, newtuple);
+ /* Update initial privileges for extensions */
+ recordExtensionInitPriv(srvid, ForeignServerRelationId, 0, new_acl);
+
/* Update the shared dependency ACL info */
updateAclDependencies(ForeignServerRelationId,
HeapTupleGetOid(tuple), 0,
@@ -2503,6 +2521,9 @@ ExecGrant_Function(InternalGrant *istmt)
/* keep the catalog indexes up to date */
CatalogUpdateIndexes(relation, newtuple);
+ /* Update initial privileges for extensions */
+ recordExtensionInitPriv(funcId, ProcedureRelationId, 0, new_acl);
+
/* Update the shared dependency ACL info */
updateAclDependencies(ProcedureRelationId, funcId, 0,
ownerId,
@@ -2633,6 +2654,9 @@ ExecGrant_Language(InternalGrant *istmt)
/* keep the catalog indexes up to date */
CatalogUpdateIndexes(relation, newtuple);
+ /* Update initial privileges for extensions */
+ recordExtensionInitPriv(langId, LanguageRelationId, 0, new_acl);
+
/* Update the shared dependency ACL info */
updateAclDependencies(LanguageRelationId, HeapTupleGetOid(tuple), 0,
ownerId,
@@ -2772,6 +2796,9 @@ ExecGrant_Largeobject(InternalGrant *istmt)
/* keep the catalog indexes up to date */
CatalogUpdateIndexes(relation, newtuple);
+ /* Update initial privileges for extensions */
+ recordExtensionInitPriv(loid, LargeObjectRelationId, 0, new_acl);
+
/* Update the shared dependency ACL info */
updateAclDependencies(LargeObjectRelationId,
HeapTupleGetOid(tuple), 0,
@@ -2897,6 +2924,9 @@ ExecGrant_Namespace(InternalGrant *istmt)
/* keep the catalog indexes up to date */
CatalogUpdateIndexes(relation, newtuple);
+ /* Update initial privileges for extensions */
+ recordExtensionInitPriv(nspid, NamespaceRelationId, 0, new_acl);
+
/* Update the shared dependency ACL info */
updateAclDependencies(NamespaceRelationId, HeapTupleGetOid(tuple), 0,
ownerId,
@@ -3158,6 +3188,9 @@ ExecGrant_Type(InternalGrant *istmt)
/* keep the catalog indexes up to date */
CatalogUpdateIndexes(relation, newtuple);
+ /* Update initial privileges for extensions */
+ recordExtensionInitPriv(typId, TypeRelationId, 0, new_acl);
+
/* Update the shared dependency ACL info */
updateAclDependencies(TypeRelationId, typId, 0,
ownerId,
@@ -5174,3 +5207,119 @@ get_user_default_acl(GrantObjectType objtype, Oid ownerId, Oid nsp_oid)
return result;
}
+
+/*
+ * Record initial ACL for an extension object
+ *
+ * This will perform a wholesale replacement of the entire ACL for the object
+ * passed in, therefore be sure to pass in the complete new ACL to use.
+ *
+ * Can be called at any time, we check if 'creating_extension' is set and, if
+ * not, exit immediately.
+ *
+ * Pass in the object OID, the OID of the class (the OID of the table which
+ * the object is defined in) and the 'sub' id of the object (objsubid), if
+ * any. If there is no 'sub' id (they are currently only used for columns of
+ * tables) then pass in '0'. Finally, pass in the complete ACL to store.
+ *
+ * If an ACL already exists for this object/sub-object then we will replace
+ * it with what is passed in.
+ *
+ * Passing in NULL for 'new_acl' will result in the entry for the object being
+ * removed, if one is found.
+ */
+static void
+recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
+{
+ Relation relation;
+ ScanKeyData key[3];
+ SysScanDesc scan;
+ HeapTuple tuple;
+ HeapTuple oldtuple;
+
+ if (!creating_extension)
+ return;
+
+ relation = heap_open(InitPrivsRelationId, RowExclusiveLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_init_privs_objoid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objoid));
+ ScanKeyInit(&key[1],
+ Anum_pg_init_privs_classoid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(classoid));
+ ScanKeyInit(&key[2],
+ Anum_pg_init_privs_objsubid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(objsubid));
+
+ scan = systable_beginscan(relation, InitPrivsObjIndexId, true,
+ NULL, 3, key);
+
+ /* There should exist only one entry or none. */
+ oldtuple = systable_getnext(scan);
+
+ systable_endscan(scan);
+
+ /* If we find an entry, update it with the latest ACL. */
+ if (HeapTupleIsValid(oldtuple))
+ {
+ Datum values[Natts_pg_init_privs];
+ bool nulls[Natts_pg_init_privs];
+ bool replace[Natts_pg_init_privs];
+
+ /* If we have a new ACL to set, then update the row with it. */
+ if (new_acl)
+ {
+ MemSet(values, 0, sizeof(values));
+ MemSet(nulls, false, sizeof(nulls));
+ MemSet(replace, false, sizeof(replace));
+
+ values[Anum_pg_init_privs_privs - 1] = PointerGetDatum(new_acl);
+ replace[Anum_pg_init_privs_privs - 1] = true;
+
+ oldtuple = heap_modify_tuple(oldtuple, RelationGetDescr(relation),
+ values, nulls, replace);
+
+ simple_heap_update(relation, &oldtuple->t_self, oldtuple);
+
+ /* keep the catalog indexes up to date */
+ CatalogUpdateIndexes(relation, oldtuple);
+ }
+ else
+ /* new_acl is NULL, so delete the entry we found. */
+ simple_heap_delete(relation, &oldtuple->t_self);
+ }
+ else
+ {
+ /* No entry found, so add it. */
+ Datum values[Natts_pg_init_privs];
+ bool nulls[Natts_pg_init_privs];
+
+ MemSet(nulls, false, sizeof(nulls));
+
+ values[Anum_pg_init_privs_objoid - 1] = ObjectIdGetDatum(objoid);
+ values[Anum_pg_init_privs_classoid - 1] = ObjectIdGetDatum(classoid);
+ values[Anum_pg_init_privs_objsubid - 1] = Int32GetDatum(objsubid);
+
+ /* This function only handles initial privileges of extensions */
+ values[Anum_pg_init_privs_privtype - 1] =
+ CharGetDatum(INITPRIVS_EXTENSION);
+
+ values[Anum_pg_init_privs_privs - 1] = PointerGetDatum(new_acl);
+
+ tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
+
+ simple_heap_insert(relation, tuple);
+
+ /* keep the catalog indexes up to date */
+ CatalogUpdateIndexes(relation, tuple);
+ }
+
+ /* prevent error when processing objects multiple times */
+ CommandCounterIncrement();
+
+ heap_close(relation, RowExclusiveLock);
+}
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index 79595a9d230..a6180a64f21 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -39,6 +39,7 @@
#include "catalog/pg_extension.h"
#include "catalog/pg_foreign_data_wrapper.h"
#include "catalog/pg_foreign_server.h"
+#include "catalog/pg_init_privs.h"
#include "catalog/pg_language.h"
#include "catalog/pg_largeobject.h"
#include "catalog/pg_namespace.h"
@@ -196,6 +197,7 @@ static bool object_address_present_add_flags(const ObjectAddress *object,
static bool stack_address_present_add_flags(const ObjectAddress *object,
int flags,
ObjectAddressStack *stack);
+static void DeleteInitPrivs(const ObjectAddress *object);
/*
@@ -1106,12 +1108,13 @@ deleteOneObject(const ObjectAddress *object, Relation *depRel, int flags)
/*
- * Delete any comments or security labels associated with this object.
- * (This is a convenient place to do these things, rather than having
- * every object type know to do it.)
+ * Delete any comments, security labels, or initial privileges associated
+ * with this object. (This is a convenient place to do these things,
+ * rather than having every object type know to do it.)
*/
DeleteComments(object->objectId, object->classId, object->objectSubId);
DeleteSecurityLabel(object);
+ DeleteInitPrivs(object);
/*
* CommandCounterIncrement here to ensure that preceding changes are all
@@ -2432,3 +2435,40 @@ getObjectClass(const ObjectAddress *object)
elog(ERROR, "unrecognized object class: %u", object->classId);
return OCLASS_CLASS; /* keep compiler quiet */
}
+
+/*
+ * delete initial ACL for extension objects
+ */
+static void
+DeleteInitPrivs(const ObjectAddress *object)
+{
+ Relation relation;
+ ScanKeyData key[3];
+ SysScanDesc scan;
+ HeapTuple oldtuple;
+
+ relation = heap_open(InitPrivsRelationId, RowExclusiveLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_init_privs_objoid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->objectId));
+ ScanKeyInit(&key[1],
+ Anum_pg_init_privs_classoid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->classId));
+ ScanKeyInit(&key[2],
+ Anum_pg_init_privs_objsubid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(object->objectSubId));
+
+ scan = systable_beginscan(relation, InitPrivsObjIndexId, true,
+ NULL, 3, key);
+
+ while (HeapTupleIsValid(oldtuple = systable_getnext(scan)))
+ simple_heap_delete(relation, &oldtuple->t_self);
+
+ systable_endscan(scan);
+
+ heap_close(relation, RowExclusiveLock);
+}