Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit35dd40d

Browse files
committed
Improve tracking of role dependencies of pg_init_privs entries.
Commit5342874 invented SHARED_DEPENDENCY_INITACL entries inpg_shdepend, but installed them only for non-owner roles mentionedin a pg_init_privs entry. This turns out to be the wrong thing,because there is nothing to cue REASSIGN OWNED to go and updatepg_init_privs entries when the object's ownership is reassigned.That leads to leaving dangling entries in pg_init_privs, asreported by Hannu Krosing. Instead, install INITACL entries forall roles mentioned in pg_init_privs entries (except pinned roles),and change ALTER OWNER to not touch them, just as it doesn'ttouch pg_init_privs entries.REASSIGN OWNED will now substitute the new owner OID for the oldin pg_init_privs entries. This feels like perhaps not quite theright thing, since pg_init_privs ought to be a historical recordof the state of affairs just after CREATE EXTENSION. However,it's hard to see what else to do, if we don't want to disallowdropping the object's original owner. In any case this isbetter than the previous do-nothing behavior, and we're unlikelyto come up with a superior solution in time for v17.While here, tighten up some coding rules about how ACLs inpg_init_privs should never be null or empty. There's not anyobvious reason to allow that, and perhaps asserting that it'snot so will catch some bugs. (We were previously inconsistenton the point, with some code paths taking care not to storeempty ACLs and others not.)This leaves recordExtensionInitPrivWorker not doing anythingwith its ownerId argument, but we'll deal with that separately.catversion bump forced because of change of expected contentsof pg_shdepend when pg_init_privs entries exist.Discussion:https://postgr.es/m/CAMT0RQSVgv48G5GArUvOVhottWqZLrvC5wBzBa4HrUdXe9VRXw@mail.gmail.com
1 parent653d396 commit35dd40d

File tree

9 files changed

+666
-111
lines changed

9 files changed

+666
-111
lines changed

‎doc/src/sgml/catalogs.sgml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7182,9 +7182,6 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
71827182
The referenced object (which must be a role) is mentioned in a
71837183
<link linkend="catalog-pg-init-privs"><structname>pg_init_privs</structname></link>
71847184
entry for the dependent object.
7185-
(A <symbol>SHARED_DEPENDENCY_INITACL</symbol> entry is not made for
7186-
the owner of the object, since the owner will have
7187-
a <symbol>SHARED_DEPENDENCY_OWNER</symbol> entry anyway.)
71887185
</para>
71897186
</listitem>
71907187
</varlistentry>

‎src/backend/catalog/aclchk.c

Lines changed: 116 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4771,19 +4771,16 @@ recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid,
47714771
/* Update pg_shdepend for roles mentioned in the old/new ACLs. */
47724772
oldAclDatum=heap_getattr(oldtuple,Anum_pg_init_privs_initprivs,
47734773
RelationGetDescr(relation),&isNull);
4774-
if (!isNull)
4775-
old_acl=DatumGetAclP(oldAclDatum);
4776-
else
4777-
old_acl=NULL;/* this case shouldn't happen, probably */
4774+
Assert(!isNull);
4775+
old_acl=DatumGetAclP(oldAclDatum);
47784776
noldmembers=aclmembers(old_acl,&oldmembers);
47794777

47804778
updateInitAclDependencies(classoid,objoid,objsubid,
4781-
ownerId,
47824779
noldmembers,oldmembers,
47834780
nnewmembers,newmembers);
47844781

47854782
/* If we have a new ACL to set, then update the row with it. */
4786-
if (new_acl)
4783+
if (new_acl&&ACL_NUM(new_acl)!=0)
47874784
{
47884785
values[Anum_pg_init_privs_initprivs-1]=PointerGetDatum(new_acl);
47894786
replace[Anum_pg_init_privs_initprivs-1]= true;
@@ -4795,7 +4792,7 @@ recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid,
47954792
}
47964793
else
47974794
{
4798-
/* new_acl is NULL, so delete the entry we found. */
4795+
/* new_acl is NULL/empty, so delete the entry we found. */
47994796
CatalogTupleDelete(relation,&oldtuple->t_self);
48004797
}
48014798
}
@@ -4810,7 +4807,7 @@ recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid,
48104807
* If we are passed in a NULL ACL and no entry exists, we can just
48114808
* fall through and do nothing.
48124809
*/
4813-
if (new_acl)
4810+
if (new_acl&&ACL_NUM(new_acl)!=0)
48144811
{
48154812
/* No entry found, so add it. */
48164813
values[Anum_pg_init_privs_objoid-1]=ObjectIdGetDatum(objoid);
@@ -4832,7 +4829,6 @@ recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid,
48324829
oldmembers=NULL;
48334830

48344831
updateInitAclDependencies(classoid,objoid,objsubid,
4835-
ownerId,
48364832
noldmembers,oldmembers,
48374833
nnewmembers,newmembers);
48384834
}
@@ -4846,6 +4842,115 @@ recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid,
48464842
table_close(relation,RowExclusiveLock);
48474843
}
48484844

