mirror of
https://github.com/postgres/postgres.git
synced 2025-04-22 23:02:54 +03:00
Add new catalog called pg_init_privs
This new catalog holds the privileges which the system was initialized with at initdb time, along with any permissions set by extensions at CREATE EXTENSION time. This allows pg_dump (and any other similar use-cases) to detect when the privileges set on initdb-created or extension-created objects have been changed from what they were set to at initdb/extension-creation time and handle those changes appropriately. Reviews by Alexander Korotkov, Jose Luis Tallon
This commit is contained in:
parent
0b62fd036e
commit
6c268df127
@ -178,6 +178,11 @@
|
|||||||
<entry>table inheritance hierarchy</entry>
|
<entry>table inheritance hierarchy</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><link linkend="catalog-pg-init-privs"><structname>pg_init_privs</structname></link></entry>
|
||||||
|
<entry>object initial privileges</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry><link linkend="catalog-pg-language"><structname>pg_language</structname></link></entry>
|
<entry><link linkend="catalog-pg-language"><structname>pg_language</structname></link></entry>
|
||||||
<entry>languages for writing functions</entry>
|
<entry>languages for writing functions</entry>
|
||||||
@ -3785,6 +3790,109 @@
|
|||||||
|
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="catalog-pg-init-privs">
|
||||||
|
<title><structname>pg_init_privs</structname></title>
|
||||||
|
|
||||||
|
<indexterm zone="catalog-pg-init-privs">
|
||||||
|
<primary>pg_init_privs</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The catalog <structname>pg_init_privs</> records information about
|
||||||
|
the initial privileges of objects in the system. There is one entry
|
||||||
|
for each object in the database which has a non-default (non-NULL)
|
||||||
|
initial set of privileges.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Objects can have initial privileges either by having those privileges set
|
||||||
|
when the system is initialized (by <application>initdb</>) or when the
|
||||||
|
object is created during a <command>CREATE EXTENSION</command> and the
|
||||||
|
extension script sets initial privileges using the <command>GRANT</command>
|
||||||
|
system. Note that the system will automatically handle recording of the
|
||||||
|
privileges during the extension script and that extension authors need
|
||||||
|
only use the <command>GRANT</command> and <command>REVOKE</command>
|
||||||
|
statements in their script to have the privileges recorded. The
|
||||||
|
<literal>privtype</literal> column indicates if the initial privilege was
|
||||||
|
set by <application>initdb</> or during a
|
||||||
|
<command>CREATE EXTENSION</command> command.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Objects which have initial privileges set by <application>initdb</> will
|
||||||
|
have entries where <literal>privtype</literal> is
|
||||||
|
<literal>'i'</literal>, while objects which have initial privileges set
|
||||||
|
by <command>CREATE EXTENSION</command> will have entries where
|
||||||
|
<literal>privtype</literal> is <literal>'e'</literal>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<title><structname>pg_inherits</> Columns</title>
|
||||||
|
|
||||||
|
<tgroup cols="4">
|
||||||
|
<thead>
|
||||||
|
<row>
|
||||||
|
<entry>Name</entry>
|
||||||
|
<entry>Type</entry>
|
||||||
|
<entry>References</entry>
|
||||||
|
<entry>Description</entry>
|
||||||
|
</row>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
<row>
|
||||||
|
<entry><structfield>objoid</structfield></entry>
|
||||||
|
<entry><type>oid</type></entry>
|
||||||
|
<entry>any OID column</entry>
|
||||||
|
<entry>The OID of the specific object</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><structfield>classoid</structfield></entry>
|
||||||
|
<entry><type>oid</type></entry>
|
||||||
|
<entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry>
|
||||||
|
<entry>The OID of the system catalog the object is in</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><structfield>objsubid</structfield></entry>
|
||||||
|
<entry><type>int4</type></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry>
|
||||||
|
For a table column, this is the column number (the
|
||||||
|
<structfield>objoid</> and <structfield>classoid</> refer to the
|
||||||
|
table itself). For all other object types, this column is
|
||||||
|
zero.
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><structfield>privtype</structfield></entry>
|
||||||
|
<entry><type>char</type></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry>
|
||||||
|
A code defining the type of initial privilege of this object; see text
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><structfield>initprivs</structfield></entry>
|
||||||
|
<entry><type>aclitem[]</type></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry>
|
||||||
|
The initial access privileges; see
|
||||||
|
<xref linkend="sql-grant"> and
|
||||||
|
<xref linkend="sql-revoke">
|
||||||
|
for details
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</tgroup>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
|
||||||
<sect1 id="catalog-pg-language">
|
<sect1 id="catalog-pg-language">
|
||||||
<title><structname>pg_language</structname></title>
|
<title><structname>pg_language</structname></title>
|
||||||
|
@ -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_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_data_wrapper.h pg_foreign_server.h pg_user_mapping.h \
|
||||||
pg_foreign_table.h pg_policy.h pg_replication_origin.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 \
|
pg_collation.h pg_range.h pg_transform.h \
|
||||||
toasting.h indexing.h \
|
toasting.h indexing.h \
|
||||||
)
|
)
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include "catalog/pg_extension.h"
|
#include "catalog/pg_extension.h"
|
||||||
#include "catalog/pg_foreign_data_wrapper.h"
|
#include "catalog/pg_foreign_data_wrapper.h"
|
||||||
#include "catalog/pg_foreign_server.h"
|
#include "catalog/pg_foreign_server.h"
|
||||||
|
#include "catalog/pg_init_privs.h"
|
||||||
#include "catalog/pg_language.h"
|
#include "catalog/pg_language.h"
|
||||||
#include "catalog/pg_largeobject.h"
|
#include "catalog/pg_largeobject.h"
|
||||||
#include "catalog/pg_largeobject_metadata.h"
|
#include "catalog/pg_largeobject_metadata.h"
|
||||||
@ -49,6 +50,7 @@
|
|||||||
#include "catalog/pg_ts_dict.h"
|
#include "catalog/pg_ts_dict.h"
|
||||||
#include "commands/dbcommands.h"
|
#include "commands/dbcommands.h"
|
||||||
#include "commands/event_trigger.h"
|
#include "commands/event_trigger.h"
|
||||||
|
#include "commands/extension.h"
|
||||||
#include "commands/proclang.h"
|
#include "commands/proclang.h"
|
||||||
#include "commands/tablespace.h"
|
#include "commands/tablespace.h"
|
||||||
#include "foreign/foreign.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);
|
AttrNumber att_number, const char *colname);
|
||||||
static AclMode pg_aclmask(AclObjectKind objkind, Oid table_oid, AttrNumber attnum,
|
static AclMode pg_aclmask(AclObjectKind objkind, Oid table_oid, AttrNumber attnum,
|
||||||
Oid roleid, AclMode mask, AclMaskHow how);
|
Oid roleid, AclMode mask, AclMaskHow how);
|
||||||
|
static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid,
|
||||||
|
Acl *new_acl);
|
||||||
|
|
||||||
|
|
||||||
#ifdef ACLDEBUG
|
#ifdef ACLDEBUG
|
||||||
@ -1678,6 +1682,10 @@ ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname,
|
|||||||
/* keep the catalog indexes up to date */
|
/* keep the catalog indexes up to date */
|
||||||
CatalogUpdateIndexes(attRelation, newtuple);
|
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 */
|
/* Update the shared dependency ACL info */
|
||||||
updateAclDependencies(RelationRelationId, relOid, attnum,
|
updateAclDependencies(RelationRelationId, relOid, attnum,
|
||||||
ownerId,
|
ownerId,
|
||||||
@ -1939,6 +1947,9 @@ ExecGrant_Relation(InternalGrant *istmt)
|
|||||||
/* keep the catalog indexes up to date */
|
/* keep the catalog indexes up to date */
|
||||||
CatalogUpdateIndexes(relation, newtuple);
|
CatalogUpdateIndexes(relation, newtuple);
|
||||||
|
|
||||||
|
/* Update initial privileges for extensions */
|
||||||
|
recordExtensionInitPriv(relOid, RelationRelationId, 0, new_acl);
|
||||||
|
|
||||||
/* Update the shared dependency ACL info */
|
/* Update the shared dependency ACL info */
|
||||||
updateAclDependencies(RelationRelationId, relOid, 0,
|
updateAclDependencies(RelationRelationId, relOid, 0,
|
||||||
ownerId,
|
ownerId,
|
||||||
@ -2254,6 +2265,10 @@ ExecGrant_Fdw(InternalGrant *istmt)
|
|||||||
/* keep the catalog indexes up to date */
|
/* keep the catalog indexes up to date */
|
||||||
CatalogUpdateIndexes(relation, newtuple);
|
CatalogUpdateIndexes(relation, newtuple);
|
||||||
|
|
||||||
|
/* Update initial privileges for extensions */
|
||||||
|
recordExtensionInitPriv(fdwid, ForeignDataWrapperRelationId, 0,
|
||||||
|
new_acl);
|
||||||
|
|
||||||
/* Update the shared dependency ACL info */
|
/* Update the shared dependency ACL info */
|
||||||
updateAclDependencies(ForeignDataWrapperRelationId,
|
updateAclDependencies(ForeignDataWrapperRelationId,
|
||||||
HeapTupleGetOid(tuple), 0,
|
HeapTupleGetOid(tuple), 0,
|
||||||
@ -2379,6 +2394,9 @@ ExecGrant_ForeignServer(InternalGrant *istmt)
|
|||||||
/* keep the catalog indexes up to date */
|
/* keep the catalog indexes up to date */
|
||||||
CatalogUpdateIndexes(relation, newtuple);
|
CatalogUpdateIndexes(relation, newtuple);
|
||||||
|
|
||||||
|
/* Update initial privileges for extensions */
|
||||||
|
recordExtensionInitPriv(srvid, ForeignServerRelationId, 0, new_acl);
|
||||||
|
|
||||||
/* Update the shared dependency ACL info */
|
/* Update the shared dependency ACL info */
|
||||||
updateAclDependencies(ForeignServerRelationId,
|
updateAclDependencies(ForeignServerRelationId,
|
||||||
HeapTupleGetOid(tuple), 0,
|
HeapTupleGetOid(tuple), 0,
|
||||||
@ -2503,6 +2521,9 @@ ExecGrant_Function(InternalGrant *istmt)
|
|||||||
/* keep the catalog indexes up to date */
|
/* keep the catalog indexes up to date */
|
||||||
CatalogUpdateIndexes(relation, newtuple);
|
CatalogUpdateIndexes(relation, newtuple);
|
||||||
|
|
||||||
|
/* Update initial privileges for extensions */
|
||||||
|
recordExtensionInitPriv(funcId, ProcedureRelationId, 0, new_acl);
|
||||||
|
|
||||||
/* Update the shared dependency ACL info */
|
/* Update the shared dependency ACL info */
|
||||||
updateAclDependencies(ProcedureRelationId, funcId, 0,
|
updateAclDependencies(ProcedureRelationId, funcId, 0,
|
||||||
ownerId,
|
ownerId,
|
||||||
@ -2633,6 +2654,9 @@ ExecGrant_Language(InternalGrant *istmt)
|
|||||||
/* keep the catalog indexes up to date */
|
/* keep the catalog indexes up to date */
|
||||||
CatalogUpdateIndexes(relation, newtuple);
|
CatalogUpdateIndexes(relation, newtuple);
|
||||||
|
|
||||||
|
/* Update initial privileges for extensions */
|
||||||
|
recordExtensionInitPriv(langId, LanguageRelationId, 0, new_acl);
|
||||||
|
|
||||||
/* Update the shared dependency ACL info */
|
/* Update the shared dependency ACL info */
|
||||||
updateAclDependencies(LanguageRelationId, HeapTupleGetOid(tuple), 0,
|
updateAclDependencies(LanguageRelationId, HeapTupleGetOid(tuple), 0,
|
||||||
ownerId,
|
ownerId,
|
||||||
@ -2772,6 +2796,9 @@ ExecGrant_Largeobject(InternalGrant *istmt)
|
|||||||
/* keep the catalog indexes up to date */
|
/* keep the catalog indexes up to date */
|
||||||
CatalogUpdateIndexes(relation, newtuple);
|
CatalogUpdateIndexes(relation, newtuple);
|
||||||
|
|
||||||
|
/* Update initial privileges for extensions */
|
||||||
|
recordExtensionInitPriv(loid, LargeObjectRelationId, 0, new_acl);
|
||||||
|
|
||||||
/* Update the shared dependency ACL info */
|
/* Update the shared dependency ACL info */
|
||||||
updateAclDependencies(LargeObjectRelationId,
|
updateAclDependencies(LargeObjectRelationId,
|
||||||
HeapTupleGetOid(tuple), 0,
|
HeapTupleGetOid(tuple), 0,
|
||||||
@ -2897,6 +2924,9 @@ ExecGrant_Namespace(InternalGrant *istmt)
|
|||||||
/* keep the catalog indexes up to date */
|
/* keep the catalog indexes up to date */
|
||||||
CatalogUpdateIndexes(relation, newtuple);
|
CatalogUpdateIndexes(relation, newtuple);
|
||||||
|
|
||||||
|
/* Update initial privileges for extensions */
|
||||||
|
recordExtensionInitPriv(nspid, NamespaceRelationId, 0, new_acl);
|
||||||
|
|
||||||
/* Update the shared dependency ACL info */
|
/* Update the shared dependency ACL info */
|
||||||
updateAclDependencies(NamespaceRelationId, HeapTupleGetOid(tuple), 0,
|
updateAclDependencies(NamespaceRelationId, HeapTupleGetOid(tuple), 0,
|
||||||
ownerId,
|
ownerId,
|
||||||
@ -3158,6 +3188,9 @@ ExecGrant_Type(InternalGrant *istmt)
|
|||||||
/* keep the catalog indexes up to date */
|
/* keep the catalog indexes up to date */
|
||||||
CatalogUpdateIndexes(relation, newtuple);
|
CatalogUpdateIndexes(relation, newtuple);
|
||||||
|
|
||||||
|
/* Update initial privileges for extensions */
|
||||||
|
recordExtensionInitPriv(typId, TypeRelationId, 0, new_acl);
|
||||||
|
|
||||||
/* Update the shared dependency ACL info */
|
/* Update the shared dependency ACL info */
|
||||||
updateAclDependencies(TypeRelationId, typId, 0,
|
updateAclDependencies(TypeRelationId, typId, 0,
|
||||||
ownerId,
|
ownerId,
|
||||||
@ -5174,3 +5207,119 @@ get_user_default_acl(GrantObjectType objtype, Oid ownerId, Oid nsp_oid)
|
|||||||
|
|
||||||
return result;
|
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);
|
||||||
|
}
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include "catalog/pg_extension.h"
|
#include "catalog/pg_extension.h"
|
||||||
#include "catalog/pg_foreign_data_wrapper.h"
|
#include "catalog/pg_foreign_data_wrapper.h"
|
||||||
#include "catalog/pg_foreign_server.h"
|
#include "catalog/pg_foreign_server.h"
|
||||||
|
#include "catalog/pg_init_privs.h"
|
||||||
#include "catalog/pg_language.h"
|
#include "catalog/pg_language.h"
|
||||||
#include "catalog/pg_largeobject.h"
|
#include "catalog/pg_largeobject.h"
|
||||||
#include "catalog/pg_namespace.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,
|
static bool stack_address_present_add_flags(const ObjectAddress *object,
|
||||||
int flags,
|
int flags,
|
||||||
ObjectAddressStack *stack);
|
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.
|
* Delete any comments, security labels, or initial privileges associated
|
||||||
* (This is a convenient place to do these things, rather than having
|
* with this object. (This is a convenient place to do these things,
|
||||||
* every object type know to do it.)
|
* rather than having every object type know to do it.)
|
||||||
*/
|
*/
|
||||||
DeleteComments(object->objectId, object->classId, object->objectSubId);
|
DeleteComments(object->objectId, object->classId, object->objectSubId);
|
||||||
DeleteSecurityLabel(object);
|
DeleteSecurityLabel(object);
|
||||||
|
DeleteInitPrivs(object);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CommandCounterIncrement here to ensure that preceding changes are all
|
* 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);
|
elog(ERROR, "unrecognized object class: %u", object->classId);
|
||||||
return OCLASS_CLASS; /* keep compiler quiet */
|
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);
|
||||||
|
}
|
||||||
|
@ -1989,6 +1989,11 @@ setup_dictionary(FILE *cmdfd)
|
|||||||
* Some objects may require different permissions by default, so we
|
* Some objects may require different permissions by default, so we
|
||||||
* make sure we don't overwrite privilege sets that have already been
|
* make sure we don't overwrite privilege sets that have already been
|
||||||
* set (NOT NULL).
|
* set (NOT NULL).
|
||||||
|
*
|
||||||
|
* Also populate pg_init_privs to save what the privileges are at init
|
||||||
|
* time. This is used by pg_dump to allow users to change privileges
|
||||||
|
* on catalog objects and to have those privilege changes preserved
|
||||||
|
* across dump/reload and pg_upgrade.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
setup_privileges(FILE *cmdfd)
|
setup_privileges(FILE *cmdfd)
|
||||||
@ -2002,6 +2007,144 @@ setup_privileges(FILE *cmdfd)
|
|||||||
"GRANT USAGE ON SCHEMA pg_catalog TO PUBLIC;\n\n",
|
"GRANT USAGE ON SCHEMA pg_catalog TO PUBLIC;\n\n",
|
||||||
"GRANT CREATE, USAGE ON SCHEMA public TO PUBLIC;\n\n",
|
"GRANT CREATE, USAGE ON SCHEMA public TO PUBLIC;\n\n",
|
||||||
"REVOKE ALL ON pg_largeobject FROM PUBLIC;\n\n",
|
"REVOKE ALL ON pg_largeobject FROM PUBLIC;\n\n",
|
||||||
|
"INSERT INTO pg_init_privs "
|
||||||
|
" (objoid, classoid, objsubid, initprivs, privtype)"
|
||||||
|
" SELECT"
|
||||||
|
" oid,"
|
||||||
|
" (SELECT oid FROM pg_class WHERE relname = 'pg_class'),"
|
||||||
|
" 0,"
|
||||||
|
" relacl,"
|
||||||
|
" 'i'"
|
||||||
|
" FROM"
|
||||||
|
" pg_class"
|
||||||
|
" WHERE"
|
||||||
|
" relacl IS NOT NULL"
|
||||||
|
" AND relkind IN ('r', 'v', 'm', 'S');",
|
||||||
|
"INSERT INTO pg_init_privs "
|
||||||
|
" (objoid, classoid, objsubid, initprivs, privtype)"
|
||||||
|
" SELECT"
|
||||||
|
" pg_class.oid,"
|
||||||
|
" (SELECT oid FROM pg_class WHERE relname = 'pg_class'),"
|
||||||
|
" pg_attribute.attnum,"
|
||||||
|
" pg_attribute.attacl,"
|
||||||
|
" 'i'"
|
||||||
|
" FROM"
|
||||||
|
" pg_class"
|
||||||
|
" JOIN pg_attribute ON (pg_class.oid = pg_attribute.attrelid)"
|
||||||
|
" WHERE"
|
||||||
|
" pg_attribute.attacl IS NOT NULL"
|
||||||
|
" AND pg_class.relkind IN ('r', 'v', 'm', 'S');",
|
||||||
|
"INSERT INTO pg_init_privs "
|
||||||
|
" (objoid, classoid, objsubid, initprivs, privtype)"
|
||||||
|
" SELECT"
|
||||||
|
" oid,"
|
||||||
|
" (SELECT oid FROM pg_class WHERE relname = 'pg_proc'),"
|
||||||
|
" 0,"
|
||||||
|
" proacl,"
|
||||||
|
" 'i'"
|
||||||
|
" FROM"
|
||||||
|
" pg_proc"
|
||||||
|
" WHERE"
|
||||||
|
" proacl IS NOT NULL;",
|
||||||
|
"INSERT INTO pg_init_privs "
|
||||||
|
" (objoid, classoid, objsubid, initprivs, privtype)"
|
||||||
|
" SELECT"
|
||||||
|
" oid,"
|
||||||
|
" (SELECT oid FROM pg_class WHERE relname = 'pg_type'),"
|
||||||
|
" 0,"
|
||||||
|
" typacl,"
|
||||||
|
" 'i'"
|
||||||
|
" FROM"
|
||||||
|
" pg_type"
|
||||||
|
" WHERE"
|
||||||
|
" typacl IS NOT NULL;",
|
||||||
|
"INSERT INTO pg_init_privs "
|
||||||
|
" (objoid, classoid, objsubid, initprivs, privtype)"
|
||||||
|
" SELECT"
|
||||||
|
" oid,"
|
||||||
|
" (SELECT oid FROM pg_class WHERE relname = 'pg_language'),"
|
||||||
|
" 0,"
|
||||||
|
" lanacl,"
|
||||||
|
" 'i'"
|
||||||
|
" FROM"
|
||||||
|
" pg_language"
|
||||||
|
" WHERE"
|
||||||
|
" lanacl IS NOT NULL;",
|
||||||
|
"INSERT INTO pg_init_privs "
|
||||||
|
" (objoid, classoid, objsubid, initprivs, privtype)"
|
||||||
|
" SELECT"
|
||||||
|
" oid,"
|
||||||
|
" (SELECT oid FROM pg_class WHERE "
|
||||||
|
" relname = 'pg_largeobject_metadata'),"
|
||||||
|
" 0,"
|
||||||
|
" lomacl,"
|
||||||
|
" 'i'"
|
||||||
|
" FROM"
|
||||||
|
" pg_largeobject_metadata"
|
||||||
|
" WHERE"
|
||||||
|
" lomacl IS NOT NULL;",
|
||||||
|
"INSERT INTO pg_init_privs "
|
||||||
|
" (objoid, classoid, objsubid, initprivs, privtype)"
|
||||||
|
" SELECT"
|
||||||
|
" oid,"
|
||||||
|
" (SELECT oid FROM pg_class WHERE relname = 'pg_namespace'),"
|
||||||
|
" 0,"
|
||||||
|
" nspacl,"
|
||||||
|
" 'i'"
|
||||||
|
" FROM"
|
||||||
|
" pg_namespace"
|
||||||
|
" WHERE"
|
||||||
|
" nspacl IS NOT NULL;",
|
||||||
|
"INSERT INTO pg_init_privs "
|
||||||
|
" (objoid, classoid, objsubid, initprivs, privtype)"
|
||||||
|
" SELECT"
|
||||||
|
" oid,"
|
||||||
|
" (SELECT oid FROM pg_class WHERE relname = 'pg_database'),"
|
||||||
|
" 0,"
|
||||||
|
" datacl,"
|
||||||
|
" 'i'"
|
||||||
|
" FROM"
|
||||||
|
" pg_database"
|
||||||
|
" WHERE"
|
||||||
|
" datacl IS NOT NULL;",
|
||||||
|
"INSERT INTO pg_init_privs "
|
||||||
|
" (objoid, classoid, objsubid, initprivs, privtype)"
|
||||||
|
" SELECT"
|
||||||
|
" oid,"
|
||||||
|
" (SELECT oid FROM pg_class WHERE relname = 'pg_tablespace'),"
|
||||||
|
" 0,"
|
||||||
|
" spcacl,"
|
||||||
|
" 'i'"
|
||||||
|
" FROM"
|
||||||
|
" pg_tablespace"
|
||||||
|
" WHERE"
|
||||||
|
" spcacl IS NOT NULL;",
|
||||||
|
"INSERT INTO pg_init_privs "
|
||||||
|
" (objoid, classoid, objsubid, initprivs, privtype)"
|
||||||
|
" SELECT"
|
||||||
|
" oid,"
|
||||||
|
" (SELECT oid FROM pg_class WHERE "
|
||||||
|
" relname = 'pg_foreign_data_wrapper'),"
|
||||||
|
" 0,"
|
||||||
|
" fdwacl,"
|
||||||
|
" 'i'"
|
||||||
|
" FROM"
|
||||||
|
" pg_foreign_data_wrapper"
|
||||||
|
" WHERE"
|
||||||
|
" fdwacl IS NOT NULL;",
|
||||||
|
"INSERT INTO pg_init_privs "
|
||||||
|
" (objoid, classoid, objsubid, initprivs, privtype)"
|
||||||
|
" SELECT"
|
||||||
|
" oid,"
|
||||||
|
" (SELECT oid FROM pg_class "
|
||||||
|
" WHERE relname = 'pg_foreign_server'),"
|
||||||
|
" 0,"
|
||||||
|
" srvacl,"
|
||||||
|
" 'i'"
|
||||||
|
" FROM"
|
||||||
|
" pg_foreign_server"
|
||||||
|
" WHERE"
|
||||||
|
" srvacl IS NOT NULL;",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -162,6 +162,9 @@ DECLARE_UNIQUE_INDEX(pg_inherits_relid_seqno_index, 2680, on pg_inherits using b
|
|||||||
DECLARE_INDEX(pg_inherits_parent_index, 2187, on pg_inherits using btree(inhparent oid_ops));
|
DECLARE_INDEX(pg_inherits_parent_index, 2187, on pg_inherits using btree(inhparent oid_ops));
|
||||||
#define InheritsParentIndexId 2187
|
#define InheritsParentIndexId 2187
|
||||||
|
|
||||||
|
DECLARE_UNIQUE_INDEX(pg_init_privs_o_c_o_index, 3395, on pg_init_privs using btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops));
|
||||||
|
#define InitPrivsObjIndexId 3395
|
||||||
|
|
||||||
DECLARE_UNIQUE_INDEX(pg_language_name_index, 2681, on pg_language using btree(lanname name_ops));
|
DECLARE_UNIQUE_INDEX(pg_language_name_index, 2681, on pg_language using btree(lanname name_ops));
|
||||||
#define LanguageNameIndexId 2681
|
#define LanguageNameIndexId 2681
|
||||||
DECLARE_UNIQUE_INDEX(pg_language_oid_index, 2682, on pg_language using btree(oid oid_ops));
|
DECLARE_UNIQUE_INDEX(pg_language_oid_index, 2682, on pg_language using btree(oid oid_ops));
|
||||||
|
101
src/include/catalog/pg_init_privs.h
Normal file
101
src/include/catalog/pg_init_privs.h
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* pg_init_privs.h
|
||||||
|
* definition of the system "initial privileges" relation (pg_init_privs)
|
||||||
|
*
|
||||||
|
* NOTE: an object is identified by the OID of the row that primarily
|
||||||
|
* defines the object, plus the OID of the table that that row appears in.
|
||||||
|
* For example, a function is identified by the OID of its pg_proc row
|
||||||
|
* plus the pg_class OID of table pg_proc. This allows unique identification
|
||||||
|
* of objects without assuming that OIDs are unique across tables.
|
||||||
|
*
|
||||||
|
* Since attributes don't have OIDs of their own, we identify an attribute
|
||||||
|
* privilege by the objoid+classoid of its parent table, plus an "objsubid"
|
||||||
|
* giving the attribute column number. "objsubid" must be zero in a privilege
|
||||||
|
* for a table itself, so that it is distinct from any column privilege.
|
||||||
|
* Currently, objsubid is unused and zero for all other kinds of objects.
|
||||||
|
*
|
||||||
|
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
|
||||||
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
|
*
|
||||||
|
* src/include/catalog/pg_init_privs.h
|
||||||
|
*
|
||||||
|
* NOTES
|
||||||
|
* the genbki.pl script reads this file and generates .bki
|
||||||
|
* information from the DATA() statements.
|
||||||
|
*
|
||||||
|
* XXX do NOT break up DATA() statements into multiple lines!
|
||||||
|
* the scripts are not as smart as you might think...
|
||||||
|
*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
#ifndef PG_INIT_PRIVS_H
|
||||||
|
#define PG_INIT_PRIVS_H
|
||||||
|
|
||||||
|
#include "catalog/genbki.h"
|
||||||
|
|
||||||
|
/* ----------------
|
||||||
|
* pg_init_privs definition. cpp turns this into
|
||||||
|
* typedef struct FormData_pg_init_privs
|
||||||
|
* ----------------
|
||||||
|
*/
|
||||||
|
#define InitPrivsRelationId 3394
|
||||||
|
|
||||||
|
CATALOG(pg_init_privs,3394) BKI_WITHOUT_OIDS
|
||||||
|
{
|
||||||
|
Oid objoid; /* OID of object itself */
|
||||||
|
Oid classoid; /* OID of table containing object */
|
||||||
|
int32 objsubid; /* column number, or 0 if not used */
|
||||||
|
char privtype; /* from initdb or extension? */
|
||||||
|
|
||||||
|
#ifdef CATALOG_VARLEN /* variable-length fields start here */
|
||||||
|
aclitem initprivs[1] BKI_FORCE_NOT_NULL; /* initial privs on
|
||||||
|
* object */
|
||||||
|
#endif
|
||||||
|
} FormData_pg_init_privs;
|
||||||
|
|
||||||
|
/* ----------------
|
||||||
|
* Form_pg_init_privs corresponds to a pointer to a tuple with
|
||||||
|
* the format of pg_init_privs relation.
|
||||||
|
* ----------------
|
||||||
|
*/
|
||||||
|
typedef FormData_pg_init_privs *Form_pg_init_privs;
|
||||||
|
|
||||||
|
/* ----------------
|
||||||
|
* compiler constants for pg_init_privs
|
||||||
|
* ----------------
|
||||||
|
*/
|
||||||
|
#define Natts_pg_init_privs 5
|
||||||
|
#define Anum_pg_init_privs_objoid 1
|
||||||
|
#define Anum_pg_init_privs_classoid 2
|
||||||
|
#define Anum_pg_init_privs_objsubid 3
|
||||||
|
#define Anum_pg_init_privs_privtype 4
|
||||||
|
#define Anum_pg_init_privs_privs 5
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It is important to know if the initial privileges are from initdb or from an
|
||||||
|
* extension. This enum is used to provide that differentiation and the two
|
||||||
|
* places which populate this table (initdb and during CREATE EXTENSION, see
|
||||||
|
* recordExtensionInitPriv()) know to use the correct values.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum InitPrivsType
|
||||||
|
{
|
||||||
|
INITPRIVS_INITDB = 'i',
|
||||||
|
INITPRIVS_EXTENSION = 'e'
|
||||||
|
} InitPrivsType;
|
||||||
|
|
||||||
|
/* ----------------
|
||||||
|
* initial contents of pg_init_privs
|
||||||
|
* ----------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Because the contents of this table depend on what is done with the other
|
||||||
|
* objects in the system (and, in particular, may change due to changes is
|
||||||
|
* system_views.sql), there is no initialization here.
|
||||||
|
*
|
||||||
|
* The initial contents are loaded near the end of initdb.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* PG_INIT_PRIVS_H */
|
@ -110,6 +110,7 @@ pg_foreign_server|t
|
|||||||
pg_foreign_table|t
|
pg_foreign_table|t
|
||||||
pg_index|t
|
pg_index|t
|
||||||
pg_inherits|t
|
pg_inherits|t
|
||||||
|
pg_init_privs|t
|
||||||
pg_language|t
|
pg_language|t
|
||||||
pg_largeobject|t
|
pg_largeobject|t
|
||||||
pg_largeobject_metadata|t
|
pg_largeobject_metadata|t
|
||||||
|
Loading…
x
Reference in New Issue
Block a user