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