Re: Fix RLS checks for UPDATE/DELETE FOR PORTION OF leftover rows - Mailing list pgsql-hackers

From Dean Rasheed
Subject Re: Fix RLS checks for UPDATE/DELETE FOR PORTION OF leftover rows
Date
Msg-id CAEZATCXW3O9_cniVFtw76zFO5p9D06P1bwMvG8RU4_YFkm0iwA@mail.gmail.com
Whole thread
In response to Re: Fix RLS checks for UPDATE/DELETE FOR PORTION OF leftover rows  (Paul A Jungwirth <pj@illuminatedcomputing.com>)
Responses Re: Fix RLS checks for UPDATE/DELETE FOR PORTION OF leftover rows
List pgsql-hackers
On Wed, 15 Jul 2026 at 22:02, Paul A Jungwirth
<pj@illuminatedcomputing.com> wrote:
>
> Thanks for taking a look! Here is a v4 with those additions.
>

+       <entry><command>UPDATE ... FOR PORTION OF</command></entry>
+       <entry>
+        Filter existing row <footnoteref linkend="rls-select-priv"/> &
+        check new row <footnoteref linkend="rls-select-priv"/>
+       </entry>
+       <entry>

The footnote "rls-select-priv" reads "If read access is required to
either the existing or new row (for example, a WHERE or RETURNING
clause that refers to columns from the relation)." However, FOR
PORTION OF is guaranteed to require read access to the table, so as
with a few other entries in that column, the link to this footnote is
not needed -- it will unconditionally apply the SELECT policy to the
existing and new rows. Similarly for DELETE ... FOR PORTION OF.


+        /*
+         * As with regular INSERT/UPDATE above, if SELECT rights are needed
+         * for the statement, ensure the leftover row remains visible.
+         */
+        if (perminfo->requiredPerms & ACL_SELECT)
+        {
+            List       *select_permissive_policies;
+            List       *select_restrictive_policies;
+
+            get_policies_for_relation(rel, CMD_SELECT, user_id,
+                                      &select_permissive_policies,
+                                      &select_restrictive_policies);
+            add_with_check_options(rel, rt_index,
+                                   WCO_RLS_INSERT_CHECK,
+                                   select_permissive_policies,
+                                   select_restrictive_policies,
+                                   withCheckOptions,
+                                   hasSubLinks,
+                                   true);
+        }

Thinking some more about this, I'm not so sure it's right. For a plain
INSERT, we apply SELECT policies if SELECT permissions are required,
which only happens if there is a RETURNING clause. The reason is to
ensure the user has rights to see the row returned by the RETURNING
clause. However, for the auxiliary INSERTS for leftover portions in
UPDATE/DELETE ... FOR PORTION OF, even if there is a RETURNING clause,
it will only return the updated/deleted row, not the leftover rows.
The command never reads the leftover rows, so why do we need the
leftover rows to satisfy the SELECT policies?

Regards,
Dean



pgsql-hackers by date:

Previous
From: Zsolt Parragi
Date:
Subject: Re: [DESIGN] Soft DROP TABLE, recoverable drops for PostgreSQL
Next
From: Masahiko Sawada
Date:
Subject: Follow-up fixes for online wal_level change