Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit95cce56

Browse files
Check for CREATE privilege on the schema in CREATE STATISTICS.
This omission allowed table owners to create statistics in anyschema, potentially leading to unexpected naming conflicts. ForALTER TABLE commands that require re-creating statistics objects,skip this check in case the user has since lost CREATE on theschema. The addition of a second parameter to CreateStatistics()breaks ABI compatibility, but we are unaware of any impactedthird-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-12817Backpatch-through: 13
1 parent96d2c7e commit95cce56

File tree

6 files changed

+56
-4
lines changed

6 files changed

+56
-4
lines changed

‎src/backend/commands/statscmds.c‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ compare_int16(const void *a, const void *b)
6262
*CREATE STATISTICS
6363
*/
6464
ObjectAddress
65-
CreateStatistics(CreateStatsStmt*stmt)
65+
CreateStatistics(CreateStatsStmt*stmt,boolcheck_rights)
6666
{
6767
int16attnums[STATS_MAX_DIMENSIONS];
6868
intnattnums=0;
@@ -175,6 +175,20 @@ CreateStatistics(CreateStatsStmt *stmt)
175175
}
176176
namestrcpy(&stxname,namestr);
177177

178+
/*
179+
* Check we have creation rights in target namespace. Skip check if
180+
* caller doesn't want it.
181+
*/
182+
if (check_rights)
183+
{
184+
AclResultaclresult;
185+
186+
aclresult=pg_namespace_aclcheck(namespaceId,GetUserId(),ACL_CREATE);
187+
if (aclresult!=ACLCHECK_OK)
188+
aclcheck_error(aclresult,OBJECT_SCHEMA,
189+
get_namespace_name(namespaceId));
190+
}
191+
178192
/*
179193
* Deal with the possibility that the statistics object already exists.
180194
*/

‎src/backend/commands/tablecmds.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8662,7 +8662,7 @@ ATExecAddStatistics(AlteredTableInfo *tab, Relation rel,
86628662
/* The CreateStatsStmt has already been through transformStatsStmt */
86638663
Assert(stmt->transformed);
86648664

8665-
address = CreateStatistics(stmt);
8665+
address = CreateStatistics(stmt, !is_rebuild);
86668666

86678667
return address;
86688668
}

‎src/backend/tcop/utility.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1881,7 +1881,7 @@ ProcessUtilitySlow(ParseState *pstate,
18811881
/* Run parse analysis ... */
18821882
stmt=transformStatsStmt(relid,stmt,queryString);
18831883

1884-
address=CreateStatistics(stmt);
1884+
address=CreateStatistics(stmt, true);
18851885
}
18861886
break;
18871887

‎src/include/commands/defrem.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ extern void RemoveOperatorById(Oid operOid);
8080
externObjectAddressAlterOperator(AlterOperatorStmt*stmt);
8181

8282
/* commands/statscmds.c */
83-
externObjectAddressCreateStatistics(CreateStatsStmt*stmt);
83+
externObjectAddressCreateStatistics(CreateStatsStmt*stmt,boolcheck_rights);
8484
externObjectAddressAlterStatistics(AlterStatsStmt*stmt);
8585
externvoidRemoveStatisticsById(OidstatsOid);
8686
externOidStatisticsGetRelation(OidstatId,boolmissing_ok);

‎src/test/regress/expected/stats_ext.out‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3371,6 +3371,23 @@ SELECT statistics_name, most_common_vals FROM pg_stats_ext_exprs x
33713371
s_expr | {1}
33723372
(2 rows)
33733373

3374+
-- CREATE STATISTICS checks for CREATE on the schema
3375+
RESET SESSION AUTHORIZATION;
3376+
CREATE SCHEMA sts_sch1 CREATE TABLE sts_sch1.tbl (a INT, b INT);
3377+
GRANT USAGE ON SCHEMA sts_sch1 TO regress_stats_user1;
3378+
ALTER TABLE sts_sch1.tbl OWNER TO regress_stats_user1;
3379+
SET SESSION AUTHORIZATION regress_stats_user1;
3380+
CREATE STATISTICS sts_sch1.fail ON a, b FROM sts_sch1.tbl;
3381+
ERROR: permission denied for schema sts_sch1
3382+
RESET SESSION AUTHORIZATION;
3383+
GRANT CREATE ON SCHEMA sts_sch1 TO regress_stats_user1;
3384+
SET SESSION AUTHORIZATION regress_stats_user1;
3385+
CREATE STATISTICS sts_sch1.pass ON a, b FROM sts_sch1.tbl;
3386+
-- re-creating statistics via ALTER TABLE bypasses checks for CREATE on schema
3387+
RESET SESSION AUTHORIZATION;
3388+
REVOKE CREATE ON SCHEMA sts_sch1 FROM regress_stats_user1;
3389+
SET SESSION AUTHORIZATION regress_stats_user1;
3390+
ALTER TABLE sts_sch1.tbl ALTER COLUMN a TYPE SMALLINT;
33743391
-- Tidy up
33753392
DROP OPERATOR <<< (int, int);
33763393
DROP FUNCTION op_leak(int, int);
@@ -3383,4 +3400,6 @@ NOTICE: drop cascades to 3 other objects
33833400
DETAIL: drop cascades to table tststats.priv_test_parent_tbl
33843401
drop cascades to table tststats.priv_test_tbl
33853402
drop cascades to view tststats.priv_test_view
3403+
DROP SCHEMA sts_sch1 CASCADE;
3404+
NOTICE: drop cascades to table sts_sch1.tbl
33863405
DROP USER regress_stats_user1;

‎src/test/regress/sql/stats_ext.sql‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1729,6 +1729,24 @@ SELECT statistics_name, most_common_vals FROM pg_stats_ext x
17291729
SELECT statistics_name, most_common_valsFROM pg_stats_ext_exprs x
17301730
WHERE tablename='stats_ext_tbl'ORDER BY ROW(x.*);
17311731

1732+
-- CREATE STATISTICS checks for CREATE on the schema
1733+
RESET SESSION AUTHORIZATION;
1734+
CREATESCHEMAsts_sch1 CREATE TABLEsts_sch1.tbl (aINT, bINT);
1735+
GRANT USAGEON SCHEMA sts_sch1 TO regress_stats_user1;
1736+
ALTERTABLEsts_sch1.tbl OWNER TO regress_stats_user1;
1737+
SET SESSION AUTHORIZATION regress_stats_user1;
1738+
CREATE STATISTICSsts_sch1.failON a, bFROMsts_sch1.tbl;
1739+
RESET SESSION AUTHORIZATION;
1740+
GRANT CREATEON SCHEMA sts_sch1 TO regress_stats_user1;
1741+
SET SESSION AUTHORIZATION regress_stats_user1;
1742+
CREATE STATISTICSsts_sch1.passON a, bFROMsts_sch1.tbl;
1743+
1744+
-- re-creating statistics via ALTER TABLE bypasses checks for CREATE on schema
1745+
RESET SESSION AUTHORIZATION;
1746+
REVOKE CREATEON SCHEMA sts_sch1FROM regress_stats_user1;
1747+
SET SESSION AUTHORIZATION regress_stats_user1;
1748+
ALTERTABLEsts_sch1.tbl ALTER COLUMN a TYPESMALLINT;
1749+
17321750
-- Tidy up
17331751
DROPOPERATOR<<< (int,int);
17341752
DROPFUNCTION op_leak(int,int);
@@ -1737,4 +1755,5 @@ DROP FUNCTION op_leak(record, record);
17371755
RESET SESSION AUTHORIZATION;
17381756
DROPTABLE stats_ext_tbl;
17391757
DROPSCHEMA tststats CASCADE;
1758+
DROPSCHEMA sts_sch1 CASCADE;
17401759
DROPUSER regress_stats_user1;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp