Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit e5e11c8

Browse files
committed
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.
1 parent db81329 commit e5e11c8

File tree

4 files changed

+180
-4
lines changed

4 files changed

+180
-4
lines changed

src/backend/optimizer/plan/planner.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -1529,7 +1529,8 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
15291529
* This may add new security barrier subquery RTEs to the rangetable.
15301530
*/
15311531
expand_security_quals(root, tlist);
1532-
root->glob->hasRowSecurity = parse->hasRowSecurity;
1532+
if (parse->hasRowSecurity)
1533+
root->glob->hasRowSecurity = true;
15331534

15341535
/*
15351536
* Locate any window functions in the tlist. (We don't need to look

src/backend/optimizer/plan/setrefs.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -2401,7 +2401,8 @@ extract_query_dependencies_walker(Node *node, PlannerInfo *context)
24012401
ListCell *lc;
24022402

24032403
/* Collect row security information */
2404-
context->glob->hasRowSecurity = query->hasRowSecurity;
2404+
if (query->hasRowSecurity)
2405+
context->glob->hasRowSecurity = true;
24052406

24062407
if (query->commandType == CMD_UTILITY)
24072408
{

src/test/regress/expected/rowsecurity.out

+153-1
Original file line numberDiff line numberDiff line change
@@ -1649,7 +1649,8 @@ ERROR: new row violates row-level security policy for table "document"
16491649
--
16501650
SET SESSION AUTHORIZATION rls_regress_user0;
16511651
CREATE TABLE z1 (a int, b text);
1652-
GRANT SELECT ON z1 TO rls_regress_group1, rls_regress_group2,
1652+
CREATE TABLE z2 (a int, b text);
1653+
GRANT SELECT ON z1,z2 TO rls_regress_group1, rls_regress_group2,
16531654
rls_regress_user1, rls_regress_user2;
16541655
INSERT INTO z1 VALUES
16551656
(1, 'aaa'),
@@ -1678,6 +1679,46 @@ EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b);
16781679
Filter: ((a % 2) = 0)
16791680
(4 rows)
16801681

1682+
PREPARE plancache_test AS SELECT * FROM z1 WHERE f_leak(b);
1683+
EXPLAIN EXECUTE plancache_test;
1684+
QUERY PLAN
1685+
---------------------------------------------------------------
1686+
Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36)
1687+
Filter: f_leak(z1.b)
1688+
-> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36)
1689+
Filter: ((a % 2) = 0)
1690+
(4 rows)
1691+
1692+
PREPARE plancache_test2 AS WITH q AS (SELECT * FROM z1 WHERE f_leak(b)) SELECT * FROM q,z2;
1693+
EXPLAIN EXECUTE plancache_test2;
1694+
QUERY PLAN
1695+
-----------------------------------------------------------------------
1696+
Nested Loop (cost=29.11..86.78 rows=2540 width=72)
1697+
CTE q
1698+
-> Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36)
1699+
Filter: f_leak(z1.b)
1700+
-> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36)
1701+
Filter: ((a % 2) = 0)
1702+
-> CTE Scan on q (cost=0.00..0.04 rows=2 width=36)
1703+
-> Materialize (cost=0.00..29.05 rows=1270 width=36)
1704+
-> Seq Scan on z2 (cost=0.00..22.70 rows=1270 width=36)
1705+
(9 rows)
1706+
1707+
PREPARE plancache_test3 AS WITH q AS (SELECT * FROM z2) SELECT * FROM q,z1 WHERE f_leak(z1.b);
1708+
EXPLAIN EXECUTE plancache_test3;
1709+
QUERY PLAN
1710+
---------------------------------------------------------------------------
1711+
Nested Loop (cost=22.70..108.97 rows=2540 width=72)
1712+
CTE q
1713+
-> Seq Scan on z2 (cost=0.00..22.70 rows=1270 width=36)
1714+
-> CTE Scan on q (cost=0.00..25.40 rows=1270 width=36)
1715+
-> Materialize (cost=0.00..29.12 rows=2 width=36)
1716+
-> Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36)
1717+
Filter: f_leak(z1.b)
1718+
-> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36)
1719+
Filter: ((a % 2) = 0)
1720+
(9 rows)
1721+
16811722
SET ROLE rls_regress_group1;
16821723
SELECT * FROM z1 WHERE f_leak(b);
16831724
NOTICE: f_leak => bbb
@@ -1697,6 +1738,43 @@ EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b);
16971738
Filter: ((a % 2) = 0)
16981739
(4 rows)
16991740

1741+
EXPLAIN EXECUTE plancache_test;
1742+
QUERY PLAN
1743+
---------------------------------------------------------------
1744+
Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36)
1745+
Filter: f_leak(z1.b)
1746+
-> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36)
1747+
Filter: ((a % 2) = 0)
1748+
(4 rows)
1749+
1750+
EXPLAIN EXECUTE plancache_test2;
1751+
QUERY PLAN
1752+
-----------------------------------------------------------------------
1753+
Nested Loop (cost=29.11..86.78 rows=2540 width=72)
1754+
CTE q
1755+
-> Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36)
1756+
Filter: f_leak(z1.b)
1757+
-> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36)
1758+
Filter: ((a % 2) = 0)
1759+
-> CTE Scan on q (cost=0.00..0.04 rows=2 width=36)
1760+
-> Materialize (cost=0.00..29.05 rows=1270 width=36)
1761+
-> Seq Scan on z2 (cost=0.00..22.70 rows=1270 width=36)
1762+
(9 rows)
1763+
1764+
EXPLAIN EXECUTE plancache_test3;
1765+
QUERY PLAN
1766+
---------------------------------------------------------------------------
1767+
Nested Loop (cost=22.70..108.97 rows=2540 width=72)
1768+
CTE q
1769+
-> Seq Scan on z2 (cost=0.00..22.70 rows=1270 width=36)
1770+
-> CTE Scan on q (cost=0.00..25.40 rows=1270 width=36)
1771+
-> Materialize (cost=0.00..29.12 rows=2 width=36)
1772+
-> Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36)
1773+
Filter: f_leak(z1.b)
1774+
-> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36)
1775+
Filter: ((a % 2) = 0)
1776+
(9 rows)
1777+
17001778
SET SESSION AUTHORIZATION rls_regress_user2;
17011779
SELECT * FROM z1 WHERE f_leak(b);
17021780
NOTICE: f_leak => aaa
@@ -1716,6 +1794,43 @@ EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b);
17161794
Filter: ((a % 2) = 1)
17171795
(4 rows)
17181796

1797+
EXPLAIN EXECUTE plancache_test;
1798+
QUERY PLAN
1799+
---------------------------------------------------------------
1800+
Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36)
1801+
Filter: f_leak(z1.b)
1802+
-> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36)
1803+
Filter: ((a % 2) = 1)
1804+
(4 rows)
1805+
1806+
EXPLAIN EXECUTE plancache_test2;
1807+
QUERY PLAN
1808+
-----------------------------------------------------------------------
1809+
Nested Loop (cost=29.11..86.78 rows=2540 width=72)
1810+
CTE q
1811+
-> Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36)
1812+
Filter: f_leak(z1.b)
1813+
-> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36)
1814+
Filter: ((a % 2) = 1)
1815+
-> CTE Scan on q (cost=0.00..0.04 rows=2 width=36)
1816+
-> Materialize (cost=0.00..29.05 rows=1270 width=36)
1817+
-> Seq Scan on z2 (cost=0.00..22.70 rows=1270 width=36)
1818+
(9 rows)
1819+
1820+
EXPLAIN EXECUTE plancache_test3;
1821+
QUERY PLAN
1822+
---------------------------------------------------------------------------
1823+
Nested Loop (cost=22.70..108.97 rows=2540 width=72)
1824+
CTE q
1825+
-> Seq Scan on z2 (cost=0.00..22.70 rows=1270 width=36)
1826+
-> CTE Scan on q (cost=0.00..25.40 rows=1270 width=36)
1827+
-> Materialize (cost=0.00..29.12 rows=2 width=36)
1828+
-> Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36)
1829+
Filter: f_leak(z1.b)
1830+
-> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36)
1831+
Filter: ((a % 2) = 1)
1832+
(9 rows)
1833+
17191834
SET ROLE rls_regress_group2;
17201835
SELECT * FROM z1 WHERE f_leak(b);
17211836
NOTICE: f_leak => aaa
@@ -1735,6 +1850,43 @@ EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b);
17351850
Filter: ((a % 2) = 1)
17361851
(4 rows)
17371852

1853+
EXPLAIN EXECUTE plancache_test;
1854+
QUERY PLAN
1855+
---------------------------------------------------------------
1856+
Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36)
1857+
Filter: f_leak(z1.b)
1858+
-> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36)
1859+
Filter: ((a % 2) = 1)
1860+
(4 rows)
1861+
1862+
EXPLAIN EXECUTE plancache_test2;
1863+
QUERY PLAN
1864+
-----------------------------------------------------------------------
1865+
Nested Loop (cost=29.11..86.78 rows=2540 width=72)
1866+
CTE q
1867+
-> Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36)
1868+
Filter: f_leak(z1.b)
1869+
-> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36)
1870+
Filter: ((a % 2) = 1)
1871+
-> CTE Scan on q (cost=0.00..0.04 rows=2 width=36)
1872+
-> Materialize (cost=0.00..29.05 rows=1270 width=36)
1873+
-> Seq Scan on z2 (cost=0.00..22.70 rows=1270 width=36)
1874+
(9 rows)
1875+
1876+
EXPLAIN EXECUTE plancache_test3;
1877+
QUERY PLAN
1878+
---------------------------------------------------------------------------
1879+
Nested Loop (cost=22.70..108.97 rows=2540 width=72)
1880+
CTE q
1881+
-> Seq Scan on z2 (cost=0.00..22.70 rows=1270 width=36)
1882+
-> CTE Scan on q (cost=0.00..25.40 rows=1270 width=36)
1883+
-> Materialize (cost=0.00..29.12 rows=2 width=36)
1884+
-> Subquery Scan on z1 (cost=0.00..29.11 rows=2 width=36)
1885+
Filter: f_leak(z1.b)
1886+
-> Seq Scan on z1 z1_1 (cost=0.00..29.05 rows=6 width=36)
1887+
Filter: ((a % 2) = 1)
1888+
(9 rows)
1889+
17381890
--
17391891
-- Views should follow policy for view owner.
17401892
--

src/test/regress/sql/rowsecurity.sql

+23-1
Original file line numberDiff line numberDiff line change
@@ -629,8 +629,9 @@ INSERT INTO document VALUES (1, (SELECT cid from category WHERE cname = 'novel')
629629
--
630630
SET SESSION AUTHORIZATION rls_regress_user0;
631631
CREATE TABLE z1 (a int, b text);
632+
CREATE TABLE z2 (a int, b text);
632633

633-
GRANT SELECT ON z1 TO rls_regress_group1, rls_regress_group2,
634+
GRANT SELECT ON z1,z2 TO rls_regress_group1, rls_regress_group2,
634635
rls_regress_user1, rls_regress_user2;
635636

636637
INSERT INTO z1 VALUES
@@ -648,18 +649,39 @@ SET SESSION AUTHORIZATION rls_regress_user1;
648649
SELECT * FROM z1 WHERE f_leak(b);
649650
EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b);
650651

652+
PREPARE plancache_test AS SELECT * FROM z1 WHERE f_leak(b);
653+
EXPLAIN EXECUTE plancache_test;
654+
655+
PREPARE plancache_test2 AS WITH q AS (SELECT * FROM z1 WHERE f_leak(b)) SELECT * FROM q,z2;
656+
EXPLAIN EXECUTE plancache_test2;
657+
658+
PREPARE plancache_test3 AS WITH q AS (SELECT * FROM z2) SELECT * FROM q,z1 WHERE f_leak(z1.b);
659+
EXPLAIN EXECUTE plancache_test3;
660+
651661
SET ROLE rls_regress_group1;
652662
SELECT * FROM z1 WHERE f_leak(b);
653663
EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b);
654664

665+
EXPLAIN EXECUTE plancache_test;
666+
EXPLAIN EXECUTE plancache_test2;
667+
EXPLAIN EXECUTE plancache_test3;
668+
655669
SET SESSION AUTHORIZATION rls_regress_user2;
656670
SELECT * FROM z1 WHERE f_leak(b);
657671
EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b);
658672

673+
EXPLAIN EXECUTE plancache_test;
674+
EXPLAIN EXECUTE plancache_test2;
675+
EXPLAIN EXECUTE plancache_test3;
676+
659677
SET ROLE rls_regress_group2;
660678
SELECT * FROM z1 WHERE f_leak(b);
661679
EXPLAIN (COSTS OFF) SELECT * FROM z1 WHERE f_leak(b);
662680

681+
EXPLAIN EXECUTE plancache_test;
682+
EXPLAIN EXECUTE plancache_test2;
683+
EXPLAIN EXECUTE plancache_test3;
684+
663685
--
664686
-- Views should follow policy for view owner.
665687
--

0 commit comments

Comments
 (0)