Invalidate acl.c caches when pg_authid changes.

This makes existing sessions reflect "ALTER ROLE ... [NO]INHERIT" as
quickly as they have been reflecting "GRANT role_name".  Back-patch to
9.5 (all supported versions).

Reviewed by Nathan Bossart.

Discussion: https://postgr.es/m/20201221095028.GB3777719@rfd.leadboat.com
This commit is contained in:
Noah Misch 2020-12-25 10:41:59 -08:00
parent f853ffa220
commit c966988060
3 changed files with 19 additions and 3 deletions

View File

@ -51,7 +51,6 @@ typedef struct
* role. In most of these tests the "given role" is the same, namely the * role. In most of these tests the "given role" is the same, namely the
* active current user. So we can optimize it by keeping a cached list of * active current user. So we can optimize it by keeping a cached list of
* all the roles the "given role" is a member of, directly or indirectly. * all the roles the "given role" is a member of, directly or indirectly.
* The cache is flushed whenever we detect a change in pg_auth_members.
* *
* There are actually two caches, one computed under "has_privs" rules * There are actually two caches, one computed under "has_privs" rules
* (do not recurse where rolinherit isn't true) and one computed under * (do not recurse where rolinherit isn't true) and one computed under
@ -4690,12 +4689,16 @@ initialize_acl(void)
if (!IsBootstrapProcessingMode()) if (!IsBootstrapProcessingMode())
{ {
/* /*
* In normal mode, set a callback on any syscache invalidation of * In normal mode, set a callback on any syscache invalidation of rows
* pg_auth_members rows * of pg_auth_members (for each AUTHMEM search in this file) or
* pg_authid (for has_rolinherit())
*/ */
CacheRegisterSyscacheCallback(AUTHMEMROLEMEM, CacheRegisterSyscacheCallback(AUTHMEMROLEMEM,
RoleMembershipCacheCallback, RoleMembershipCacheCallback,
(Datum) 0); (Datum) 0);
CacheRegisterSyscacheCallback(AUTHOID,
RoleMembershipCacheCallback,
(Datum) 0);
} }
} }

View File

@ -346,6 +346,13 @@ SET SESSION AUTHORIZATION regress_priv_user1;
SELECT * FROM atest3; -- fail SELECT * FROM atest3; -- fail
ERROR: permission denied for table atest3 ERROR: permission denied for table atest3
DELETE FROM atest3; -- ok DELETE FROM atest3; -- ok
BEGIN;
RESET SESSION AUTHORIZATION;
ALTER ROLE regress_priv_user1 NOINHERIT;
SET SESSION AUTHORIZATION regress_priv_user1;
DELETE FROM atest3;
ERROR: permission denied for table atest3
ROLLBACK;
-- views -- views
SET SESSION AUTHORIZATION regress_priv_user3; SET SESSION AUTHORIZATION regress_priv_user3;
CREATE VIEW atestv1 AS SELECT * FROM atest1; -- ok CREATE VIEW atestv1 AS SELECT * FROM atest1; -- ok

View File

@ -216,6 +216,12 @@ SET SESSION AUTHORIZATION regress_priv_user1;
SELECT * FROM atest3; -- fail SELECT * FROM atest3; -- fail
DELETE FROM atest3; -- ok DELETE FROM atest3; -- ok
BEGIN;
RESET SESSION AUTHORIZATION;
ALTER ROLE regress_priv_user1 NOINHERIT;
SET SESSION AUTHORIZATION regress_priv_user1;
DELETE FROM atest3;
ROLLBACK;
-- views -- views