diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index 77322a115f1..1d6ae8b4f3e 100644 --- a/src/backend/utils/adt/acl.c +++ b/src/backend/utils/adt/acl.c @@ -1230,11 +1230,11 @@ recursive_revoke(Acl *acl, if (grantee == ownerId) return acl; - /* The grantee might still have the privileges via another grantor */ + /* The grantee might still have some grant options via another grantor */ still_has = aclmask(acl, grantee, ownerId, ACL_GRANT_OPTION_FOR(revoke_privs), ACLMASK_ALL); - revoke_privs &= ~still_has; + revoke_privs &= ~ACL_OPTION_TO_PRIVS(still_has); if (revoke_privs == ACL_NO_RIGHTS) return acl; diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out index f99ebde33cc..e8930cb2eb5 100644 --- a/src/test/regress/expected/privileges.out +++ b/src/test/regress/expected/privileges.out @@ -1331,6 +1331,56 @@ SELECT has_function_privilege('regressuser1', 'testns.testfunc(int)', 'EXECUTE') SET client_min_messages TO 'warning'; DROP SCHEMA testns CASCADE; RESET client_min_messages; +-- test that dependent privileges are revoked (or not) properly +\c - +set session role regressuser1; +create table dep_priv_test (a int); +grant select on dep_priv_test to regressuser2 with grant option; +grant select on dep_priv_test to regressuser3 with grant option; +set session role regressuser2; +grant select on dep_priv_test to regressuser4 with grant option; +set session role regressuser3; +grant select on dep_priv_test to regressuser4 with grant option; +set session role regressuser4; +grant select on dep_priv_test to regressuser5; +\dp dep_priv_test + Access privileges + Schema | Name | Type | Access privileges | Column access privileges +--------+---------------+-------+-----------------------------------+-------------------------- + public | dep_priv_test | table | regressuser1=arwdDxt/regressuser1+| + | | | regressuser2=r*/regressuser1 +| + | | | regressuser3=r*/regressuser1 +| + | | | regressuser4=r*/regressuser2 +| + | | | regressuser4=r*/regressuser3 +| + | | | regressuser5=r/regressuser4 | +(1 row) + +set session role regressuser2; +revoke select on dep_priv_test from regressuser4 cascade; +\dp dep_priv_test + Access privileges + Schema | Name | Type | Access privileges | Column access privileges +--------+---------------+-------+-----------------------------------+-------------------------- + public | dep_priv_test | table | regressuser1=arwdDxt/regressuser1+| + | | | regressuser2=r*/regressuser1 +| + | | | regressuser3=r*/regressuser1 +| + | | | regressuser4=r*/regressuser3 +| + | | | regressuser5=r/regressuser4 | +(1 row) + +set session role regressuser3; +revoke select on dep_priv_test from regressuser4 cascade; +\dp dep_priv_test + Access privileges + Schema | Name | Type | Access privileges | Column access privileges +--------+---------------+-------+-----------------------------------+-------------------------- + public | dep_priv_test | table | regressuser1=arwdDxt/regressuser1+| + | | | regressuser2=r*/regressuser1 +| + | | | regressuser3=r*/regressuser1 | +(1 row) + +set session role regressuser1; +drop table dep_priv_test; -- clean up \c drop sequence x_seq; diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql index 3dd77a79179..d4d328e649f 100644 --- a/src/test/regress/sql/privileges.sql +++ b/src/test/regress/sql/privileges.sql @@ -795,6 +795,30 @@ DROP SCHEMA testns CASCADE; RESET client_min_messages; +-- test that dependent privileges are revoked (or not) properly +\c - + +set session role regressuser1; +create table dep_priv_test (a int); +grant select on dep_priv_test to regressuser2 with grant option; +grant select on dep_priv_test to regressuser3 with grant option; +set session role regressuser2; +grant select on dep_priv_test to regressuser4 with grant option; +set session role regressuser3; +grant select on dep_priv_test to regressuser4 with grant option; +set session role regressuser4; +grant select on dep_priv_test to regressuser5; +\dp dep_priv_test +set session role regressuser2; +revoke select on dep_priv_test from regressuser4 cascade; +\dp dep_priv_test +set session role regressuser3; +revoke select on dep_priv_test from regressuser4 cascade; +\dp dep_priv_test +set session role regressuser1; +drop table dep_priv_test; + + -- clean up \c