Commit b7aac362 authored by Stephen Frost's avatar Stephen Frost

Handle append_rel_list in expand_security_qual

During expand_security_quals, we take the security barrier quals on an
RTE and create a subquery which evaluates the quals.  During this, we
have to replace any variables in the outer query which refer to the
original RTE with references to the columns from the subquery.

We need to also perform that replacement for any Vars in the
append_rel_list.

Only backpatching to 9.5 as we only go through this process in 9.4 for
auto-updatable security barrier views, which UNION ALL queries aren't.

Discovered by Haribabu Kommi

Patch by Dean Rasheed
parent 94f5246c
...@@ -56,6 +56,12 @@ static bool security_barrier_replace_vars_walker(Node *node, ...@@ -56,6 +56,12 @@ static bool security_barrier_replace_vars_walker(Node *node,
* the others, providing protection against malicious user-defined security * the others, providing protection against malicious user-defined security
* barriers. The first security barrier qual in the list will be used in the * barriers. The first security barrier qual in the list will be used in the
* innermost subquery. * innermost subquery.
*
* In practice, the only RTEs that will have security barrier quals are those
* that refer to tables with row-level security, or which are the target
* relation of an update to an auto-updatable security barrier view. RTEs
* that read from a security barrier view will have already been expanded by
* the rewriter.
*/ */
void void
expand_security_quals(PlannerInfo *root, List *tlist) expand_security_quals(PlannerInfo *root, List *tlist)
...@@ -263,7 +269,8 @@ expand_security_qual(PlannerInfo *root, List *tlist, int rt_index, ...@@ -263,7 +269,8 @@ expand_security_qual(PlannerInfo *root, List *tlist, int rt_index,
* Replace any variables in the outer query that refer to the * Replace any variables in the outer query that refer to the
* original relation RTE with references to columns that we will * original relation RTE with references to columns that we will
* expose in the new subquery, building the subquery's targetlist * expose in the new subquery, building the subquery's targetlist
* as we go. * as we go. Also replace any references in the translated_vars
* lists of any appendrels.
*/ */
context.rt_index = rt_index; context.rt_index = rt_index;
context.sublevels_up = 0; context.sublevels_up = 0;
...@@ -274,6 +281,8 @@ expand_security_qual(PlannerInfo *root, List *tlist, int rt_index, ...@@ -274,6 +281,8 @@ expand_security_qual(PlannerInfo *root, List *tlist, int rt_index,
security_barrier_replace_vars((Node *) parse, &context); security_barrier_replace_vars((Node *) parse, &context);
security_barrier_replace_vars((Node *) tlist, &context); security_barrier_replace_vars((Node *) tlist, &context);
security_barrier_replace_vars((Node *) root->append_rel_list,
&context);
heap_close(context.rel, NoLock); heap_close(context.rel, NoLock);
......
...@@ -640,6 +640,26 @@ EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b) FOR SHARE; ...@@ -640,6 +640,26 @@ EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b) FOR SHARE;
Filter: ((a % 2) = 0) Filter: ((a % 2) = 0)
(12 rows) (12 rows)
-- union all query
SELECT a, b, oid FROM t2 UNION ALL SELECT a, b, oid FROM t3;
a | b | oid
---+-----+-----
1 | abc | 201
3 | cde | 203
1 | xxx | 301
2 | yyy | 302
3 | zzz | 303
(5 rows)
EXPLAIN (COSTS OFF) SELECT a, b, oid FROM t2 UNION ALL SELECT a, b, oid FROM t3;
QUERY PLAN
-------------------------------
Append
-> Seq Scan on t2
Filter: ((a % 2) = 1)
-> Seq Scan on t3
(4 rows)
-- superuser is allowed to bypass RLS checks -- superuser is allowed to bypass RLS checks
RESET SESSION AUTHORIZATION; RESET SESSION AUTHORIZATION;
SET row_security TO OFF; SET row_security TO OFF;
......
...@@ -255,6 +255,10 @@ EXPLAIN (COSTS OFF) SELECT * FROM t1 FOR SHARE; ...@@ -255,6 +255,10 @@ EXPLAIN (COSTS OFF) SELECT * FROM t1 FOR SHARE;
SELECT * FROM t1 WHERE f_leak(b) FOR SHARE; SELECT * FROM t1 WHERE f_leak(b) FOR SHARE;
EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b) FOR SHARE; EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b) FOR SHARE;
-- union all query
SELECT a, b, oid FROM t2 UNION ALL SELECT a, b, oid FROM t3;
EXPLAIN (COSTS OFF) SELECT a, b, oid FROM t2 UNION ALL SELECT a, b, oid FROM t3;
-- superuser is allowed to bypass RLS checks -- superuser is allowed to bypass RLS checks
RESET SESSION AUTHORIZATION; RESET SESSION AUTHORIZATION;
SET row_security TO OFF; SET row_security TO OFF;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment