7f623e
Author: Filip Januš <fjanus@redhat.com>
7f623e
Backport from release: 10.21/12.11/13.7
7f623e
Upstream commit: https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=a117cebd638dd02e5c2e791c25e43745f233111b
7f623e
postgresql-9.2 doesn't support amcheck and brin
7f623e
BZ: https://bugzilla.redhat.com/show_bug.cgi?id=2081126
7f623e
diff -ur -x '*.so' -x '*.o' -x 'cscope.*' -x '*.out' -x '*.sql' postgresql-9.2.24/src/backend/catalog/index.c postgresql-9.2.24_patched/src/backend/catalog/index.c
7f623e
--- postgresql-9.2.24/src/backend/catalog/index.c	2017-11-06 23:17:39.000000000 +0100
7f623e
+++ postgresql-9.2.24_patched/src/backend/catalog/index.c	2022-06-09 15:40:32.000000000 +0200
7f623e
@@ -2684,7 +2684,16 @@
7f623e
7f623e
 	/* Open and lock the parent heap relation */
7f623e
 	heapRelation = heap_open(heapId, ShareUpdateExclusiveLock);
7f623e
-	/* And the target index relation */
7f623e
+	/*
7f623e
+	* Switch to the table owner's userid, so that any index functions are run
7f623e
+	* as that user.  Also lock down security-restricted operations and
7f623e
+	* arrange to make GUC variable changes local to this command.
7f623e
+	*/
7f623e
+	GetUserIdAndSecContext(&save_userid, &save_sec_context);
7f623e
+	SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
7f623e
+                           save_sec_context | SECURITY_RESTRICTED_OPERATION);
7f623e
+	save_nestlevel = NewGUCNestLevel();
7f623e
+
7f623e
 	indexRelation = index_open(indexId, RowExclusiveLock);
7f623e
7f623e
 	/*
7f623e
@@ -2698,16 +2707,6 @@
7f623e
 	indexInfo->ii_Concurrent = true;
7f623e
7f623e
 	/*
7f623e
-	 * Switch to the table owner's userid, so that any index functions are run
7f623e
-	 * as that user.  Also lock down security-restricted operations and
7f623e
-	 * arrange to make GUC variable changes local to this command.
7f623e
-	 */
7f623e
-	GetUserIdAndSecContext(&save_userid, &save_sec_context);
7f623e
-	SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
7f623e
-						   save_sec_context | SECURITY_RESTRICTED_OPERATION);
7f623e
-	save_nestlevel = NewGUCNestLevel();
7f623e
-
7f623e
-	/*
7f623e
 	 * Scan the index and gather up all the TIDs into a tuplesort object.
7f623e
 	 */
7f623e
 	ivinfo.index = indexRelation;
7f623e
@@ -3112,6 +3111,9 @@
7f623e
 	Oid			heapId;
7f623e
 	IndexInfo  *indexInfo;
7f623e
 	volatile bool skipped_constraint = false;
7f623e
+	Oid         save_userid;
7f623e
+	int         save_sec_context;
7f623e
+	int         save_nestlevel;
7f623e
7f623e
 	/*
7f623e
 	 * Open and lock the parent heap relation.  ShareLock is sufficient since
7f623e
@@ -3121,6 +3123,16 @@
7f623e
 	heapRelation = heap_open(heapId, ShareLock);
7f623e
7f623e
 	/*
7f623e
+	 * Switch to the table owner's userid, so that any index functions are run
7f623e
+	 * as that user.  Also lock down security-restricted operations and
7f623e
+	 * arrange to make GUC variable changes local to this command.
7f623e
+	 */
7f623e
+	GetUserIdAndSecContext(&save_userid, &save_sec_context);
7f623e
+	SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
7f623e
+                           save_sec_context | SECURITY_RESTRICTED_OPERATION);
7f623e
+	save_nestlevel = NewGUCNestLevel();
7f623e
+
7f623e
+	/*
7f623e
 	 * Open the target index relation and get an exclusive lock on it, to
7f623e
 	 * ensure that no one else is touching this particular index.
7f623e
 	 */
