Skip to content

Commit a30531c

Browse files
committed
Fix "unexpected relkind" error when denying permissions on toast tables.
get_relkind_objtype, and hence get_object_type, failed when applied to a toast table. This is not a good thing, because it prevents reporting of perfectly legitimate permissions errors. (At present, these functions are in fact *only* used to determine the ObjectType argument for acl_error() calls.) It seems best to have them fall back to returning OBJECT_TABLE in every case where they can't determine an object type for a pg_class entry, so do that. In passing, make some edits to alter.c to make it more obvious that those calls of get_object_type() are used only for error reporting. This might save a few cycles in the non-error code path, too. Back-patch to v11 where this issue originated. John Hsu, Michael Paquier, Tom Lane Discussion: https://postgr.es/m/C652D3DF-2B0C-4128-9420-FB5379F6B1E4@amazon.com
1 parent 529ebb2 commit a30531c

File tree

4 files changed

+42
-14
lines changed

4 files changed

+42
-14
lines changed

src/backend/catalog/objectaddress.c

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2612,6 +2612,13 @@ get_object_attnum_acl(Oid class_id)
26122612
return prop->attnum_acl;
26132613
}
26142614

2615+
/*
2616+
* get_object_type
2617+
*
2618+
* Return the object type associated with a given object. This routine
2619+
* is primarily used to determine the object type to mention in ACL check
2620+
* error messages, so it's desirable for it to avoid failing.
2621+
*/
26152622
ObjectType
26162623
get_object_type(Oid class_id, Oid object_id)
26172624
{
@@ -5333,6 +5340,16 @@ strlist_to_textarray(List *list)
53335340
return arr;
53345341
}
53355342

5343+
/*
5344+
* get_relkind_objtype
5345+
*
5346+
* Return the object type for the relkind given by the caller.
5347+
*
5348+
* If an unexpected relkind is passed, we say OBJECT_TABLE rather than
5349+
* failing. That's because this is mostly used for generating error messages
5350+
* for failed ACL checks on relations, and we'd rather produce a generic
5351+
* message saying "table" than fail entirely.
5352+
*/
53365353
ObjectType
53375354
get_relkind_objtype(char relkind)
53385355
{
@@ -5352,13 +5369,10 @@ get_relkind_objtype(char relkind)
53525369
return OBJECT_MATVIEW;
53535370
case RELKIND_FOREIGN_TABLE:
53545371
return OBJECT_FOREIGN_TABLE;
5355-
5356-
/*
5357-
* other relkinds are not supported here because they don't map to
5358-
* OBJECT_* values
5359-
*/
5372+
case RELKIND_TOASTVALUE:
5373+
return OBJECT_TABLE;
53605374
default:
5361-
elog(ERROR, "unexpected relkind: %d", relkind);
5362-
return 0;
5375+
/* Per above, don't raise an error */
5376+
return OBJECT_TABLE;
53635377
}
53645378
}

src/backend/commands/alter.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,6 @@ AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name)
172172
AttrNumber Anum_name = get_object_attnum_name(classId);
173173
AttrNumber Anum_namespace = get_object_attnum_namespace(classId);
174174
AttrNumber Anum_owner = get_object_attnum_owner(classId);
175-
ObjectType objtype = get_object_type(classId, objectId);
176175
HeapTuple oldtup;
177176
HeapTuple newtup;
178177
Datum datum;
@@ -224,7 +223,8 @@ AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name)
224223
ownerId = DatumGetObjectId(datum);
225224

226225
if (!has_privs_of_role(GetUserId(), DatumGetObjectId(ownerId)))
227-
aclcheck_error(ACLCHECK_NOT_OWNER, objtype, old_name);
226+
aclcheck_error(ACLCHECK_NOT_OWNER, get_object_type(classId, objectId),
227+
old_name);
228228

