postgres.git / summary / log / commit / refs
commit f68f47fe7d66a475d934823624013bcb7fae6f01
Author: Amit Langote <amitlan@postgresql.org>
Date: Fri Aug 07 07:34:00 2026 +0000
Begin RI fast-path index scan under the switched user id
ri_FastPathCheck() called index_beginscan() before switching to the
referenced relation's owner for the permission check and probe. For
btree this has no consequence, but starting the scan before the user id
switch sets a poor example for code dealing with out-of-tree access
methods, whose beginscan could observe the wrong user id. Move
index_beginscan() after the SetUserIdAndSecContext() call.
Reported-by: Noah Misch <noah@leadboat.com>
Reviewed-by: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Discussion: https://postgr.es/m/20260705210533.ee.noahmisch@microsoft.com
Backpatch-through: 19
src/backend/utils/adt/ri_triggers.c | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index 74774f6b2bd..19af06ee794 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -2828,10 +2828,6 @@ ri_FastPathCheck(RI_ConstraintInfo *riinfo,
idx_rel = index_open(riinfo->conindid, AccessShareLock);
slot = table_slot_create(pk_rel, NULL);
- scandesc = index_beginscan(pk_rel, idx_rel,
- snapshot, NULL,
- riinfo->nkeys, 0,
- SO_NONE);
GetUserIdAndSecContext(&saved_userid, &saved_sec_context);
SetUserIdAndSecContext(RelationGetForm(pk_rel)->relowner,
@@ -2840,6 +2836,17 @@ ri_FastPathCheck(RI_ConstraintInfo *riinfo,
SECURITY_NOFORCE_RLS);
ri_CheckPermissions(pk_rel);
+ /*
+ * Begin the scan under the switched user id, so that any access method
+ * code invoked by index_beginscan() runs as the PK relation's owner. For
+ * btree this has no functional consequence, but it keeps the ordering
+ * correct for out-of-tree access methods.
+ */
+ scandesc = index_beginscan(pk_rel, idx_rel,
+ snapshot, NULL,
+ riinfo->nkeys, 0,
+ SO_NONE);
+
if (riinfo->fpmeta == NULL)
{
/* Reload to ensure it's valid. */
@@ -2965,9 +2972,6 @@ ri_FastPathBatchFlush(RI_FastPathEntry *fpentry, Relation fk_rel,
*/
oldcxt = MemoryContextSwitchTo(fpentry->flush_cxt);
- scandesc = index_beginscan(pk_rel, idx_rel, snapshot, NULL,
- riinfo->nkeys, 0, SO_NONE);
-
GetUserIdAndSecContext(&saved_userid, &saved_sec_context);
SetUserIdAndSecContext(RelationGetForm(pk_rel)->relowner,
saved_sec_context |
@@ -2983,6 +2987,15 @@ ri_FastPathBatchFlush(RI_FastPathEntry *fpentry, Relation fk_rel,
*/
ri_CheckPermissions(pk_rel);
+ /*
+ * Begin the scan under the switched user id, so that any access method
+ * code invoked by index_beginscan() runs as the PK relation's owner. For
+ * btree this has no functional consequence, but it keeps the ordering
+ * correct for out-of-tree access methods.
+ */
+ scandesc = index_beginscan(pk_rel, idx_rel, snapshot, NULL,
+ riinfo->nkeys, 0, SO_NONE);
+
if (riinfo->fpmeta == NULL)
{
/* Reload to ensure it's valid. */
[parent: 8c0aa08c1594]