4845+
/*
4846+
* ReplaceRoleInInitPriv
4847+
*
4848+
* Used by shdepReassignOwned to replace mentions of a role in pg_init_privs.
4849+
*/
4850+
void
4851+
ReplaceRoleInInitPriv(Oidoldroleid,Oidnewroleid,
4852+
Oidclassid,Oidobjid,int32objsubid)
4853+
{
4854+
Relationrel;
4855+
ScanKeyDatakey[3];
4856+
SysScanDescscan;
4857+
HeapTupleoldtuple;
4858+
DatumoldAclDatum;
4859+
boolisNull;
4860+
Acl*old_acl;
4861+
Acl*new_acl;
4862+
HeapTuplenewtuple;
4863+
intnoldmembers;
4864+
intnnewmembers;
4865+
Oid*oldmembers;
4866+
Oid*newmembers;
4867+
4868+
/* Search for existing pg_init_privs entry for the target object. */
4869+
rel=table_open(InitPrivsRelationId,RowExclusiveLock);
4870+
4871+
ScanKeyInit(&key[0],
4872+
Anum_pg_init_privs_objoid,
4873+
BTEqualStrategyNumber,F_OIDEQ,
4874+
ObjectIdGetDatum(objid));
4875+
ScanKeyInit(&key[1],
4876+
Anum_pg_init_privs_classoid,
4877+
BTEqualStrategyNumber,F_OIDEQ,
4878+
ObjectIdGetDatum(classid));
4879+
ScanKeyInit(&key[2],
4880+
Anum_pg_init_privs_objsubid,
4881+
BTEqualStrategyNumber,F_INT4EQ,
4882+
Int32GetDatum(objsubid));
4883+
4884+
scan=systable_beginscan(rel,InitPrivsObjIndexId, true,
4885+
NULL,3,key);
4886+
4887+
/* There should exist only one entry or none. */
4888+
oldtuple=systable_getnext(scan);
4889+
4890+
if (!HeapTupleIsValid(oldtuple))
4891+
{
4892+
/*
4893+
* Hmm, why are we here if there's no entry? But pack up and go away
4894+
* quietly.
4895+
*/
4896+
systable_endscan(scan);
4897+
table_close(rel,RowExclusiveLock);
4898+
return;
4899+
}
4900+
4901+
/* Get a writable copy of the existing ACL. */
4902+
oldAclDatum=heap_getattr(oldtuple,Anum_pg_init_privs_initprivs,
4903+
RelationGetDescr(rel),&isNull);
4904+
Assert(!isNull);
4905+
old_acl=DatumGetAclPCopy(oldAclDatum);
4906+
4907+
/*
4908+
* Generate new ACL. This usage of aclnewowner is a bit off-label when
4909+
* oldroleid isn't the owner; but it does the job fine.
4910+
*/
4911+
new_acl=aclnewowner(old_acl,oldroleid,newroleid);
4912+
4913+
/*
4914+
* If we end with an empty ACL, delete the pg_init_privs entry. (That
4915+
* probably can't happen here, but we may as well cover the case.)
4916+
*/
4917+
if (new_acl==NULL||ACL_NUM(new_acl)==0)
4918+
{
4919+
CatalogTupleDelete(rel,&oldtuple->t_self);
4920+
}
4921+
else
4922+
{
4923+
Datumvalues[Natts_pg_init_privs]= {0};
4924+
boolnulls[Natts_pg_init_privs]= {0};
4925+
boolreplaces[Natts_pg_init_privs]= {0};
4926+
4927+
/* Update existing entry. */
4928+
values[Anum_pg_init_privs_initprivs-1]=PointerGetDatum(new_acl);
4929+
replaces[Anum_pg_init_privs_initprivs-1]= true;
4930+
4931+
newtuple=heap_modify_tuple(oldtuple,RelationGetDescr(rel),
4932+
values,nulls,replaces);
4933+
CatalogTupleUpdate(rel,&newtuple->t_self,newtuple);
4934+
}
4935+
4936+
/*
4937+
* Update the shared dependency ACL info.
4938+
*/
4939+
noldmembers=aclmembers(old_acl,&oldmembers);
4940+
nnewmembers=aclmembers(new_acl,&newmembers);
4941+
4942+
updateInitAclDependencies(classid,objid,objsubid,
4943+
noldmembers,oldmembers,
4944+
nnewmembers,newmembers);
4945+
4946+
systable_endscan(scan);
4947+
4948+
/* prevent error when processing objects multiple times */
4949+
CommandCounterIncrement();
4950+
4951+
table_close(rel,RowExclusiveLock);
4952+
}
4953+
48494954
/*
48504955
* RemoveRoleFromInitPriv
48514956
*
@@ -4907,10 +5012,8 @@ RemoveRoleFromInitPriv(Oid roleid, Oid classid, Oid objid, int32 objsubid)
49075012
/* Get a writable copy of the existing ACL. */
49085013
oldAclDatum=heap_getattr(oldtuple,Anum_pg_init_privs_initprivs,
49095014
RelationGetDescr(rel),&isNull);
4910-
if (!isNull)
4911-
old_acl=DatumGetAclPCopy(oldAclDatum);
4912-
else
4913-
old_acl=NULL;/* this case shouldn't happen, probably */
5015+
Assert(!isNull);
5016+
old_acl=DatumGetAclPCopy(oldAclDatum);
49145017

49155018
/*
49165019
* We need the members of both old and new ACLs so we can correct the
@@ -4972,7 +5075,6 @@ RemoveRoleFromInitPriv(Oid roleid, Oid classid, Oid objid, int32 objsubid)
49725075
nnewmembers=aclmembers(new_acl,&newmembers);
49735076

49745077
updateInitAclDependencies(classid,objid,objsubid,
4975-
ownerId,
49765078
noldmembers,oldmembers,
49775079
nnewmembers,newmembers);
49785080

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp