]> granicus.if.org Git - postgresql/commitdiff
Perform RLS subquery checks as the right user when going via a view.
authorDean Rasheed <dean.a.rasheed@gmail.com>
Tue, 2 Apr 2019 07:19:09 +0000 (08:19 +0100)
committerDean Rasheed <dean.a.rasheed@gmail.com>
Tue, 2 Apr 2019 07:19:09 +0000 (08:19 +0100)
When accessing a table with RLS via a view, the RLS checks are
performed as the view owner. However, the code neglected to propagate
that to any subqueries in the RLS checks. Fix that by calling
setRuleCheckAsUser() for all RLS policy quals and withCheckOption
checks for RTEs with RLS.

Back-patch to 9.5 where RLS was added.

Per bug #15708 from daurnimator.

Discussion: https://postgr.es/m/15708-d65cab2ce9b1717a@postgresql.org

src/backend/rewrite/rowsecurity.c
src/test/regress/expected/rowsecurity.out
src/test/regress/sql/rowsecurity.sql

index 5bd33f7ba41e3db158bc72b7223f24ed973c4e53..72979b354fd3055c96419c98aed8196e989f56b2 100644 (file)
@@ -47,6 +47,7 @@
 #include "nodes/pg_list.h"
 #include "nodes/plannodes.h"
 #include "parser/parsetree.h"
+#include "rewrite/rewriteDefine.h"
 #include "rewrite/rewriteHandler.h"
 #include "rewrite/rewriteManip.h"
 #include "rewrite/rowsecurity.h"
@@ -381,6 +382,13 @@ get_row_security_policies(Query *root, RangeTblEntry *rte, int rt_index,
 
        heap_close(rel, NoLock);
 
+       /*
+        * Copy checkAsUser to the row security quals and WithCheckOption checks,
+        * in case they contain any subqueries referring to other relations.
+        */
+       setRuleCheckAsUser((Node *) *securityQuals, rte->checkAsUser);
+       setRuleCheckAsUser((Node *) *withCheckOptions, rte->checkAsUser);
+
        /*
         * Mark this query as having row security, so plancache can invalidate it
         * when necessary (eg: role changes)
index beb1129737d21c0fdb893bcf84ab73d184580024..3b211045f4d869152fd975eb27de8c8c6587274a 100644 (file)
@@ -3911,6 +3911,33 @@ DROP OWNED BY regress_rls_dob_role1;
 DROP POLICY p1 ON dob_t2; -- should succeed
 DROP USER regress_rls_dob_role1;
 DROP USER regress_rls_dob_role2;
+-- Bug #15708: view + table with RLS should check policies as view owner
+CREATE TABLE ref_tbl (a int);
+INSERT INTO ref_tbl VALUES (1);
+CREATE TABLE rls_tbl (a int);
+INSERT INTO rls_tbl VALUES (10);
+ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY;
+CREATE POLICY p1 ON rls_tbl USING (EXISTS (SELECT 1 FROM ref_tbl));
+GRANT SELECT ON ref_tbl TO regress_rls_bob;
+GRANT SELECT ON rls_tbl TO regress_rls_bob;
+CREATE VIEW rls_view AS SELECT * FROM rls_tbl;
+ALTER VIEW rls_view OWNER TO regress_rls_bob;
+GRANT SELECT ON rls_view TO regress_rls_alice;
+SET SESSION AUTHORIZATION regress_rls_alice;
+SELECT * FROM ref_tbl; -- Permission denied
+ERROR:  permission denied for relation ref_tbl
+SELECT * FROM rls_tbl; -- Permission denied
+ERROR:  permission denied for relation rls_tbl
+SELECT * FROM rls_view; -- OK
+ a  
+----
+ 10
+(1 row)
+
+RESET SESSION AUTHORIZATION;
+DROP VIEW rls_view;
+DROP TABLE rls_tbl;
+DROP TABLE ref_tbl;
 --
 -- Clean up objects
 --
index 5a9fdcad742b7e8f0416c3474e546c5678b931ff..21d6222d507074d2bf433849a8b2ca5bf8b6894b 100644 (file)
@@ -1767,6 +1767,32 @@ DROP POLICY p1 ON dob_t2; -- should succeed
 DROP USER regress_rls_dob_role1;
 DROP USER regress_rls_dob_role2;
 
+-- Bug #15708: view + table with RLS should check policies as view owner
+CREATE TABLE ref_tbl (a int);
+INSERT INTO ref_tbl VALUES (1);
+
+CREATE TABLE rls_tbl (a int);
+INSERT INTO rls_tbl VALUES (10);
+ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY;
+CREATE POLICY p1 ON rls_tbl USING (EXISTS (SELECT 1 FROM ref_tbl));
+
+GRANT SELECT ON ref_tbl TO regress_rls_bob;
+GRANT SELECT ON rls_tbl TO regress_rls_bob;
+
+CREATE VIEW rls_view AS SELECT * FROM rls_tbl;
+ALTER VIEW rls_view OWNER TO regress_rls_bob;
+GRANT SELECT ON rls_view TO regress_rls_alice;
+
+SET SESSION AUTHORIZATION regress_rls_alice;
+SELECT * FROM ref_tbl; -- Permission denied
+SELECT * FROM rls_tbl; -- Permission denied
+SELECT * FROM rls_view; -- OK
+RESET SESSION AUTHORIZATION;
+
+DROP VIEW rls_view;
+DROP TABLE rls_tbl;
+DROP TABLE ref_tbl;
+
 --
 -- Clean up objects
 --