aboutsummaryrefslogtreecommitdiff
path: root/src/backend/rewrite/rowsecurity.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/rewrite/rowsecurity.c')
-rw-r--r--src/backend/rewrite/rowsecurity.c85
1 files changed, 60 insertions, 25 deletions
diff --git a/src/backend/rewrite/rowsecurity.c b/src/backend/rewrite/rowsecurity.c
index 5c3fe4eda28..b1620e4625d 100644
--- a/src/backend/rewrite/rowsecurity.c
+++ b/src/backend/rewrite/rowsecurity.c
@@ -394,7 +394,11 @@ get_row_security_policies(Query *root, RangeTblEntry *rte, int rt_index,
* and set them up so that we can enforce the appropriate policy depending
* on the final action we take.
*
- * We already fetched the SELECT policies above.
+ * We already fetched the SELECT policies above, to check existing rows,
+ * but we must also check that new rows created by UPDATE actions are
+ * visible, if SELECT rights are required for this relation. We don't do
+ * this for INSERT actions, since an INSERT command would only do this
+ * check if it had a RETURNING list, and MERGE does not support RETURNING.
*
* We don't push the UPDATE/DELETE USING quals to the RTE because we don't
* really want to apply them while scanning the relation since we don't
@@ -410,16 +414,20 @@ get_row_security_policies(Query *root, RangeTblEntry *rte, int rt_index,
*/
if (commandType == CMD_MERGE)
{
- List *merge_permissive_policies;
- List *merge_restrictive_policies;
+ List *merge_update_permissive_policies;
+ List *merge_update_restrictive_policies;
+ List *merge_delete_permissive_policies;
+ List *merge_delete_restrictive_policies;
+ List *merge_insert_permissive_policies;
+ List *merge_insert_restrictive_policies;
/*
* Fetch the UPDATE policies and set them up to execute on the
* existing target row before doing UPDATE.
*/
get_policies_for_relation(rel, CMD_UPDATE, user_id,
- &merge_permissive_policies,
- &merge_restrictive_policies);
+ &merge_update_permissive_policies,
+ &merge_update_restrictive_policies);
/*
* WCO_RLS_MERGE_UPDATE_CHECK is used to check UPDATE USING quals on
@@ -427,23 +435,59 @@ get_row_security_policies(Query *root, RangeTblEntry *rte, int rt_index,
*/
add_with_check_options(rel, rt_index,
WCO_RLS_MERGE_UPDATE_CHECK,
- merge_permissive_policies,
- merge_restrictive_policies,
+ merge_update_permissive_policies,
+ merge_update_restrictive_policies,
withCheckOptions,
hasSubLinks,
true);
+ /* Enforce the WITH CHECK clauses of the UPDATE policies */
+ add_with_check_options(rel, rt_index,
+ WCO_RLS_UPDATE_CHECK,
+ merge_update_permissive_policies,
+ merge_update_restrictive_policies,
+ withCheckOptions,
+ hasSubLinks,
+ false);
+
+ /*
+ * Add ALL/SELECT policies as WCO_RLS_UPDATE_CHECK WCOs, to ensure
+ * that the updated row is visible when executing an UPDATE action, if
+ * SELECT rights are required for this relation.
+ */
+ if (perminfo->requiredPerms & ACL_SELECT)
+ {
+ List *merge_select_permissive_policies;
+ List *merge_select_restrictive_policies;
+
+ get_policies_for_relation(rel, CMD_SELECT, user_id,
+ &merge_select_permissive_policies,
+ &merge_select_restrictive_policies);
+ add_with_check_options(rel, rt_index,
+ WCO_RLS_UPDATE_CHECK,
+ merge_select_permissive_policies,
+ merge_select_restrictive_policies,
+ withCheckOptions,
+ hasSubLinks,
+ true);
+ }
+
/*
- * Same with DELETE policies.
+ * Fetch the DELETE policies and set them up to execute on the
+ * existing target row before doing DELETE.
*/
get_policies_for_relation(rel, CMD_DELETE, user_id,
- &merge_permissive_policies,
- &merge_restrictive_policies);
+ &merge_delete_permissive_policies,
+ &merge_delete_restrictive_policies);
+ /*
+ * WCO_RLS_MERGE_DELETE_CHECK is used to check DELETE USING quals on
+ * the existing target row.
+ */
add_with_check_options(rel, rt_index,
WCO_RLS_MERGE_DELETE_CHECK,
- merge_permissive_policies,
- merge_restrictive_policies,
+ merge_delete_permissive_policies,
+ merge_delete_restrictive_policies,
withCheckOptions,
hasSubLinks,
true);
@@ -454,22 +498,13 @@ get_row_security_policies(Query *root, RangeTblEntry *rte, int rt_index,
* withCheckOptions.
*/
get_policies_for_relation(rel, CMD_INSERT, user_id,
- &merge_permissive_policies,
- &merge_restrictive_policies);
+ &merge_insert_permissive_policies,
+ &merge_insert_restrictive_policies);
add_with_check_options(rel, rt_index,
WCO_RLS_INSERT_CHECK,
- merge_permissive_policies,
- merge_restrictive_policies,
- withCheckOptions,
- hasSubLinks,
- false);
-
- /* Enforce the WITH CHECK clauses of the UPDATE policies */
- add_with_check_options(rel, rt_index,
- WCO_RLS_UPDATE_CHECK,
- merge_permissive_policies,
- merge_restrictive_policies,
+ merge_insert_permissive_policies,
+ merge_insert_restrictive_policies,
withCheckOptions,
hasSubLinks,
false);