7f623e
@@ -3260,6 +3272,12 @@
7f623e
 		heap_close(pg_index, RowExclusiveLock);
7f623e
 	}
7f623e
7f623e
+	/* Roll back any GUC changes executed by index functions */
7f623e
+	AtEOXact_GUC(false, save_nestlevel);
7f623e
+
7f623e
+	/* Restore userid and security context */
7f623e
+	SetUserIdAndSecContext(save_userid, save_sec_context);
7f623e
+
7f623e
 	/* Close rels, but keep locks */
7f623e
 	index_close(iRel, NoLock);
7f623e
 	heap_close(heapRelation, NoLock);
7f623e
diff -ur -x '*.so' -x '*.o' -x 'cscope.*' -x '*.out' -x '*.sql' postgresql-9.2.24/src/backend/commands/cluster.c postgresql-9.2.24_patched/src/backend/commands/cluster.c
7f623e
--- postgresql-9.2.24/src/backend/commands/cluster.c	2017-11-06 23:17:39.000000000 +0100
7f623e
+++ postgresql-9.2.24_patched/src/backend/commands/cluster.c	2022-06-09 15:41:12.000000000 +0200
7f623e
@@ -258,7 +258,9 @@
7f623e
 			int freeze_min_age, int freeze_table_age)
7f623e
 {
7f623e
 	Relation	OldHeap;
7f623e
-
7f623e
+	Oid		save_userid;
7f623e
+	int		save_sec_context;
7f623e
+	int		save_nestlevel;
7f623e
 	/* Check for user-requested abort. */
7f623e
 	CHECK_FOR_INTERRUPTS();
7f623e
7f623e
@@ -275,6 +277,16 @@
7f623e
 		return;
7f623e
7f623e
 	/*
7f623e
+	 * Switch to the table owner's userid, so that any index functions are run
7f623e
+	 * as that user.  Also lock down security-restricted operations and
7f623e
+	 * arrange to make GUC variable changes local to this command.
7f623e
+	 */
7f623e
+	GetUserIdAndSecContext(&save_userid, &save_sec_context);
7f623e
+	SetUserIdAndSecContext(OldHeap->rd_rel->relowner,
7f623e
+                           save_sec_context | SECURITY_RESTRICTED_OPERATION);
7f623e
+	save_nestlevel = NewGUCNestLevel();
7f623e
+
7f623e
+	/*
7f623e
 	 * Since we may open a new transaction for each relation, we have to check
7f623e
 	 * that the relation still is what we think it is.
7f623e
 	 *
7f623e
@@ -288,10 +300,10 @@
7f623e
 		Form_pg_index indexForm;
7f623e
7f623e
 		/* Check that the user still owns the relation */
7f623e
-		if (!pg_class_ownercheck(tableOid, GetUserId()))
7f623e
+		if (!pg_class_ownercheck(tableOid, save_userid))
7f623e
 		{
7f623e
 			relation_close(OldHeap, AccessExclusiveLock);
7f623e
-			return;
7f623e
+			goto out;
7f623e
 		}
7f623e
7f623e
 		/*
7f623e
@@ -305,7 +317,7 @@
7f623e
 		if (RELATION_IS_OTHER_TEMP(OldHeap))
7f623e
 		{
7f623e
 			relation_close(OldHeap, AccessExclusiveLock);
7f623e
-			return;
7f623e
+			goto out;
7f623e
 		}
7f623e
7f623e
 		if (OidIsValid(indexOid))
7f623e
@@ -316,7 +328,7 @@
7f623e
 			if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(indexOid)))
7f623e
 			{
7f623e
 				relation_close(OldHeap, AccessExclusiveLock);
7f623e
-				return;
7f623e
+				goto out;
7f623e
 			}
7f623e
7f623e
 			/*
7f623e
@@ -326,14 +338,14 @@
7f623e
 			if (!HeapTupleIsValid(tuple))		/* probably can't happen */
7f623e
 			{
7f623e
 				relation_close(OldHeap, AccessExclusiveLock);
7f623e
-				return;
7f623e
+				goto out;
7f623e
 			}
7f623e
 			indexForm = (Form_pg_index) GETSTRUCT(tuple);
7f623e
 			if (!indexForm->indisclustered)
7f623e
 			{
7f623e
 				ReleaseSysCache(tuple);
7f623e
 				relation_close(OldHeap, AccessExclusiveLock);
7f623e
-				return;
7f623e
+				goto out;
7f623e
 			}
7f623e
 			ReleaseSysCache(tuple);
7f623e
 		}
7f623e
@@ -389,6 +401,13 @@
7f623e
 					 verbose);
7f623e
7f623e
 	/* NB: rebuild_relation does heap_close() on OldHeap */
7f623e
+
7f623e
+out:
7f623e
+	/* Roll back any GUC changes executed by index functions */
7f623e
+	AtEOXact_GUC(false, save_nestlevel);
7f623e
+
7f623e
+	/* Restore userid and security context */
7f623e
+	SetUserIdAndSecContext(save_userid, save_sec_context);
7f623e
 }
7f623e
7f623e
 /*
7f623e
diff -ur -x '*.so' -x '*.o' -x 'cscope.*' -x '*.out' -x '*.sql' postgresql-9.2.24/src/backend/commands/indexcmds.c postgresql-9.2.24_patched/src/backend/commands/indexcmds.c
7f623e
--- postgresql-9.2.24/src/backend/commands/indexcmds.c	2017-11-06 23:17:39.000000000 +0100
7f623e
+++ postgresql-9.2.24_patched/src/backend/commands/indexcmds.c	2022-06-08 12:32:22.000000000 +0200
7f623e
@@ -329,6 +329,11 @@
7f623e
 	LOCKMODE	lockmode;
7f623e
 	Snapshot	snapshot;
7f623e
 	int			i;
7f623e
+	Oid		root_save_userid;
7f623e
+	int		root_save_sec_context;
7f623e
+	int		root_save_nestlevel;
7f623e
+
7f623e
+	root_save_nestlevel = NewGUCNestLevel();
7f623e
7f623e
 	/*
7f623e
 	 * count attributes in index
7f623e
@@ -358,6 +363,15 @@
7f623e
 	lockmode = stmt->concurrent ? ShareUpdateExclusiveLock : ShareLock;
7f623e
 	rel = heap_open(relationId, lockmode);
7f623e
7f623e
+	/*
7f623e
+	 * Switch to the table owner's userid, so that any index functions are run
7f623e
+	 * as that user.  Also lock down security-restricted operations.  We
7f623e
+	 * already arranged to make GUC variable changes local to this command.
7f623e
+	 */
7f623e
+	GetUserIdAndSecContext(&root_save_userid, &root_save_sec_context);
7f623e
+	SetUserIdAndSecContext(rel->rd_rel->relowner,
7f623e
+                           root_save_sec_context | SECURITY_RESTRICTED_OPERATION);
7f623e
+
7f623e
 	relationId = RelationGetRelid(rel);
7f623e
 	namespaceId = RelationGetNamespace(rel);
