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:22:48 +0000 (08:22 +0100)
committerDean Rasheed <dean.a.rasheed@gmail.com>
Tue, 2 Apr 2019 07:22:48 +0000 (08:22 +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 4a228b9e15849e960771613391c4d0297f69fa03..b794e7365e9156ecbbbba26859333c411e879f34 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"
@@ -378,6 +379,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 91ad2f2f87dc07875a3c8050432735b67dd8b87c..f3f7afaa53f84361d3442d09420425592c6baebf 100644 (file)
@@ -3463,6 +3463,37 @@ DROP OWNED BY dob_role1;
 DROP POLICY p1 ON dob_t1; -- should succeed
 DROP USER dob_role1;
 DROP USER dob_role2;
+-- Bug #15708: view + table with RLS should check policies as view owner
+CREATE USER regress_rls_alice NOLOGIN;
+CREATE USER regress_rls_bob NOLOGIN;
+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;
+DROP USER regress_rls_alice;
+DROP USER regress_rls_bob;
 --
 -- Clean up objects
 --
index 8e14cc0dca70fcc32029d3548c733cc8480a4800..fb12d02ba922252e32e2b7e7d6cae44dc08a7834 100644 (file)
@@ -1575,6 +1575,37 @@ DROP POLICY p1 ON dob_t1; -- should succeed
 DROP USER dob_role1;
 DROP USER dob_role2;
 
+-- Bug #15708: view + table with RLS should check policies as view owner
+CREATE USER regress_rls_alice NOLOGIN;
+CREATE USER regress_rls_bob NOLOGIN;
+
+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;
+DROP USER regress_rls_alice;
+DROP USER regress_rls_bob;
+
 --
 -- Clean up objects
 --