Skip to content

Commit bf1e33d

Browse files
committed
Fix unwanted denial of ALTER OWNER rights to superusers. There was some
discussion of getting around this by relaxing the checks made for regular users, but I'm disinclined to toy with the security model right now, so just special-case it for superusers where needed.
1 parent a7f4925 commit bf1e33d

File tree

9 files changed

+147
-112
lines changed

9 files changed

+147
-112
lines changed

src/backend/commands/aggregatecmds.c

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.28 2005/07/14 21:46:29 tgl Exp $
12+
* $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.29 2005/08/22 17:38:20 tgl Exp $
1313
*
1414
* DESCRIPTION
1515
* The "DefineFoo" routines take the parse tree and pick out the
@@ -332,20 +332,25 @@ AlterAggregateOwner(List *name, TypeName *basetype, Oid newOwnerId)
332332
*/
333333
if (procForm->proowner != newOwnerId)
334334
{
335-
/* Otherwise, must be owner of the existing object */
336-
if (!pg_proc_ownercheck(procOid, GetUserId()))
337-
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
338-
NameListToString(name));
339-
340-
/* Must be able to become new owner */
341-
check_is_member_of_role(GetUserId(), newOwnerId);
342-
343-
/* New owner must have CREATE privilege on namespace */
344-
aclresult = pg_namespace_aclcheck(procForm->pronamespace, newOwnerId,
345-
ACL_CREATE);
346-
if (aclresult != ACLCHECK_OK)
347-
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
348-
get_namespace_name(procForm->pronamespace));
335+
/* Superusers can always do it */
336+
if (!superuser())
337+
{
338+
/* Otherwise, must be owner of the existing object */
339+
if (!pg_proc_ownercheck(procOid, GetUserId()))
340+
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
341+
NameListToString(name));
342+
343+
/* Must be able to become new owner */
344+
check_is_member_of_role(GetUserId(), newOwnerId);
345+
346+
/* New owner must have CREATE privilege on namespace */
347+
aclresult = pg_namespace_aclcheck(procForm->pronamespace,
348+
newOwnerId,
349+
ACL_CREATE);
350+
if (aclresult != ACLCHECK_OK)
351+
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
352+
get_namespace_name(procForm->pronamespace));
353+
}
349354

350355
/*
351356
* Modify the owner --- okay to scribble on tup because it's a

src/backend/commands/conversioncmds.c

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/conversioncmds.c,v 1.21 2005/07/14 21:46:29 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/conversioncmds.c,v 1.22 2005/08/22 17:38:20 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -206,20 +206,25 @@ AlterConversionOwner(List *name, Oid newOwnerId)
206206
*/
207207
if (convForm->conowner != newOwnerId)
208208
{
209-
/* Otherwise, must be owner of the existing object */
210-
if (!pg_conversion_ownercheck(HeapTupleGetOid(tup),GetUserId()))
211-
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
212-
NameListToString(name));
213-
214-
/* Must be able to become new owner */
215-
check_is_member_of_role(GetUserId(), newOwnerId);
216-
217-
/* New owner must have CREATE privilege on namespace */
218-
aclresult = pg_namespace_aclcheck(convForm->connamespace, newOwnerId,
219-
ACL_CREATE);
220-
if (aclresult != ACLCHECK_OK)
221-
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
222-
get_namespace_name(convForm->connamespace));
209+
/* Superusers can always do it */
210+
if (!superuser())
211+
{
212+
/* Otherwise, must be owner of the existing object */
213+
if (!pg_conversion_ownercheck(HeapTupleGetOid(tup),GetUserId()))
214+
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
215+
NameListToString(name));
216+
217+
/* Must be able to become new owner */
218+
check_is_member_of_role(GetUserId(), newOwnerId);
219+
220+
/* New owner must have CREATE privilege on namespace */
221+
aclresult = pg_namespace_aclcheck(convForm->connamespace,
222+
newOwnerId,
223+
ACL_CREATE);
224+
if (aclresult != ACLCHECK_OK)
225+
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
226+
get_namespace_name(convForm->connamespace));
227+
}
223228

