Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 6c268df

Browse files
committed
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
1 parent 0b62fd0 commit 6c268df

File tree

8 files changed

+549
-4
lines changed

8 files changed

+549
-4
lines changed

doc/src/sgml/catalogs.sgml

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,11 @@
178178
<entry>table inheritance hierarchy</entry>
179179
</row>
180180

181+
<row>
182+
<entry><link linkend="catalog-pg-init-privs"><structname>pg_init_privs</structname></link></entry>
183+
<entry>object initial privileges</entry>
184+
</row>
185+
181186
<row>
182187
<entry><link linkend="catalog-pg-language"><structname>pg_language</structname></link></entry>
183188
<entry>languages for writing functions</entry>
@@ -3785,6 +3790,109 @@
37853790

37863791
</sect1>
37873792

3793+
<sect1 id="catalog-pg-init-privs">
3794+
<title><structname>pg_init_privs</structname></title>
3795+
3796+
<indexterm zone="catalog-pg-init-privs">
3797+
<primary>pg_init_privs</primary>
3798+
</indexterm>
3799+
3800+
<para>
3801+
The catalog <structname>pg_init_privs</> records information about
3802+
the initial privileges of objects in the system. There is one entry
3803+
for each object in the database which has a non-default (non-NULL)
3804+
initial set of privileges.
3805+
</para>
3806+
3807+
<para>
3808+
Objects can have initial privileges either by having those privileges set
3809+
when the system is initialized (by <application>initdb</>) or when the
3810+
object is created during a <command>CREATE EXTENSION</command> and the
3811+
extension script sets initial privileges using the <command>GRANT</command>
3812+
system. Note that the system will automatically handle recording of the
3813+
privileges during the extension script and that extension authors need
3814+
only use the <command>GRANT</command> and <command>REVOKE</command>
3815+
statements in their script to have the privileges recorded. The
3816+
<literal>privtype</literal> column indicates if the initial privilege was
3817+
set by <application>initdb</> or during a
3818+
<command>CREATE EXTENSION</command> command.
3819+
</para>
3820+
3821+
<para>
3822+
Objects which have initial privileges set by <application>initdb</> will
3823+
have entries where <literal>privtype</literal> is
3824+
<literal>'i'</literal>, while objects which have initial privileges set
3825+
by <command>CREATE EXTENSION</command> will have entries where
3826+
<literal>privtype</literal> is <literal>'e'</literal>.
3827+
</para>
3828+
3829+
<table>
3830+
<title><structname>pg_inherits</> Columns</title>
3831+
3832+
<tgroup cols="4">
3833+
<thead>
3834+
<row>
3835+
<entry>Name</entry>
3836+
<entry>Type</entry>
3837+
<entry>References</entry>
3838+
<entry>Description</entry>
3839+
</row>
3840+
</thead>
3841+
3842+
<tbody>
3843+
<row>
3844+
<entry><structfield>objoid</structfield></entry>
3845+
<entry><type>oid</type></entry>
3846+
<entry>any OID column</entry>
3847+
<entry>The OID of the specific object</entry>
3848+
</row>
3849+
3850+
<row>
3851+
<entry><structfield>classoid</structfield></entry>
3852+
<entry><type>oid</type></entry>
3853+
<entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry>
3854+
<entry>The OID of the system catalog the object is in</entry>
3855+
</row>
3856+
3857+
<row>
3858+
<entry><structfield>objsubid</structfield></entry>
3859+
<entry><type>int4</type></entry>
3860+
<entry></entry>
3861+
<entry>
3862+
For a table column, this is the column number (the
3863+
<structfield>objoid</> and <structfield>classoid</> refer to the
3864+
table itself). For all other object types, this column is
3865+
zero.
3866+
</entry>
3867+
</row>
3868+
3869+
<row>
3870+
<entry><structfield>privtype</structfield></entry>
3871+
<entry><type>char</type></entry>
3872+
<entry></entry>
3873+
<entry>
3874+
A code defining the type of initial privilege of this object; see text
3875+
</entry>
3876+
</row>
3877+
3878+
<row>
3879+
<entry><structfield>initprivs</structfield></entry>
3880+
<entry><type>aclitem[]</type></entry>
3881+
<entry></entry>
3882+
<entry>
3883+
The initial access privileges; see
3884+
<xref linkend="sql-grant"> and
3885+
<xref linkend="sql-revoke">
3886+
for details
3887+
</entry>
3888+
</row>
3889+
3890+
</tbody>
3891+
</tgroup>
3892+
</table>
3893+
3894+
</sect1>
3895+
37883896