229229
/* User must have CREATE privilege on the namespace */
230230
if (OidIsValid(namespaceId))
@@ -670,7 +670,6 @@ AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid)
670670
AttrNumber Anum_name = get_object_attnum_name(classId);
671671
AttrNumber Anum_namespace = get_object_attnum_namespace(classId);
672672
AttrNumber Anum_owner = get_object_attnum_owner(classId);
673-
ObjectType objtype = get_object_type(classId, objid);
674673
Oid oldNspOid;
675674
Datum name,
676675
namespace;
@@ -726,7 +725,7 @@ AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid)
726725
ownerId = DatumGetObjectId(owner);
727726

728727
if (!has_privs_of_role(GetUserId(), ownerId))
729-
aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
728+
aclcheck_error(ACLCHECK_NOT_OWNER, get_object_type(classId, objid),
730729
NameStr(*(DatumGetName(name))));
731730

732731
/* User must have CREATE privilege on new namespace */
@@ -950,8 +949,6 @@ AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId)
950949
/* Superusers can bypass permission checks */
951950
if (!superuser())
952951
{
953-
ObjectType objtype = get_object_type(classId, objectId);
954-
955952
/* must be owner */
956953
if (!has_privs_of_role(GetUserId(), old_ownerId))
957954
{
@@ -970,7 +967,8 @@ AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId)
970967
snprintf(namebuf, sizeof(namebuf), "%u", objectId);
971968
objname = namebuf;
972969
}
973-
aclcheck_error(ACLCHECK_NOT_OWNER, objtype, objname);
970+
aclcheck_error(ACLCHECK_NOT_OWNER, get_object_type(classId, objectId),
971+
objname);
974972
}
975973
/* Must be able to become new owner */
976974
check_is_member_of_role(GetUserId(), new_ownerId);

src/test/regress/expected/create_index.out

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2434,8 +2434,17 @@ CREATE ROLE regress_reindexuser NOLOGIN;
24342434
SET SESSION ROLE regress_reindexuser;
24352435
REINDEX SCHEMA schema_to_reindex;
24362436
ERROR: must be owner of schema schema_to_reindex
2437+
-- Permission failures with toast tables and indexes (pg_authid here)
2438+
RESET ROLE;
2439+
GRANT USAGE ON SCHEMA pg_toast TO regress_reindexuser;
2440+
SET SESSION ROLE regress_reindexuser;
2441+
REINDEX TABLE pg_toast.pg_toast_1260;
2442+
ERROR: must be owner of table pg_toast_1260
2443+
REINDEX INDEX pg_toast.pg_toast_1260_index;
2444+
ERROR: must be owner of index pg_toast_1260_index
24372445
-- Clean up
24382446
RESET ROLE;
2447+
REVOKE USAGE ON SCHEMA pg_toast FROM regress_reindexuser;
24392448
DROP ROLE regress_reindexuser;
24402449
DROP SCHEMA schema_to_reindex CASCADE;
24412450
NOTICE: drop cascades to 6 other objects

src/test/regress/sql/create_index.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,8 +1003,15 @@ REINDEX SCHEMA CONCURRENTLY schema_to_reindex;
10031003
CREATE ROLE regress_reindexuser NOLOGIN;
10041004
SET SESSION ROLE regress_reindexuser;
10051005
REINDEX SCHEMA schema_to_reindex;
1006+
-- Permission failures with toast tables and indexes (pg_authid here)
1007+
RESET ROLE;
1008+
GRANT USAGE ON SCHEMA pg_toast TO regress_reindexuser;
1009+
SET SESSION ROLE regress_reindexuser;
1010+
REINDEX TABLE pg_toast.pg_toast_1260;
1011+
REINDEX INDEX pg_toast.pg_toast_1260_index;
10061012

10071013
-- Clean up
10081014
RESET ROLE;
1015+
REVOKE USAGE ON SCHEMA pg_toast FROM regress_reindexuser;
10091016
DROP ROLE regress_reindexuser;
10101017
DROP SCHEMA schema_to_reindex CASCADE;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy