mirror of
https://github.com/postgres/postgres.git
synced 2025-11-22 12:22:45 +03:00
Make relation-enumerating operations be security-restricted operations.
When a feature enumerates relations and runs functions associated with all found relations, the feature's user shall not need to trust every user having permission to create objects. BRIN-specific functionality in autovacuum neglected to account for this, as did pg_amcheck and CLUSTER. An attacker having permission to create non-temp objects in at least one schema could execute arbitrary SQL functions under the identity of the bootstrap superuser. CREATE INDEX (not a relation-enumerating operation) and REINDEX protected themselves too late. This change extends to the non-enumerating amcheck interface. Back-patch to v10 (all supported versions). Sergey Shinderuk, reviewed (in earlier versions) by Alexander Lakhin. Reported by Alexander Lakhin. Security: CVE-2022-1552
This commit is contained in:
@@ -1445,6 +1445,9 @@ index_concurrently_build(Oid heapRelationId,
|
||||
Oid indexRelationId)
|
||||
{
|
||||
Relation heapRel;
|
||||
Oid save_userid;
|
||||
int save_sec_context;
|
||||
int save_nestlevel;
|
||||
Relation indexRelation;
|
||||
IndexInfo *indexInfo;
|
||||
|
||||
@@ -1454,7 +1457,16 @@ index_concurrently_build(Oid heapRelationId,
|
||||
/* Open and lock the parent heap relation */
|
||||
heapRel = table_open(heapRelationId, 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(heapRel->rd_rel->relowner,
|
||||
save_sec_context | SECURITY_RESTRICTED_OPERATION);
|
||||
save_nestlevel = NewGUCNestLevel();
|
||||
|
||||
indexRelation = index_open(indexRelationId, RowExclusiveLock);
|
||||
|
||||
/*
|
||||
@@ -1470,6 +1482,12 @@ index_concurrently_build(Oid heapRelationId,
|
||||
/* Now build the index */
|
||||
index_build(heapRel, indexRelation, indexInfo, false, true);
|
||||
|
||||
/* 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 both the relations, but keep the locks */
|
||||
table_close(heapRel, NoLock);
|
||||
index_close(indexRelation, NoLock);
|
||||
@@ -3299,7 +3317,17 @@ validate_index(Oid heapId, Oid indexId, Snapshot snapshot)
|
||||
|
||||
/* Open and lock the parent heap relation */
|
||||
heapRelation = table_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);
|
||||
|
||||
/*
|
||||
@@ -3312,16 +3340,6 @@ validate_index(Oid heapId, Oid indexId, Snapshot snapshot)
|
||||
/* mark build is concurrent just for consistency */
|
||||
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.
|
||||
*/
|
||||
@@ -3530,6 +3548,9 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
|
||||
Relation iRel,
|
||||
heapRelation;
|
||||
Oid heapId;
|
||||
Oid save_userid;
|
||||
int save_sec_context;
|
||||
int save_nestlevel;
|
||||
IndexInfo *indexInfo;
|
||||
volatile bool skipped_constraint = false;
|
||||
PGRUsage ru0;
|
||||
@@ -3557,6 +3578,16 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
|
||||
if (!heapRelation)
|
||||
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(heapRelation->rd_rel->relowner,
|
||||
save_sec_context | SECURITY_RESTRICTED_OPERATION);
|
||||
save_nestlevel = NewGUCNestLevel();
|
||||
|
||||
if (progress)
|
||||
{
|
||||
const int progress_cols[] = {
|
||||
@@ -3775,12 +3806,18 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
|
||||
errdetail_internal("%s",
|
||||
pg_rusage_show(&ru0))));
|
||||
|
||||
if (progress)
|
||||
pgstat_progress_end_command();
|
||||
/* 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);
|
||||
table_close(heapRelation, NoLock);
|
||||
|
||||
if (progress)
|
||||
pgstat_progress_end_command();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user