diff options
-rw-r--r-- | src/backend/rewrite/rowsecurity.c | 47 | ||||
-rw-r--r-- | src/test/regress/expected/rowsecurity.out | 3 |
2 files changed, 47 insertions, 3 deletions
diff --git a/src/backend/rewrite/rowsecurity.c b/src/backend/rewrite/rowsecurity.c index 69eb9bdb2a..c3d4b7ec14 100644 --- a/src/backend/rewrite/rowsecurity.c +++ b/src/backend/rewrite/rowsecurity.c @@ -189,6 +189,33 @@ get_row_security_policies(Query *root, RangeTblEntry *rte, int rt_index, hasSubLinks); /* + * For the target relation, when there is a returning list, we need to + * collect up CMD_SELECT policies and add them via add_security_quals. + * This is because, for the RETURNING case, we have to filter any records + * which are not visible through an ALL or SELECT USING policy. + * + * We don't need to worry about the non-target relation case because we are + * checking the ALL and SELECT policies for those relations anyway (see + * above). + */ + if (root->returningList != NIL && + (commandType == CMD_UPDATE || commandType == CMD_DELETE)) + { + List *returning_permissive_policies; + List *returning_restrictive_policies; + + get_policies_for_relation(rel, CMD_SELECT, user_id, + &returning_permissive_policies, + &returning_restrictive_policies); + + add_security_quals(rt_index, + returning_permissive_policies, + returning_restrictive_policies, + securityQuals, + hasSubLinks); + } + + /* * For INSERT and UPDATE, add withCheckOptions to verify that any new * records added are consistent with the security policies. This will use * each policy's WITH CHECK clause, or its USING clause if no explicit @@ -235,6 +262,26 @@ get_row_security_policies(Query *root, RangeTblEntry *rte, int rt_index, withCheckOptions, hasSubLinks); + /* + * Get and add ALL/SELECT policies, if there is a RETURNING clause, + * also as WCO policies, again, to avoid silently dropping data. + */ + if (root->returningList != NIL) + { + List *conflict_returning_permissive_policies = NIL; + List *conflict_returning_restrictive_policies = NIL; + + get_policies_for_relation(rel, CMD_SELECT, user_id, + &conflict_returning_permissive_policies, + &conflict_returning_restrictive_policies); + add_with_check_options(rel, rt_index, + WCO_RLS_CONFLICT_CHECK, + conflict_returning_permissive_policies, + conflict_returning_restrictive_policies, + withCheckOptions, + hasSubLinks); + } + /* Enforce the WITH CHECK clauses of the UPDATE policies */ add_with_check_options(rel, rt_index, WCO_RLS_UPDATE_CHECK, diff --git a/src/test/regress/expected/rowsecurity.out b/src/test/regress/expected/rowsecurity.out index 576bcafa49..de6b618789 100644 --- a/src/test/regress/expected/rowsecurity.out +++ b/src/test/regress/expected/rowsecurity.out @@ -1954,9 +1954,6 @@ DELETE FROM x1 WHERE f_leak(b) RETURNING *; 2 | bcd_updt_updt | rls_regress_user1 6 | fgh_updt_updt | rls_regress_user1 8 | fgh_updt_updt | rls_regress_user2 - 3 | cde_updt | rls_regress_user2 - 7 | fgh_updt | rls_regress_user2 - 4 | def_updt_updt | rls_regress_user2 (6 rows) -- |