mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-04 10:27:19 +02:00
Collect the global OR of hasRowSecurity flags for plancache
We carry around information about if a given query has row security or not to allow the plancache to use that information to invalidate a planned query in the event that the environment changes. Previously, the flag of one of the subqueries was simply being copied into place to indicate if the query overall included RLS components. That's wrong as we need the global OR of all subqueries. Fix by changing the code to match how fireRIRules works, which is results in OR'ing all of the flags. Noted by Tom. Back-patch to 9.5 where RLS was introduced.
This commit is contained in:
parent
2c24f0f092
commit
651e2ba74a
@ -1449,7 +1449,8 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
|
||||
* This may add new security barrier subquery RTEs to the rangetable.
|
||||
*/
|
||||
expand_security_quals(root, tlist);
|
||||
root->glob->hasRowSecurity = parse->hasRowSecurity;
|
||||
if (parse->hasRowSecurity)
|
||||
root->glob->hasRowSecurity = true;
|
||||
|
||||
/*
|
||||
* Locate any window functions in the tlist. (We don't need to look
|
||||
|
@ -2392,7 +2392,8 @@ extract_query_dependencies_walker(Node *node, PlannerInfo *context)
|
||||
ListCell *lc;
|
||||
|
||||
/* Collect row security information */
|
||||
context->glob->hasRowSecurity = query->hasRowSecurity;
|
||||
if (query->hasRowSecurity)
|
||||
context->glob->hasRowSecurity = true;
|
||||
|
||||
if (query->commandType == CMD_UTILITY)
|
||||
{
|
||||
|
@ -1649,7 +1649,8 @@ ERROR: new row violates row-level security policy for table "document"
|
||||
--
|
||||
SET SESSION AUTHORIZATION rls_regress_user0;
|
||||
CREATE TABLE z1 (a int, b text);
|
||||
GRANT SELECT ON z1 TO rls_regress_group1, rls_regress_group2,
|
||||
CREATE TABLE z2 (a int, b text);
|
||||
GRANT SELECT ON z1,z2 TO rls_regress_group1, rls_regress_group2,
|
||||
rls_regress_user1, rls_regress_user2;
|
||||
INSERT INTO z1 VALUES
|
||||
(1, 'aaa'),
|
||||
@ -1678,6 +1679,46 @@ EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b);
|
||||
Filter: ((a % 2) = 0)
|
||||
(4 rows)
|
||||
|
||||
PREPARE plancache_test AS SELECT * FROM z1 WHERE f_leak(b);
|
||||
EXPLAIN EXECUTE plancache_test;
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------
|
||||
Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36)
|
||||
Filter: f_leak(z1.b)
|
||||
-> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36)
|
||||
Filter: ((a % 2) = 0)
|
||||
(4 rows)
|
||||
|
||||
PREPARE plancache_test2 AS WITH q AS (SELECT * FROM z1 WHERE f_leak(b)) SELECT * FROM q,z2;
|
||||
EXPLAIN EXECUTE plancache_test2;
|
||||
QUERY PLAN
|
||||
-----------------------------------------------------------------------
|
||||
Nested Loop (cost=29.11..86.78 rows=2540 width=72)
|
||||
CTE q
|
||||
-> Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36)
|
||||
Filter: f_leak(z1.b)
|
||||
-> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36)
|
||||
Filter: ((a % 2) = 0)
|
||||
-> CTE Scan on q (cost=0.00..0.04 rows=2 width=36)
|
||||
-> Materialize (cost=0.00..29.05 rows=1270 width=36)
|
||||
-> Seq Scan on z2 (cost=0.00..22.70 rows=1270 width=36)
|
||||
(9 rows)
|
||||
|
||||
PREPARE plancache_test3 AS WITH q AS (SELECT * FROM z2) SELECT * FROM q,z1 WHERE f_leak(z1.b);
|
||||
EXPLAIN EXECUTE plancache_test3;
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------------
|
||||
Nested Loop (cost=22.70..108.97 rows=2540 width=72)
|
||||
CTE q
|
||||
-> Seq Scan on z2 (cost=0.00..22.70 rows=1270 width=36)
|
||||
-> CTE Scan on q (cost=0.00..25.40 rows=1270 width=36)
|
||||
-> Materialize (cost=0.00..29.12 rows=2 width=36)
|
||||
-> Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36)
|
||||
Filter: f_leak(z1.b)
|
||||
-> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36)
|
||||
Filter: ((a % 2) = 0)
|
||||
(9 rows)
|
||||
|
||||
SET ROLE rls_regress_group1;
|
||||
SELECT * FROM z1 WHERE f_leak(b);
|
||||
NOTICE: f_leak => bbb
|
||||
@ -1697,6 +1738,43 @@ EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b);
|
||||
Filter: ((a % 2) = 0)
|
||||
(4 rows)
|
||||
|
||||
EXPLAIN EXECUTE plancache_test;
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------
|
||||
Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36)
|
||||
Filter: f_leak(z1.b)
|
||||
-> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36)
|
||||
Filter: ((a % 2) = 0)
|
||||
(4 rows)
|
||||
|
||||
EXPLAIN EXECUTE plancache_test2;
|
||||
QUERY PLAN
|
||||
-----------------------------------------------------------------------
|
||||
Nested Loop (cost=29.11..86.78 rows=2540 width=72)
|
||||
CTE q
|
||||
-> Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36)
|
||||
Filter: f_leak(z1.b)
|
||||
-> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36)
|
||||
Filter: ((a % 2) = 0)
|
||||
-> CTE Scan on q (cost=0.00..0.04 rows=2 width=36)
|
||||
-> Materialize (cost=0.00..29.05 rows=1270 width=36)
|
||||
-> Seq Scan on z2 (cost=0.00..22.70 rows=1270 width=36)
|
||||
(9 rows)
|
||||
|
||||
EXPLAIN EXECUTE plancache_test3;
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------------
|
||||
Nested Loop (cost=22.70..108.97 rows=2540 width=72)
|
||||
CTE q
|
||||
-> Seq Scan on z2 (cost=0.00..22.70 rows=1270 width=36)
|
||||
-> CTE Scan on q (cost=0.00..25.40 rows=1270 width=36)
|
||||
-> Materialize (cost=0.00..29.12 rows=2 width=36)
|
||||
-> Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36)
|
||||
Filter: f_leak(z1.b)
|
||||
-> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36)
|
||||
Filter: ((a % 2) = 0)
|
||||
(9 rows)
|
||||
|
||||
SET SESSION AUTHORIZATION rls_regress_user2;
|
||||
SELECT * FROM z1 WHERE f_leak(b);
|
||||
NOTICE: f_leak => aaa
|
||||
@ -1716,6 +1794,43 @@ EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b);
|
||||
Filter: ((a % 2) = 1)
|
||||
(4 rows)
|
||||
|
||||
EXPLAIN EXECUTE plancache_test;
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------
|
||||
Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36)
|
||||
Filter: f_leak(z1.b)
|
||||
-> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36)
|
||||
Filter: ((a % 2) = 1)
|
||||
(4 rows)
|
||||
|
||||
EXPLAIN EXECUTE plancache_test2;
|
||||
QUERY PLAN
|
||||
-----------------------------------------------------------------------
|
||||
Nested Loop (cost=29.11..86.78 rows=2540 width=72)
|
||||
CTE q
|
||||
-> Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36)
|
||||
Filter: f_leak(z1.b)
|
||||
-> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36)
|
||||
Filter: ((a % 2) = 1)
|
||||
-> CTE Scan on q (cost=0.00..0.04 rows=2 width=36)
|
||||
-> Materialize (cost=0.00..29.05 rows=1270 width=36)
|
||||
-> Seq Scan on z2 (cost=0.00..22.70 rows=1270 width=36)
|
||||
(9 rows)
|
||||
|
||||
EXPLAIN EXECUTE plancache_test3;
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------------
|
||||
Nested Loop (cost=22.70..108.97 rows=2540 width=72)
|
||||
CTE q
|
||||
-> Seq Scan on z2 (cost=0.00..22.70 rows=1270 width=36)
|
||||
-> CTE Scan on q (cost=0.00..25.40 rows=1270 width=36)
|
||||
-> Materialize (cost=0.00..29.12 rows=2 width=36)
|
||||
-> Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36)
|
||||
Filter: f_leak(z1.b)
|
||||
-> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36)
|
||||
Filter: ((a % 2) = 1)
|
||||
(9 rows)
|
||||
|
||||
SET ROLE rls_regress_group2;
|
||||
SELECT * FROM z1 WHERE f_leak(b);
|
||||
NOTICE: f_leak => aaa
|
||||
@ -1735,6 +1850,43 @@ EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b);
|
||||
Filter: ((a % 2) = 1)
|
||||
(4 rows)
|
||||
|
||||
EXPLAIN EXECUTE plancache_test;
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------
|
||||
Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36)
|
||||
Filter: f_leak(z1.b)
|
||||
-> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36)
|
||||
Filter: ((a % 2) = 1)
|
||||
(4 rows)
|
||||
|
||||
EXPLAIN EXECUTE plancache_test2;
|
||||
QUERY PLAN
|
||||
-----------------------------------------------------------------------
|
||||
Nested Loop (cost=29.11..86.78 rows=2540 width=72)
|
||||
CTE q
|
||||
-> Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36)
|
||||
Filter: f_leak(z1.b)
|
||||
-> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36)
|
||||
Filter: ((a % 2) = 1)
|
||||
-> CTE Scan on q (cost=0.00..0.04 rows=2 width=36)
|
||||
-> Materialize (cost=0.00..29.05 rows=1270 width=36)
|
||||
-> Seq Scan on z2 (cost=0.00..22.70 rows=1270 width=36)
|
||||
(9 rows)
|
||||
|
||||
EXPLAIN EXECUTE plancache_test3;
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------------
|
||||
Nested Loop (cost=22.70..108.97 rows=2540 width=72)
|
||||
CTE q
|
||||
-> Seq Scan on z2 (cost=0.00..22.70 rows=1270 width=36)
|
||||
-> CTE Scan on q (cost=0.00..25.40 rows=1270 width=36)
|
||||
-> Materialize (cost=0.00..29.12 rows=2 width=36)
|
||||
-> Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36)
|
||||
Filter: f_leak(z1.b)
|
||||
-> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36)
|
||||
Filter: ((a % 2) = 1)
|
||||
(9 rows)
|
||||
|
||||
--
|
||||
-- Views should follow policy for view owner.
|
||||
--
|
||||
|
@ -629,8 +629,9 @@ INSERT INTO document VALUES (1, (SELECT cid from category WHERE cname = 'novel')
|
||||
--
|
||||
SET SESSION AUTHORIZATION rls_regress_user0;
|
||||
CREATE TABLE z1 (a int, b text);
|
||||
CREATE TABLE z2 (a int, b text);
|
||||
|
||||
GRANT SELECT ON z1 TO rls_regress_group1, rls_regress_group2,
|
||||
GRANT SELECT ON z1,z2 TO rls_regress_group1, rls_regress_group2,
|
||||
rls_regress_user1, rls_regress_user2;
|
||||
|
||||
INSERT INTO z1 VALUES
|
||||
@ -648,18 +649,39 @@ SET SESSION AUTHORIZATION rls_regress_user1;
|
||||
SELECT * FROM z1 WHERE f_leak(b);
|
||||
EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b);
|
||||
|
||||
PREPARE plancache_test AS SELECT * FROM z1 WHERE f_leak(b);
|
||||
EXPLAIN EXECUTE plancache_test;
|
||||
|
||||
PREPARE plancache_test2 AS WITH q AS (SELECT * FROM z1 WHERE f_leak(b)) SELECT * FROM q,z2;
|
||||
EXPLAIN EXECUTE plancache_test2;
|
||||
|
||||
PREPARE plancache_test3 AS WITH q AS (SELECT * FROM z2) SELECT * FROM q,z1 WHERE f_leak(z1.b);
|
||||
EXPLAIN EXECUTE plancache_test3;
|
||||
|
||||
SET ROLE rls_regress_group1;
|
||||
SELECT * FROM z1 WHERE f_leak(b);
|
||||
EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b);
|
||||
|
||||
EXPLAIN EXECUTE plancache_test;
|
||||
EXPLAIN EXECUTE plancache_test2;
|
||||
EXPLAIN EXECUTE plancache_test3;
|
||||
|
||||
SET SESSION AUTHORIZATION rls_regress_user2;
|
||||
SELECT * FROM z1 WHERE f_leak(b);
|
||||
EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b);
|
||||
|
||||
EXPLAIN EXECUTE plancache_test;
|
||||
EXPLAIN EXECUTE plancache_test2;
|
||||
EXPLAIN EXECUTE plancache_test3;
|
||||
|
||||
SET ROLE rls_regress_group2;
|
||||
SELECT * FROM z1 WHERE f_leak(b);
|
||||
EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b);
|
||||
|
||||
EXPLAIN EXECUTE plancache_test;
|
||||
EXPLAIN EXECUTE plancache_test2;
|
||||
EXPLAIN EXECUTE plancache_test3;
|
||||
|
||||
--
|
||||
-- Views should follow policy for view owner.
|
||||
--
|
||||
|
Loading…
Reference in New Issue
Block a user