224229
/*
225230
* Modify the owner --- okay to scribble on tup because it's a

src/backend/commands/dbcommands.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.170 2005/08/12 01:35:57 tgl Exp $
18+
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.171 2005/08/22 17:38:20 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -1024,7 +1024,8 @@ AlterDatabaseOwner(const char *dbname, Oid newOwnerId)
10241024
* NOTE: This is different from other alter-owner checks in
10251025
* that the current user is checked for createdb privileges
10261026
* instead of the destination owner. This is consistent
1027-
* with the CREATE case for databases.
1027+
* with the CREATE case for databases. Because superusers
1028+
* will always have this right, we need no special case for them.
10281029
*/
10291030
if (!have_createdb_privilege())
10301031
ereport(ERROR,

src/backend/commands/functioncmds.c

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.65 2005/08/01 04:03:55 tgl Exp $
13+
* $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.66 2005/08/22 17:38:20 tgl Exp $
1414
*
1515
* DESCRIPTION
1616
* These routines take the parse tree and pick out the
@@ -894,20 +894,25 @@ AlterFunctionOwner(List *name, List *argtypes, Oid newOwnerId)
894894
bool isNull;
895895
HeapTuple newtuple;
896896

897-
/* Otherwise, must be owner of the existing object */
898-
if (!pg_proc_ownercheck(procOid,GetUserId()))
899-
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
900-
NameListToString(name));
901-
902-
/* Must be able to become new owner */
903-
check_is_member_of_role(GetUserId(), newOwnerId);
904-
905-
/* New owner must have CREATE privilege on namespace */
906-
aclresult = pg_namespace_aclcheck(procForm->pronamespace, newOwnerId,
907-
ACL_CREATE);
908-
if (aclresult != ACLCHECK_OK)
909-
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
910-
get_namespace_name(procForm->pronamespace));
897+
/* Superusers can always do it */
898+
if (!superuser())
899+
{
900+
/* Otherwise, must be owner of the existing object */
901+
if (!pg_proc_ownercheck(procOid,GetUserId()))
902+
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
903+
NameListToString(name));
904+
905+
/* Must be able to become new owner */
906+
check_is_member_of_role(GetUserId(), newOwnerId);
907+
908+
/* New owner must have CREATE privilege on namespace */
909+
aclresult = pg_namespace_aclcheck(procForm->pronamespace,
910+
newOwnerId,
911+
ACL_CREATE);
912+
if (aclresult != ACLCHECK_OK)
913+
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
914+
get_namespace_name(procForm->pronamespace));
915+
}
911916

912917
memset(repl_null, ' ', sizeof(repl_null));
913918
memset(repl_repl, ' ', sizeof(repl_repl));

src/backend/commands/opclasscmds.c

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.35 2005/07/14 21:46:29 tgl Exp $
12+
* $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.36 2005/08/22 17:38:20 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -951,20 +951,24 @@ AlterOpClassOwner(List *name, const char *access_method, Oid newOwnerId)
951951
*/
952952
if (opcForm->opcowner != newOwnerId)
953953
{
954-
/* Otherwise, must be owner of the existing object */
955-
if (!pg_opclass_ownercheck(HeapTupleGetOid(tup),GetUserId()))
956-
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPCLASS,
957-
NameListToString(name));
958-
959-
/* Must be able to become new owner */
960-
check_is_member_of_role(GetUserId(), newOwnerId);
961-
962-
/* New owner must have CREATE privilege on namespace */
963-
aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId,
964-
ACL_CREATE);
965-
if (aclresult != ACLCHECK_OK)
966-
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
967-
get_namespace_name(namespaceOid));
954+
/* Superusers can always do it */
955+
if (!superuser())
956+
{
957+
/* Otherwise, must be owner of the existing object */
958+
if (!pg_opclass_ownercheck(HeapTupleGetOid(tup),GetUserId()))
959+
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPCLASS,
960+
NameListToString(name));
961+
962+
/* Must be able to become new owner */
963+
check_is_member_of_role(GetUserId(), newOwnerId);
964+
965+
/* New owner must have CREATE privilege on namespace */
966+
aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId,
967+
ACL_CREATE);
968+
if (aclresult != ACLCHECK_OK)
969+
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
970+
get_namespace_name(namespaceOid));
971+
}
968972

969973
/*
970974
* Modify the owner --- okay to scribble on tup because it's a

src/backend/commands/operatorcmds.c

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.24 2005/07/14 21:46:29 tgl Exp $
12+
* $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.25 2005/08/22 17:38:20 tgl Exp $
1313
*
1414
* DESCRIPTION
1515
* The "DefineFoo" routines take the parse tree and pick out the
@@ -296,20 +296,25 @@ AlterOperatorOwner(List *name, TypeName *typeName1, TypeName *typeName2,
296296
*/
297297
if (oprForm->oprowner != newOwnerId)
298298
{
299-
/* Otherwise, must be owner of the existing object */
300-
if (!pg_oper_ownercheck(operOid,GetUserId()))
301-
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPER,
302-
NameListToString(name));
303-
304-
/* Must be able to become new owner */
305-
check_is_member_of_role(GetUserId(), newOwnerId);
306-
307-
/* New owner must have CREATE privilege on namespace */
308-
aclresult = pg_namespace_aclcheck(oprForm->oprnamespace, newOwnerId,
309-
ACL_CREATE);
310-
if (aclresult != ACLCHECK_OK)
311-
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
312-
get_namespace_name(oprForm->oprnamespace));
299+
/* Superusers can always do it */
300+
if (!superuser())
301+
{
302+
/* Otherwise, must be owner of the existing object */
303+
if (!pg_oper_ownercheck(operOid,GetUserId()))
304+
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPER,
305+
NameListToString(name));
306+
307+
/* Must be able to become new owner */
308+
check_is_member_of_role(GetUserId(), newOwnerId);
309+
310+
/* New owner must have CREATE privilege on namespace */
311+
aclresult = pg_namespace_aclcheck(oprForm->oprnamespace,
312+
newOwnerId,
313+
ACL_CREATE);
314+
if (aclresult != ACLCHECK_OK)
315+
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
316+
get_namespace_name(oprForm->oprnamespace));
317+
}
313318

314319
/*
315320
* Modify the owner --- okay to scribble on tup because it's a

src/backend/commands/schemacmds.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.33 2005/07/14 21:46:29 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.34 2005/08/22 17:38:20 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -315,7 +315,8 @@ AlterSchemaOwner(const char *name, Oid newOwnerId)
315315
* NOTE: This is different from other alter-owner checks in
316316
* that the current user is checked for create privileges
317317
* instead of the destination owner. This is consistent
318-
* with the CREATE case for schemas.
318+
* with the CREATE case for schemas. Because superusers
319+
* will always have this right, we need no special case for them.
319320
*/
320321
aclresult = pg_database_aclcheck(MyDatabaseId, GetUserId(),
321322
ACL_CREATE);

src/backend/commands/tablecmds.c

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.166 2005/08/04 01:09:28 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.167 2005/08/22 17:38:20 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -5307,23 +5307,27 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing)
53075307
/* skip permission checks when recursing to index or toast table */
53085308
if (!recursing)
53095309
{
5310-
Oid namespaceOid = tuple_class->relnamespace;
5311-
AclResult aclresult;
5312-
5313-
/* Otherwise, must be owner of the existing object */
5314-
if (!pg_class_ownercheck(relationOid,GetUserId()))
5315-
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
5316-
RelationGetRelationName(target_rel));
5317-
5318-
/* Must be able to become new owner */
5319-
check_is_member_of_role(GetUserId(), newOwnerId);
5320-
5321-
/* New owner must have CREATE privilege on namespace */
5322-
aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId,
5323-
ACL_CREATE);
5324-
if (aclresult != ACLCHECK_OK)
5325-
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
5326-
get_namespace_name(namespaceOid));
5310+
/* Superusers can always do it */
5311+
if (!superuser())
5312+
{
5313+
Oid namespaceOid = tuple_class->relnamespace;
5314+
AclResult aclresult;
5315+
5316+
/* Otherwise, must be owner of the existing object */
5317+
if (!pg_class_ownercheck(relationOid,GetUserId()))
5318+
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
5319+
RelationGetRelationName(target_rel));
5320+
5321+
/* Must be able to become new owner */
5322+
check_is_member_of_role(GetUserId(), newOwnerId);
5323+
5324+
/* New owner must have CREATE privilege on namespace */
5325+
aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId,
5326+
ACL_CREATE);
5327+
if (aclresult != ACLCHECK_OK)
5328+
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
5329+
get_namespace_name(namespaceOid));
5330+
}
53275331
}
53285332

53295333
memset(repl_null, ' ', sizeof(repl_null));

src/backend/commands/typecmds.c

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.79 2005/08/12 01:35:58 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.80 2005/08/22 17:38:20 tgl Exp $
1212
*
1313
* DESCRIPTION
1414
* The "DefineFoo" routines take the parse tree and pick out the
@@ -2067,20 +2067,25 @@ AlterTypeOwner(List *names, Oid newOwnerId)
20672067
*/
20682068
if (typTup->typowner != newOwnerId)
20692069
{
2070-
/* Otherwise, must be owner of the existing object */
2071-
if (!pg_type_ownercheck(HeapTupleGetOid(tup),GetUserId()))
2072-
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,
2073-
TypeNameToString(typename));
2074-
2075-
/* Must be able to become new owner */
2076-
check_is_member_of_role(GetUserId(), newOwnerId);
2077-
2078-
/* New owner must have CREATE privilege on namespace */
2079-
aclresult = pg_namespace_aclcheck(typTup->typnamespace, newOwnerId,
2080-
ACL_CREATE);
2081-
if (aclresult != ACLCHECK_OK)
2082-
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
2083-
get_namespace_name(typTup->typnamespace));
2070+
/* Superusers can always do it */
2071+
if (!superuser())
2072+
{
2073+
/* Otherwise, must be owner of the existing object */
2074+
if (!pg_type_ownercheck(HeapTupleGetOid(tup),GetUserId()))
2075+
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,
2076+
TypeNameToString(typename));
2077+
2078+
/* Must be able to become new owner */
2079+
check_is_member_of_role(GetUserId(), newOwnerId);
2080+
2081+
/* New owner must have CREATE privilege on namespace */
2082+
aclresult = pg_namespace_aclcheck(typTup->typnamespace,
2083+
newOwnerId,
2084+
ACL_CREATE);
2085+
if (aclresult != ACLCHECK_OK)
2086+
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
2087+
get_namespace_name(typTup->typnamespace));
2088+
}
20842089

20852090
/*
20862091
* Modify the owner --- okay to scribble on typTup because it's a

0 commit comments

Comments
 (0)