Change the way ACL are checked whe locking shard

In `EnsureTablePermissions()`, which is used in `lock_shard_resources()`
but also in few other places, citus does check the ACL at the table
level but is not examining attributes ACL.
It prevents GRANT INSERT/UPDATE(col) to work as citus requires to lock
shared but this GRANT is not a table lock.

Change the behavior to check attributes ACL also.

Other usage:

* `Datum get_shard_id_for_distribution_column()`, looks safe.
* `Datum master_create_empty_shard()`, in this case it is apparently
  really required to be more careful. This is managed in the next
  commit.
pull/7918/head
Cédric Villemain 2025-03-17 14:43:28 +01:00
parent 0338d0af32
commit 196f6af27a
1 changed files with 15 additions and 2 deletions

View File

@ -2428,14 +2428,27 @@ UpdateNoneDistTableMetadata(Oid relationId, char replicationModel, uint32 coloca
/*
* Check that the current user has `mode` permissions on relationId, error out
* if not. Superusers always have such permissions.
* Check that the current user has `mode` permissions on relationId or on at
* least one relationId's attribute, error out if not.
* Superusers always have such permissions.
*/
void
EnsureTablePermissions(Oid relationId, AclMode mode)
{
AclResult aclresult = pg_class_aclcheck(relationId, GetUserId(), mode);
if (aclresult == ACLCHECK_OK)
{
return;
}
/*
* Also check the attributes: for example "GRANT ALL(a)" has no table level
* right but user is still allowed to lock table as needed. PostgreSQL will
* still enforce ACL later so it's safe.
*/
aclresult = pg_attribute_aclcheck_all(relationId, GetUserId(), mode, ACLMASK_ANY);
if (aclresult != ACLCHECK_OK)
{
aclcheck_error(aclresult, OBJECT_TABLE, get_rel_name(relationId));