aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/optimizer/prep/prepjointree.c3
-rw-r--r--src/backend/rewrite/rewriteHandler.c32
-rw-r--r--src/include/nodes/parsenodes.h9
3 files changed, 36 insertions, 8 deletions
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 878db9b4ab7..b6812303498 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -1187,6 +1187,9 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
*/
parse->hasSubLinks |= subquery->hasSubLinks;
+ /* If subquery had any RLS conditions, now main query does too */
+ parse->hasRowSecurity |= subquery->hasRowSecurity;
+
/*
* subquery won't be pulled up if it hasAggs, hasWindowFuncs, or
* hasTargetSRFs, so no work needed on those flags
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index b828e3cb077..65c3d6e0814 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -447,6 +447,15 @@ rewriteRuleAction(Query *parsetree,
}
/*
+ * Also, we might have absorbed some RTEs with RLS conditions into the
+ * sub_action. If so, mark it as hasRowSecurity, whether or not those
+ * RTEs will be referenced after we finish rewriting. (Note: currently
+ * this is a no-op because RLS conditions aren't added till later, but it
+ * seems like good future-proofing to do this anyway.)
+ */
+ sub_action->hasRowSecurity |= parsetree->hasRowSecurity;
+
+ /*
* Each rule action's jointree should be the main parsetree's jointree
* plus that rule's jointree, but usually *without* the original rtindex
* that we're replacing (if present, which it won't be for INSERT). Note
@@ -1835,10 +1844,10 @@ fireRIRrules(Query *parsetree, List *activeRIRs, bool forUpdatePushedDown)
}
/*
- * Add the new security quals to the start of the RTE's list so
- * that they get applied before any existing security quals (which
- * might have come from a user-written security barrier view, and
- * might contain malicious code).
+ * Add the new security barrier quals to the start of the RTE's
+ * list so that they get applied before any existing barrier quals
+ * (which would have come from a security-barrier view, and should
+ * get lower priority than RLS conditions on the table itself).
*/
rte->securityQuals = list_concat(securityQuals,
rte->securityQuals);
@@ -2957,9 +2966,9 @@ rewriteTargetView(Query *parsetree, Relation view)
* only adjust their varnos to reference the new target (just the same as
* we did with the view targetlist).
*
- * Note that there is special-case handling for the quals of a security
- * barrier view, since they need to be kept separate from any
- * user-supplied quals, so these quals are kept on the new target RTE.
+ * If it's a security-barrier view, its WHERE quals must be applied before
+ * quals from the outer query, so we attach them to the RTE as security
+ * barrier quals rather than adding them to the main WHERE clause.
*
* For INSERT, the view's quals can be ignored in the main query.
*/
@@ -2980,6 +2989,10 @@ rewriteTargetView(Query *parsetree, Relation view)
if (RelationIsSecurityView(view))
{
/*
+ * The view's quals go in front of existing barrier quals: those
+ * would have come from an outer level of security-barrier view,
+ * and so must get evaluated later.
+ *
* Note: the parsetree has been mutated, so the new_rte pointer is
* stale and needs to be re-computed.
*/
@@ -2987,6 +3000,11 @@ rewriteTargetView(Query *parsetree, Relation view)
new_rte->securityQuals = lcons(viewqual, new_rte->securityQuals);
/*
+ * Do not set parsetree->hasRowSecurity, because these aren't RLS
+ * conditions (they aren't affected by enabling/disabling RLS).
+ */
+
+ /*
* Make sure that the query is marked correctly if the added qual
* has sublinks.
*/
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 9b600a5f76d..04b1c2f2d43 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -775,6 +775,13 @@ typedef struct XmlSerialize
* FirstLowInvalidHeapAttributeNumber from column numbers before storing
* them in these fields. A whole-row Var reference is represented by
* setting the bit for InvalidAttrNumber.
+ *
+ * securityQuals is a list of security barrier quals (boolean expressions),
+ * to be tested in the listed order before returning a row from the
+ * relation. It is always NIL in parser output. Entries are added by the
+ * rewriter to implement security-barrier views and/or row-level security.
+ * Note that the planner turns each boolean expression into an implicitly
+ * AND'ed sublist, as is its usual habit with qualification expressions.
*--------------------
*/
typedef enum RTEKind
@@ -872,7 +879,7 @@ typedef struct RangeTblEntry
Bitmapset *selectedCols; /* columns needing SELECT permission */
Bitmapset *insertedCols; /* columns needing INSERT permission */
Bitmapset *updatedCols; /* columns needing UPDATE permission */
- List *securityQuals; /* any security barrier quals to apply */
+ List *securityQuals; /* security barrier quals to apply, if any */
} RangeTblEntry;
/*