aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r--src/backend/optimizer/path/allpaths.c14
-rw-r--r--src/backend/optimizer/prep/prepjointree.c2
2 files changed, 16 insertions, 0 deletions
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 815b996a131..b3777eae2e4 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -744,6 +744,11 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
* pseudoconstant clauses; better to have the gating node above the
* subquery.
*
+ * Also, if the sub-query has "security_barrier" flag, it means the
+ * sub-query originated from a view that must enforce row-level security.
+ * We must not push down quals in order to avoid information leaks, either
+ * via side-effects or error output.
+ *
* Non-pushed-down clauses will get evaluated as qpquals of the
* SubqueryScan node.
*
@@ -762,7 +767,16 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
Node *clause = (Node *) rinfo->clause;
+ /*
+ * XXX. You might wonder why we're testing rte->security_barrier
+ * qual-by-qual here rather than hoisting the test up into the
+ * surrounding if statement; after all, the answer will be the
+ * same for all quals. The answer is that we expect to shortly
+ * change this logic to allow pushing down some quals that use only
+ * "leakproof" operators even through a security barrier.
+ */
if (!rinfo->pseudoconstant &&
+ !rte->security_barrier &&
qual_is_pushdown_safe(subquery, rti, clause, differentTypes))
{
/* Push it down */
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 8bb011b7116..a711c4f646b 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -543,6 +543,7 @@ pull_up_subqueries(PlannerInfo *root, Node *jtnode,
*/
if (rte->rtekind == RTE_SUBQUERY &&
is_simple_subquery(rte->subquery) &&
+ !rte->security_barrier &&
(containing_appendrel == NULL ||
is_safe_append_member(rte->subquery)))
return pull_up_simple_subquery(root, jtnode, rte,
@@ -712,6 +713,7 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
* pull_up_subqueries.
*/
if (is_simple_subquery(subquery) &&
+ !rte->security_barrier &&
(containing_appendrel == NULL || is_safe_append_member(subquery)))
{
/* good to go */