mirror of
https://github.com/postgres/postgres.git
synced 2025-07-09 22:41:56 +03:00
Replace last PushOverrideSearchPath() call with set_config_option().
The two methods don't cooperate, so set_config_option("search_path", ...) has been ineffective under non-empty overrideStack. This defect enabled an attacker having database-level CREATE privilege to execute arbitrary code as the bootstrap superuser. While that particular attack requires v13+ for the trusted extension attribute, other attacks are feasible in all supported versions. Standardize on the combination of NewGUCNestLevel() and set_config_option("search_path", ...). It is newer than PushOverrideSearchPath(), more-prevalent, and has no known disadvantages. The "override" mechanism remains for now, for compatibility with out-of-tree code. Users should update such code, which likely suffers from the same sort of vulnerability closed here. Back-patch to v11 (all supported versions). Alexander Lakhin. Reported by Alexander Lakhin. Security: CVE-2023-2454
This commit is contained in:
@ -30,6 +30,7 @@
|
||||
#include "commands/schemacmds.h"
|
||||
#include "miscadmin.h"
|
||||
#include "parser/parse_utilcmd.h"
|
||||
#include "parser/scansup.h"
|
||||
#include "tcop/utility.h"
|
||||
#include "utils/acl.h"
|
||||
#include "utils/builtins.h"
|
||||
@ -53,14 +54,16 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString,
|
||||
{
|
||||
const char *schemaName = stmt->schemaname;
|
||||
Oid namespaceId;
|
||||
OverrideSearchPath *overridePath;
|
||||
List *parsetree_list;
|
||||
ListCell *parsetree_item;
|
||||
Oid owner_uid;
|
||||
Oid saved_uid;
|
||||
int save_sec_context;
|
||||
int save_nestlevel;
|
||||
char *nsp = namespace_search_path;
|
||||
AclResult aclresult;
|
||||
ObjectAddress address;
|
||||
StringInfoData pathbuf;
|
||||
|
||||
GetUserIdAndSecContext(&saved_uid, &save_sec_context);
|
||||
|
||||
@ -153,14 +156,26 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString,
|
||||
CommandCounterIncrement();
|
||||
|
||||
/*
|
||||
* Temporarily make the new namespace be the front of the search path, as
|
||||
* well as the default creation target namespace. This will be undone at
|
||||
* the end of this routine, or upon error.
|
||||
* Prepend the new schema to the current search path.
|
||||
*
|
||||
* We use the equivalent of a function SET option to allow the setting to
|
||||
* persist for exactly the duration of the schema creation. guc.c also
|
||||
* takes care of undoing the setting on error.
|
||||
*/
|
||||
overridePath = GetOverrideSearchPath(CurrentMemoryContext);
|
||||
overridePath->schemas = lcons_oid(namespaceId, overridePath->schemas);
|
||||
/* XXX should we clear overridePath->useTemp? */
|
||||
PushOverrideSearchPath(overridePath);
|
||||
save_nestlevel = NewGUCNestLevel();
|
||||
|
||||
initStringInfo(&pathbuf);
|
||||
appendStringInfoString(&pathbuf, quote_identifier(schemaName));
|
||||
|
||||
while (scanner_isspace(*nsp))
|
||||
nsp++;
|
||||
|
||||
if (*nsp != '\0')
|
||||
appendStringInfo(&pathbuf, ", %s", nsp);
|
||||
|
||||
(void) set_config_option("search_path", pathbuf.data,
|
||||
PGC_USERSET, PGC_S_SESSION,
|
||||
GUC_ACTION_SAVE, true, 0, false);
|
||||
|
||||
/*
|
||||
* Report the new schema to possibly interested event triggers. Note we
|
||||
@ -215,8 +230,10 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString,
|
||||
CommandCounterIncrement();
|
||||
}
|
||||
|
||||
/* Reset search path to normal state */
|
||||
PopOverrideSearchPath();
|
||||
/*
|
||||
* Restore the GUC variable search_path we set above.
|
||||
*/
|
||||
AtEOXact_GUC(true, save_nestlevel);
|
||||
|
||||
/* Reset current user and security context */
|
||||
SetUserIdAndSecContext(saved_uid, save_sec_context);
|
||||
|
Reference in New Issue
Block a user