Skip to content

Commit 473626c

Browse files
committed
Handle RLS dependencies in inlined set-returning functions properly.
If an SRF in the FROM clause references a table having row-level security policies, and we inline that SRF into the calling query, we neglected to mark the plan as potentially dependent on which role is executing it. This could lead to later executions in the same session returning or hiding rows that should have been hidden or returned instead. Our thanks to Wolfgang Walther for reporting this problem. Stephen Frost and Tom Lane Security: CVE-2023-2455
1 parent 23cb8ea commit 473626c

File tree

3 files changed

+54
-0
lines changed

3 files changed

+54
-0
lines changed

src/backend/optimizer/util/clauses.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5342,6 +5342,13 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
53425342
*/
53435343
record_plan_function_dependency(root, func_oid);
53445344

5345+
/*
5346+
* We must also notice if the inserted query adds a dependency on the
5347+
* calling role due to RLS quals.
5348+
*/
5349+
if (querytree->hasRowSecurity)
5350+
root->glob->dependsOnRole = true;
5351+
53455352
return querytree;
53465353

53475354
/* Here if func is not inlinable: release temp memory and return NULL */

src/test/regress/expected/rowsecurity.out

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4039,6 +4039,33 @@ SELECT * FROM rls_tbl;
40394039

40404040
DROP TABLE rls_tbl;
40414041
RESET SESSION AUTHORIZATION;
4042+
-- CVE-2023-2455: inlining an SRF may introduce an RLS dependency
4043+
create table rls_t (c text);
4044+
insert into rls_t values ('invisible to bob');
4045+
alter table rls_t enable row level security;
4046+
grant select on rls_t to regress_rls_alice, regress_rls_bob;
4047+
create policy p1 on rls_t for select to regress_rls_alice using (true);
4048+
create policy p2 on rls_t for select to regress_rls_bob using (false);
4049+
create function rls_f () returns setof rls_t
4050+
stable language sql
4051+
as $$ select * from rls_t $$;
4052+
prepare q as select current_user, * from rls_f();
4053+
set role regress_rls_alice;
4054+
execute q;
4055+
current_user | c
4056+
-------------------+------------------
4057+
regress_rls_alice | invisible to bob
4058+
(1 row)
4059+
4060+
set role regress_rls_bob;
4061+
execute q;
4062+
current_user | c
4063+
--------------+---
4064+
(0 rows)
4065+
4066+
RESET ROLE;
4067+
DROP FUNCTION rls_f();
4068+
DROP TABLE rls_t;
40424069
--
40434070
-- Clean up objects
40444071
--

src/test/regress/sql/rowsecurity.sql

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,6 +1876,26 @@ SELECT * FROM rls_tbl;
18761876
DROP TABLE rls_tbl;
18771877
RESET SESSION AUTHORIZATION;
18781878

1879+
-- CVE-2023-2455: inlining an SRF may introduce an RLS dependency
1880+
create table rls_t (c text);
1881+
insert into rls_t values ('invisible to bob');
1882+
alter table rls_t enable row level security;
1883+
grant select on rls_t to regress_rls_alice, regress_rls_bob;
1884+
create policy p1 on rls_t for select to regress_rls_alice using (true);
1885+
create policy p2 on rls_t for select to regress_rls_bob using (false);
1886+
create function rls_f () returns setof rls_t
1887+
stable language sql
1888+
as $$ select * from rls_t $$;
1889+
prepare q as select current_user, * from rls_f();
1890+
set role regress_rls_alice;
1891+
execute q;
1892+
set role regress_rls_bob;
1893+
execute q;
1894+
1895+
RESET ROLE;
1896+
DROP FUNCTION rls_f();
1897+
DROP TABLE rls_t;
1898+
18791899
--
18801900
-- Clean up objects
18811901
--

0 commit comments

Comments
 (0)