1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-16 15:02:33 +03:00

Check for CREATE privilege on the schema in CREATE STATISTICS.

This omission allowed table owners to create statistics in any
schema, potentially leading to unexpected naming conflicts.  For
ALTER TABLE commands that require re-creating statistics objects,
skip this check in case the user has since lost CREATE on the
schema.  The addition of a second parameter to CreateStatistics()
breaks ABI compatibility, but we are unaware of any impacted
third-party code.

Reported-by: Jelte Fennema-Nio <postgres@jeltef.nl>
Author: Jelte Fennema-Nio <postgres@jeltef.nl>
Co-authored-by: Nathan Bossart <nathandbossart@gmail.com>
Reviewed-by: Noah Misch <noah@leadboat.com>
Reviewed-by: Álvaro Herrera <alvherre@kurilemu.de>
Security: CVE-2025-12817
Backpatch-through: 13
This commit is contained in:
Nathan Bossart
2025-11-10 09:00:00 -06:00
parent 600086f471
commit 5e4fcbe531
6 changed files with 90 additions and 4 deletions

View File

@@ -60,7 +60,7 @@ compare_int16(const void *a, const void *b)
* CREATE STATISTICS
*/
ObjectAddress
CreateStatistics(CreateStatsStmt *stmt)
CreateStatistics(CreateStatsStmt *stmt, bool check_rights)
{
int16 attnums[STATS_MAX_DIMENSIONS];
int nattnums = 0;
@@ -170,6 +170,21 @@ CreateStatistics(CreateStatsStmt *stmt)
}
namestrcpy(&stxname, namestr);
/*
* Check we have creation rights in target namespace. Skip check if
* caller doesn't want it.
*/
if (check_rights)
{
AclResult aclresult;
aclresult = object_aclcheck(NamespaceRelationId, namespaceId,
GetUserId(), ACL_CREATE);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, OBJECT_SCHEMA,
get_namespace_name(namespaceId));
}
/*
* Deal with the possibility that the statistics object already exists.
*/

View File

@@ -9682,7 +9682,7 @@ ATExecAddStatistics(AlteredTableInfo *tab, Relation rel,
/* The CreateStatsStmt has already been through transformStatsStmt */
Assert(stmt->transformed);
address = CreateStatistics(stmt);
address = CreateStatistics(stmt, !is_rebuild);
return address;
}

View File

@@ -1900,7 +1900,7 @@ ProcessUtilitySlow(ParseState *pstate,
/* Run parse analysis ... */
stmt = transformStatsStmt(relid, stmt, queryString);
address = CreateStatistics(stmt);
address = CreateStatistics(stmt, true);
}
break;