diff options
author | Tom Lane | 2019-09-12 22:29:17 +0000 |
---|---|---|
committer | Tom Lane | 2019-09-12 22:29:45 +0000 |
commit | 7f1f72c44400e6fef3436b05f1ad0f6bacd03d96 (patch) | |
tree | 89910a625a6713e6761934906fb9040a835363b2 | |
parent | 614cdeaa8908f69ab0b97b688e9785147575c01f (diff) |
Fix usage of whole-row variables in WCO and RLS policy expressions.
Since WITH CHECK OPTION was introduced, ExecInitModifyTable has
initialized WCO expressions with the wrong plan node as parent -- that is,
it passed its input subplan not the ModifyTable node itself. Up to now
we thought this was harmless, but bug #16006 from Vinay Banakar shows it's
not: if the input node is a SubqueryScan then ExecInitWholeRowVar can get
confused into doing the wrong thing. (The fact that ExecInitWholeRowVar
contains such logic is certainly a horrid kluge that doesn't deserve to
live, but figuring out another way to do that is a task for some other day.)
Andres had already noticed the wrong-parent mistake and fixed it in commit
148e632c0, but not being aware of any user-visible consequences, he quite
reasonably didn't back-patch. This patch is simply a back-patch of
148e632c0, plus addition of a test case based on bug #16006. I also added
the test case to v12/HEAD, even though the bug is already fixed there.
Back-patch to all supported branches. 9.4 lacks RLS policies so the
new test case doesn't work there, but I'm pretty sure a test could be
devised based on using a whole-row Var in a plain WITH CHECK OPTION
condition. (I lack the cycles to do so myself, though.)
Andres Freund and Tom Lane
Discussion: https://postgr.es/m/[email protected]
Discussion: https://postgr.es/m/[email protected]
-rw-r--r-- | src/test/regress/expected/rowsecurity.out | 34 | ||||
-rw-r--r-- | src/test/regress/sql/rowsecurity.sql | 19 |
2 files changed, 53 insertions, 0 deletions
diff --git a/src/test/regress/expected/rowsecurity.out b/src/test/regress/expected/rowsecurity.out index aa3b083ee3..d01769299e 100644 --- a/src/test/regress/expected/rowsecurity.out +++ b/src/test/regress/expected/rowsecurity.out @@ -3958,6 +3958,40 @@ DROP OPERATOR <<< (int, int); DROP FUNCTION op_leak(int, int); RESET SESSION AUTHORIZATION; DROP TABLE rls_tbl; +-- Bug #16006: whole-row Vars in a policy don't play nice with sub-selects +SET SESSION AUTHORIZATION regress_rls_alice; +CREATE TABLE rls_tbl (a int, b int, c int); +CREATE POLICY p1 ON rls_tbl USING (rls_tbl >= ROW(1,1,1)); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +ALTER TABLE rls_tbl FORCE ROW LEVEL SECURITY; +INSERT INTO rls_tbl SELECT 10, 20, 30; +EXPLAIN (VERBOSE, COSTS OFF) +INSERT INTO rls_tbl + SELECT * FROM (SELECT b, c FROM rls_tbl ORDER BY a) ss; + QUERY PLAN +-------------------------------------------------------------------- + Insert on regress_rls_schema.rls_tbl + -> Subquery Scan on ss + Output: ss.b, ss.c, NULL::integer + -> Sort + Output: rls_tbl_1.b, rls_tbl_1.c, rls_tbl_1.a + Sort Key: rls_tbl_1.a + -> Seq Scan on regress_rls_schema.rls_tbl rls_tbl_1 + Output: rls_tbl_1.b, rls_tbl_1.c, rls_tbl_1.a + Filter: (rls_tbl_1.* >= '(1,1,1)'::record) +(9 rows) + +INSERT INTO rls_tbl + SELECT * FROM (SELECT b, c FROM rls_tbl ORDER BY a) ss; +SELECT * FROM rls_tbl; + a | b | c +----+----+---- + 10 | 20 | 30 + 20 | 30 | +(2 rows) + +DROP TABLE rls_tbl; +RESET SESSION AUTHORIZATION; -- -- Clean up objects -- diff --git a/src/test/regress/sql/rowsecurity.sql b/src/test/regress/sql/rowsecurity.sql index 679733051c..d7a5a36cf8 100644 --- a/src/test/regress/sql/rowsecurity.sql +++ b/src/test/regress/sql/rowsecurity.sql @@ -1810,6 +1810,25 @@ DROP FUNCTION op_leak(int, int); RESET SESSION AUTHORIZATION; DROP TABLE rls_tbl; +-- Bug #16006: whole-row Vars in a policy don't play nice with sub-selects +SET SESSION AUTHORIZATION regress_rls_alice; +CREATE TABLE rls_tbl (a int, b int, c int); +CREATE POLICY p1 ON rls_tbl USING (rls_tbl >= ROW(1,1,1)); + +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +ALTER TABLE rls_tbl FORCE ROW LEVEL SECURITY; + +INSERT INTO rls_tbl SELECT 10, 20, 30; +EXPLAIN (VERBOSE, COSTS OFF) +INSERT INTO rls_tbl + SELECT * FROM (SELECT b, c FROM rls_tbl ORDER BY a) ss; +INSERT INTO rls_tbl + SELECT * FROM (SELECT b, c FROM rls_tbl ORDER BY a) ss; +SELECT * FROM rls_tbl; + +DROP TABLE rls_tbl; +RESET SESSION AUTHORIZATION; + -- -- Clean up objects -- |