7f623e
7f623e
@@ -400,7 +414,7 @@
7f623e
 	{
7f623e
 		AclResult	aclresult;
7f623e
7f623e
-		aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
7f623e
+		aclresult = pg_namespace_aclcheck(namespaceId, root_save_userid,
7f623e
 										  ACL_CREATE);
7f623e
 		if (aclresult != ACLCHECK_OK)
7f623e
 			aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
7f623e
@@ -427,7 +441,7 @@
7f623e
 	{
7f623e
 		AclResult	aclresult;
7f623e
7f623e
-		aclresult = pg_tablespace_aclcheck(tablespaceId, GetUserId(),
7f623e
+		aclresult = pg_tablespace_aclcheck(tablespaceId, root_save_userid,
7f623e
 										   ACL_CREATE);
7f623e
 		if (aclresult != ACLCHECK_OK)
7f623e
 			aclcheck_error(aclresult, ACL_KIND_TABLESPACE,
7f623e
@@ -610,11 +624,40 @@
7f623e
 					 skip_build || stmt->concurrent,
7f623e
 					 stmt->concurrent);
7f623e
7f623e
+    if (!OidIsValid(indexRelationId))
7f623e
+    {
7f623e
+        /*
7f623e
+         * Roll back any GUC changes executed by index functions.  Also revert
7f623e
+         * to original default_tablespace if we changed it above.
7f623e
+         */
7f623e
+        AtEOXact_GUC(false, root_save_nestlevel);
7f623e
+
7f623e
+        /* Restore userid and security context */
7f623e
+        SetUserIdAndSecContext(root_save_userid, root_save_sec_context);
7f623e
+
7f623e
+        heap_close(rel, NoLock);
7f623e
+        return indexRelationId;
7f623e
+    }
7f623e
+
7f623e
+     /*
7f623e
+     * Roll back any GUC changes executed by index functions, and keep
7f623e
+     * subsequent changes local to this command.  It's barely possible that
7f623e
+     * some index function changed a behavior-affecting GUC, e.g. xmloption,
7f623e
+     * that affects subsequent steps.  This improves bug-compatibility with
7f623e
+     * older PostgreSQL versions.  They did the AtEOXact_GUC() here for the
7f623e
+     * purpose of clearing the above default_tablespace change.
7f623e
+     */
7f623e
+    AtEOXact_GUC(false, root_save_nestlevel);
7f623e
+    root_save_nestlevel = NewGUCNestLevel();
7f623e
+
7f623e
 	/* Add any requested comment */
7f623e
 	if (stmt->idxcomment != NULL)
7f623e
 		CreateComments(indexRelationId, RelationRelationId, 0,
7f623e
 					   stmt->idxcomment);
7f623e
7f623e
+    AtEOXact_GUC(false, root_save_nestlevel);
7f623e
+    SetUserIdAndSecContext(root_save_userid, root_save_sec_context);
7f623e
+
7f623e
 	if (!stmt->concurrent)
7f623e
 	{
7f623e
 		/* Close the heap and we're done, in the non-concurrent case */
7f623e
@@ -705,6 +748,16 @@
7f623e
 	/* Open and lock the parent heap relation */
7f623e
 	rel = heap_openrv(stmt->relation, ShareUpdateExclusiveLock);
7f623e
7f623e
+	/*
7f623e
+         * Switch to the table owner's userid, so that any index functions are run
7f623e
+         * as that user.  Also lock down security-restricted operations and
7f623e
+         * arrange to make GUC variable changes local to this command.
7f623e
+         */
7f623e
+        GetUserIdAndSecContext(&root_save_userid, &root_save_sec_context);
7f623e
+        SetUserIdAndSecContext(rel->rd_rel->relowner,
7f623e
+                                                   root_save_sec_context | SECURITY_RESTRICTED_OPERATION);
7f623e
+        root_save_nestlevel = NewGUCNestLevel();
7f623e
+
7f623e
 	/* And the target index relation */
7f623e
 	indexRelation = index_open(indexRelationId, RowExclusiveLock);
7f623e
7f623e
@@ -720,6 +773,12 @@
7f623e
 	/* Now build the index */
7f623e
 	index_build(rel, indexRelation, indexInfo, stmt->primary, false);
7f623e
7f623e
+	/* Roll back any GUC changes executed by index functions */
7f623e
+        AtEOXact_GUC(false, root_save_nestlevel);
7f623e
+
7f623e
+        /* Restore userid and security context */
7f623e
+        SetUserIdAndSecContext(root_save_userid, root_save_sec_context);
7f623e
+
7f623e
 	/* Close both the relations, but keep the locks */
7f623e
 	heap_close(rel, NoLock);
7f623e
 	index_close(indexRelation, NoLock);
7f623e
7f623e
--- postgresql-9.2.24/src/test/regress/expected/privileges.out	2017-11-06 23:17:39.000000000 +0100
7f623e
+++ privileges.out	2022-06-10 10:05:51.000000000 +0200
7f623e
@@ -1544,9 +1544,27 @@
7f623e
 
7f623e
 set session role regressuser1;
7f623e
 drop table dep_priv_test;
7f623e
+\c -
7f623e
+CREATE ROLE regress_sro_user;
7f623e
+CREATE FUNCTION sro_ifun(int) RETURNS int AS $$
7f623e
+BEGIN
7f623e
+        RETURN(SELECT current_user);
7f623e
+
7f623e
+END;
7f623e
+$$ LANGUAGE plpgsql IMMUTABLE;
7f623e
+CREATE TABLE sro_tab (a int);
7f623e
+ALTER TABLE sro_tab OWNER TO regress_sro_user;
7f623e
+INSERT INTO sro_tab VALUES (1), (2), (3);
7f623e
+CREATE INDEX sro_idx ON sro_tab ((sro_ifun(a) + sro_ifun(0)))
7f623e
+        WHERE sro_ifun(a + 10) > sro_ifun(10);
7f623e
+ERROR:  invalid input syntax for integer: "regress_sro_user"
7f623e
+CONTEXT:  PL/pgSQL function sro_ifun(integer) while casting return value to function's return type
7f623e
 -- clean up
7f623e
 \c
7f623e
 drop sequence x_seq;
7f623e
+DROP TABLE sro_tab;
7f623e
+DROP ROLE regress_sro_user;
7f623e
+DROP FUNCTION sro_ifun(int);
7f623e
 DROP FUNCTION testfunc2(int);
7f623e
 DROP FUNCTION testfunc4(boolean);
7f623e
 DROP VIEW atestv1;
7f623e
7f623e
diff -ur postgresql-9.2.24/src/test/regress/sql/privileges.sql postgresql-9.2.24_patch/src/test/regress/sql/privileges.sql
7f623e
--- postgresql-9.2.24/src/test/regress/sql/privileges.sql       2017-11-06 23:17:39.000000000 +0100
7f623e
+++ postgresql-9.2.24_patch/src/test/regress/sql/privileges.sql 2022-06-08 10:01:35.000000000 +0200
7f623e
@@ -931,6 +931,19 @@
7f623e
 set session role regressuser1;
7f623e
 drop table dep_priv_test;
7f623e
7f623e
+\c -
7f623e
+CREATE ROLE regress_sro_user;
7f623e
+CREATE FUNCTION sro_ifun(int) RETURNS int AS $$
7f623e
+BEGIN
7f623e
+        RETURN(SELECT current_user);
7f623e
+
7f623e
+END;
7f623e
+$$ LANGUAGE plpgsql IMMUTABLE;
7f623e
+CREATE TABLE sro_tab (a int);
7f623e
+ALTER TABLE sro_tab OWNER TO regress_sro_user;
7f623e
+INSERT INTO sro_tab VALUES (1), (2), (3);
7f623e
+CREATE INDEX sro_idx ON sro_tab ((sro_ifun(a) + sro_ifun(0)))
7f623e
+        WHERE sro_ifun(a + 10) > sro_ifun(10);
7f623e
7f623e
 -- clean up
7f623e
7f623e
@@ -938,6 +951,10 @@
7f623e
7f623e
 drop sequence x_seq;
7f623e
7f623e
+DROP TABLE sro_tab;
7f623e
+DROP ROLE regress_sro_user;
7f623e
+
7f623e
+DROP FUNCTION sro_ifun(int);
7f623e
 DROP FUNCTION testfunc2(int);
7f623e
 DROP FUNCTION testfunc4(boolean);