mirror of
https://github.com/postgres/postgres.git
synced 2025-07-14 08:21:07 +03:00
Make security barrier views automatically updatable
Views which are marked as security_barrier must have their quals applied before any user-defined quals are called, to prevent user-defined functions from being able to see rows which the security barrier view is intended to prevent them from seeing. Remove the restriction on security barrier views being automatically updatable by adding a new securityQuals list to the RTE structure which keeps track of the quals from security barrier views at each level, independently of the user-supplied quals. When RTEs are later discovered which have securityQuals populated, they are turned into subquery RTEs which are marked as security_barrier to prevent any user-supplied quals being pushed down (modulo LEAKPROOF quals). Dean Rasheed, reviewed by Craig Ringer, Simon Riggs, KaiGai Kohei
This commit is contained in:
@ -915,6 +915,12 @@ inheritance_planner(PlannerInfo *root)
|
||||
/* Generate plan */
|
||||
subplan = grouping_planner(&subroot, 0.0 /* retrieve all tuples */ );
|
||||
|
||||
/*
|
||||
* Planning may have modified the query result relation (if there
|
||||
* were security barrier quals on the result RTE).
|
||||
*/
|
||||
appinfo->child_relid = subroot.parse->resultRelation;
|
||||
|
||||
/*
|
||||
* If this child rel was excluded by constraint exclusion, exclude it
|
||||
* from the result plan.
|
||||
@ -932,9 +938,40 @@ inheritance_planner(PlannerInfo *root)
|
||||
if (final_rtable == NIL)
|
||||
final_rtable = subroot.parse->rtable;
|
||||
else
|
||||
final_rtable = list_concat(final_rtable,
|
||||
{
|
||||
List *tmp_rtable = NIL;
|
||||
ListCell *cell1, *cell2;
|
||||
|
||||
/*
|
||||
* Check to see if any of the original RTEs were turned into
|
||||
* subqueries during planning. Currently, this should only ever
|
||||
* happen due to securityQuals being involved which push a
|
||||
* relation down under a subquery, to ensure that the security
|
||||
* barrier quals are evaluated first.
|
||||
*
|
||||
* When this happens, we want to use the new subqueries in the
|
||||
* final rtable.
|
||||
*/
|
||||
forboth(cell1, final_rtable, cell2, subroot.parse->rtable)
|
||||
{
|
||||
RangeTblEntry *rte1 = (RangeTblEntry *) lfirst(cell1);
|
||||
RangeTblEntry *rte2 = (RangeTblEntry *) lfirst(cell2);
|
||||
|
||||
if (rte1->rtekind == RTE_RELATION &&
|
||||
rte2->rtekind == RTE_SUBQUERY)
|
||||
{
|
||||
/* Should only be when there are securityQuals today */
|
||||
Assert(rte1->securityQuals != NIL);
|
||||
tmp_rtable = lappend(tmp_rtable, rte2);
|
||||
}
|
||||
else
|
||||
tmp_rtable = lappend(tmp_rtable, rte1);
|
||||
}
|
||||
|
||||
final_rtable = list_concat(tmp_rtable,
|
||||
list_copy_tail(subroot.parse->rtable,
|
||||
list_length(final_rtable)));
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to collect all the RelOptInfos from all child plans into
|
||||
@ -1162,6 +1199,12 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
|
||||
/* Preprocess targetlist */
|
||||
tlist = preprocess_targetlist(root, tlist);
|
||||
|
||||
/*
|
||||
* Expand any rangetable entries that have security barrier quals.
|
||||
* This may add new security barrier subquery RTEs to the rangetable.
|
||||
*/
|
||||
expand_security_quals(root, tlist);
|
||||
|
||||
/*
|
||||
* Locate any window functions in the tlist. (We don't need to look
|
||||
* anywhere else, since expressions used in ORDER BY will be in there
|
||||
|
Reference in New Issue
Block a user