37893897
<sect1 id="catalog-pg-language">
37903898
<title><structname>pg_language</structname></title>

src/backend/catalog/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ POSTGRES_BKI_SRCS = $(addprefix $(top_srcdir)/src/include/catalog/,\
4040
pg_ts_parser.h pg_ts_template.h pg_extension.h \
4141
pg_foreign_data_wrapper.h pg_foreign_server.h pg_user_mapping.h \
4242
pg_foreign_table.h pg_policy.h pg_replication_origin.h \
43-
pg_default_acl.h pg_seclabel.h pg_shseclabel.h \
43+
pg_default_acl.h pg_init_privs.h pg_seclabel.h pg_shseclabel.h \
4444
pg_collation.h pg_range.h pg_transform.h \
4545
toasting.h indexing.h \
4646
)

src/backend/catalog/aclchk.c

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "catalog/pg_extension.h"
3636
#include "catalog/pg_foreign_data_wrapper.h"
3737
#include "catalog/pg_foreign_server.h"
38+
#include "catalog/pg_init_privs.h"
3839
#include "catalog/pg_language.h"
3940
#include "catalog/pg_largeobject.h"
4041
#include "catalog/pg_largeobject_metadata.h"
@@ -49,6 +50,7 @@
4950
#include "catalog/pg_ts_dict.h"
5051
#include "commands/dbcommands.h"
5152
#include "commands/event_trigger.h"
53+
#include "commands/extension.h"
5254
#include "commands/proclang.h"
5355
#include "commands/tablespace.h"
5456
#include "foreign/foreign.h"
@@ -119,6 +121,8 @@ static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions,
119121
AttrNumber att_number, const char *colname);
120122
static AclMode pg_aclmask(AclObjectKind objkind, Oid table_oid, AttrNumber attnum,
121123
Oid roleid, AclMode mask, AclMaskHow how);
124+
static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid,
125+
Acl *new_acl);
122126

123127

124128
#ifdef ACLDEBUG
@@ -1678,6 +1682,10 @@ ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname,
16781682
/* keep the catalog indexes up to date */
16791683
CatalogUpdateIndexes(attRelation, newtuple);
16801684

1685+
/* Update initial privileges for extensions */
1686+
recordExtensionInitPriv(relOid, RelationRelationId, attnum,
1687+
ACL_NUM(new_acl) > 0 ? new_acl : NULL);
1688+
16811689
/* Update the shared dependency ACL info */
16821690
updateAclDependencies(RelationRelationId, relOid, attnum,
16831691
ownerId,
@@ -1939,6 +1947,9 @@ ExecGrant_Relation(InternalGrant *istmt)
19391947
/* keep the catalog indexes up to date */
19401948
CatalogUpdateIndexes(relation, newtuple);
19411949

1950+
/* Update initial privileges for extensions */
1951+
recordExtensionInitPriv(relOid, RelationRelationId, 0, new_acl);
1952+
19421953
/* Update the shared dependency ACL info */
19431954
updateAclDependencies(RelationRelationId, relOid, 0,
19441955
ownerId,
@@ -2254,6 +2265,10 @@ ExecGrant_Fdw(InternalGrant *istmt)
22542265
/* keep the catalog indexes up to date */
22552266
CatalogUpdateIndexes(relation, newtuple);
22562267

2268+
/* Update initial privileges for extensions */
2269+
recordExtensionInitPriv(fdwid, ForeignDataWrapperRelationId, 0,
2270+
new_acl);
2271+
22572272
/* Update the shared dependency ACL info */
22582273
updateAclDependencies(ForeignDataWrapperRelationId,
22592274
HeapTupleGetOid(tuple), 0,
@@ -2379,6 +2394,9 @@ ExecGrant_ForeignServer(InternalGrant *istmt)
23792394
/* keep the catalog indexes up to date */
23802395
CatalogUpdateIndexes(relation, newtuple);
23812396

2397+
/* Update initial privileges for extensions */
2398+
recordExtensionInitPriv(srvid, ForeignServerRelationId, 0, new_acl);
2399+
23822400
/* Update the shared dependency ACL info */
23832401
updateAclDependencies(ForeignServerRelationId,
23842402
HeapTupleGetOid(tuple), 0,
@@ -2503,6 +2521,9 @@ ExecGrant_Function(InternalGrant *istmt)
25032521
/* keep the catalog indexes up to date */
25042522
CatalogUpdateIndexes(relation, newtuple);
25052523

2524+
/* Update initial privileges for extensions */
2525+
recordExtensionInitPriv(funcId, ProcedureRelationId, 0, new_acl);
2526+
25062527
/* Update the shared dependency ACL info */
25072528
updateAclDependencies(ProcedureRelationId, funcId, 0,
25082529
ownerId,
@@ -2633,6 +2654,9 @@ ExecGrant_Language(InternalGrant *istmt)
26332654
/* keep the catalog indexes up to date */
26342655
CatalogUpdateIndexes(relation, newtuple);
26352656

2657+
/* Update initial privileges for extensions */
2658+
recordExtensionInitPriv(langId, LanguageRelationId, 0, new_acl);
2659+
26362660
/* Update the shared dependency ACL info */
26372661
updateAclDependencies(LanguageRelationId, HeapTupleGetOid(tuple), 0,
26382662
ownerId,
@@ -2772,6 +2796,9 @@ ExecGrant_Largeobject(InternalGrant *istmt)
27722796
/* keep the catalog indexes up to date */
27732797
CatalogUpdateIndexes(relation, newtuple);
27742798

2799+
/* Update initial privileges for extensions */
2800+
recordExtensionInitPriv(loid, LargeObjectRelationId, 0, new_acl);
2801+
27752802
/* Update the shared dependency ACL info */
27762803
updateAclDependencies(LargeObjectRelationId,
27772804
HeapTupleGetOid(tuple), 0,
@@ -2897,6 +2924,9 @@ ExecGrant_Namespace(InternalGrant *istmt)
28972924
/* keep the catalog indexes up to date */
28982925
CatalogUpdateIndexes(relation, newtuple);
28992926

2927+
/* Update initial privileges for extensions */
2928+
recordExtensionInitPriv(nspid, NamespaceRelationId, 0, new_acl);
2929+
29002930
/* Update the shared dependency ACL info */
29012931
updateAclDependencies(NamespaceRelationId, HeapTupleGetOid(tuple), 0,
29022932
ownerId,
@@ -3158,6 +3188,9 @@ ExecGrant_Type(InternalGrant *istmt)
31583188
/* keep the catalog indexes up to date */
31593189
CatalogUpdateIndexes(relation, newtuple);
31603190

3191+
/* Update initial privileges for extensions */
3192+
recordExtensionInitPriv(typId, TypeRelationId, 0, new_acl);
3193+
31613194
/* Update the shared dependency ACL info */
31623195
updateAclDependencies(TypeRelationId, typId, 0,
31633196
ownerId,
@@ -5174,3 +5207,119 @@ get_user_default_acl(GrantObjectType objtype, Oid ownerId, Oid nsp_oid)
51745207

51755208
return result;
51765209
}
5210+
5211+
/*
5212+
* Record initial ACL for an extension object
5213+
*
5214+
* This will perform a wholesale replacement of the entire ACL for the object
5215+
* passed in, therefore be sure to pass in the complete new ACL to use.
5216+
*
5217+
* Can be called at any time, we check if 'creating_extension' is set and, if
5218+
* not, exit immediately.
5219+
*
5220+
* Pass in the object OID, the OID of the class (the OID of the table which
5221+
* the object is defined in) and the 'sub' id of the object (objsubid), if
5222+
* any. If there is no 'sub' id (they are currently only used for columns of
5223+
* tables) then pass in '0'. Finally, pass in the complete ACL to store.
5224+
*
5225+
* If an ACL already exists for this object/sub-object then we will replace
5226+
* it with what is passed in.
5227+
*
5228+
* Passing in NULL for 'new_acl' will result in the entry for the object being
5229+
* removed, if one is found.
5230+
*/
5231+
static void
5232+
recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
5233+
{
5234+
Relation relation;
5235+
ScanKeyData key[3];
5236+
SysScanDesc scan;
5237+
HeapTuple tuple;
5238+
HeapTuple oldtuple;
5239+
5240+
if (!creating_extension)
5241+
return;
5242+
5243+
relation = heap_open(InitPrivsRelationId, RowExclusiveLock);
5244+
5245+
ScanKeyInit(&key[0],
5246+
Anum_pg_init_privs_objoid,
5247+
BTEqualStrategyNumber, F_OIDEQ,
5248+
ObjectIdGetDatum(objoid));
5249+
ScanKeyInit(&key[1],
5250+
Anum_pg_init_privs_classoid,
5251+
BTEqualStrategyNumber, F_OIDEQ,
5252+
ObjectIdGetDatum(classoid));
5253+
ScanKeyInit(&key[2],
5254+
Anum_pg_init_privs_objsubid,
5255+
BTEqualStrategyNumber, F_INT4EQ,
5256+
Int32GetDatum(objsubid));
5257+
5258+
scan = systable_beginscan(relation, InitPrivsObjIndexId, true,
5259+
NULL, 3, key);
5260+
5261+
/* There should exist only one entry or none. */
5262+
oldtuple = systable_getnext(scan);
5263+
5264+
systable_endscan(scan);
5265+
5266+
/* If we find an entry, update it with the latest ACL. */
5267+
if (HeapTupleIsValid(oldtuple))
5268+
{
5269+
Datum values[Natts_pg_init_privs];
5270+
bool nulls[Natts_pg_init_privs];
5271+
bool replace[Natts_pg_init_privs];
5272+
5273+
/* If we have a new ACL to set, then update the row with it. */
5274+
if (new_acl)
5275+
{
5276+
MemSet(values, 0, sizeof(values));
5277+
MemSet(nulls, false, sizeof(nulls));
5278+
MemSet(replace, false, sizeof(replace));
5279+
5280+
values[Anum_pg_init_privs_privs - 1] = PointerGetDatum(new_acl);
5281+
replace[Anum_pg_init_privs_privs - 1] = true;
5282+
5283+
oldtuple = heap_modify_tuple(oldtuple, RelationGetDescr(relation),
5284+
values, nulls, replace);
5285+
5286+
simple_heap_update(relation, &oldtuple->t_self, oldtuple);
5287+
5288+
/* keep the catalog indexes up to date */
5289+
CatalogUpdateIndexes(relation, oldtuple);
5290+
}
5291+
else
5292+
/* new_acl is NULL, so delete the entry we found. */
5293+
simple_heap_delete(relation, &oldtuple->t_self);
5294+
}
5295+
else
5296+
{
5297+
/* No entry found, so add it. */
5298+
Datum values[Natts_pg_init_privs];
5299+
bool nulls[Natts_pg_init_privs];
5300+
5301+
MemSet(nulls, false, sizeof(nulls));
5302+
5303+
values[Anum_pg_init_privs_objoid - 1] = ObjectIdGetDatum(objoid);
5304+
values[Anum_pg_init_privs_classoid - 1] = ObjectIdGetDatum(classoid);
5305+
values[Anum_pg_init_privs_objsubid - 1] = Int32GetDatum(objsubid);
5306+
5307+
/* This function only handles initial privileges of extensions */
5308+
values[Anum_pg_init_privs_privtype - 1] =
5309+
CharGetDatum(INITPRIVS_EXTENSION);
5310+
5311+
values[Anum_pg_init_privs_privs - 1] = PointerGetDatum(new_acl);
5312+
5313+
tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
5314+
5315+
simple_heap_insert(relation, tuple);
5316+
5317+
/* keep the catalog indexes up to date */
5318+
CatalogUpdateIndexes(relation, tuple);
5319+
}
5320+
5321+
/* prevent error when processing objects multiple times */
5322+
CommandCounterIncrement();
5323+
5324+
heap_close(relation, RowExclusiveLock);
5325+
}

0 commit comments

Comments
 (0)