mirror of
https://github.com/postgres/postgres.git
synced 2025-08-08 06:02:22 +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:
@@ -34,6 +34,7 @@
|
||||
#include "miscadmin.h"
|
||||
#include "storage/lmgr.h"
|
||||
#include "storage/smgr.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/snapmgr.h"
|
||||
|
||||
@@ -206,6 +207,9 @@ bt_index_check_internal(Oid indrelid, bool parentcheck, bool heapallindexed)
|
||||
Relation indrel;
|
||||
Relation heaprel;
|
||||
LOCKMODE lockmode;
|
||||
Oid save_userid;
|
||||
int save_sec_context;
|
||||
int save_nestlevel;
|
||||
|
||||
if (parentcheck)
|
||||
lockmode = ShareLock;
|
||||
@@ -222,9 +226,27 @@ bt_index_check_internal(Oid indrelid, bool parentcheck, bool heapallindexed)
|
||||
*/
|
||||
heapid = IndexGetRelation(indrelid, true);
|
||||
if (OidIsValid(heapid))
|
||||
{
|
||||
heaprel = heap_open(heapid, lockmode);
|
||||
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
else
|
||||
{
|
||||
heaprel = NULL;
|
||||
/* for "gcc -Og" https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78394 */
|
||||
save_userid = InvalidOid;
|
||||
save_sec_context = -1;
|
||||
save_nestlevel = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open the target index relations separately (like relation_openrv(), but
|
||||
@@ -267,6 +289,12 @@ bt_index_check_internal(Oid indrelid, bool parentcheck, bool heapallindexed)
|
||||
bt_check_every_level(indrel, heaprel, parentcheck, heapallindexed);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
/*
|
||||
* Release locks early. That's ok here because nothing in the called
|
||||
* routines will trigger shared cache invalidations to be sent, so we can
|
||||
|
Reference in New Issue
Block a user