postgres.git / summary / log / commit / refs
commit b6e45b4f82481b54134640887fc1cdf4791f9b3a
Author: Nathan Bossart <nathan@postgresql.org>
Commit: Noah Misch <noah@leadboat.com>
Date: Mon Aug 10 13:38:36 2026 +0000
Check for USAGE privilege on the composite type in ALTER TABLE OF.
This omission allowed roles without USAGE on a type to create
tables that depend on it, which could prevent the owner from
changing the type later.
Reported-by: Nathan Bossart <nathandbossart@gmail.com>
Author: Nathan Bossart <nathandbossart@gmail.com>
Reviewed-by: Robert Haas <robertmhaas@gmail.com>
Security: CVE-2026-6470
Backpatch-through: 14
src/backend/commands/tablecmds.c | 5 +++++
src/test/regress/expected/privileges.out | 6 ++++++
src/test/regress/sql/privileges.sql | 5 +++++
3 files changed, 16 insertions(+)
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index a2697d624b6..e445b801a6b 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -15504,6 +15504,7 @@ ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode)
ObjectAddress tableobj,
typeobj;
HeapTuple classtuple;
+ AclResult aclresult;
/* Validate the type. */
typetuple = typenameType(NULL, ofTypename, NULL);
@@ -15511,6 +15512,10 @@ ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode)
typeform = (Form_pg_type) GETSTRUCT(typetuple);
typeid = typeform->oid;
+ aclresult = pg_type_aclcheck(typeid, GetUserId(), ACL_USAGE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error_type(aclresult, typeid);
+
/* Fail if the table has any inheritance parents. */
inheritsRelation = table_open(InheritsRelationId, AccessShareLock);
ScanKeyInit(&key,
diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out
index f0e4b5b6ece..416866ded3f 100644
--- a/src/test/regress/expected/privileges.out
+++ b/src/test/regress/expected/privileges.out
@@ -1096,6 +1096,9 @@ CREATE TABLE test5a (a int, b priv_testdomain1);
ERROR: permission denied for type priv_testdomain1
CREATE TABLE test6a OF priv_testtype1;
ERROR: permission denied for type priv_testtype1
+CREATE TABLE test6a2 (a int, b text);
+ALTER TABLE test6a2 OF priv_testtype1;
+ERROR: permission denied for type priv_testtype1
CREATE TABLE test10a (a int[], b priv_testtype1[]);
ERROR: permission denied for type priv_testtype1
CREATE TABLE test9a (a int, b int);
@@ -1143,6 +1146,8 @@ CREATE FUNCTION priv_testfunc7b(a int DEFAULT ('(0,1)'::priv_testtype1).a) RETUR
CREATE OPERATOR !! (PROCEDURE = priv_testfunc5b, RIGHTARG = priv_testdomain1);
CREATE TABLE test5b (a int, b priv_testdomain1);
CREATE TABLE test6b OF priv_testtype1;
+CREATE TABLE test6b2 (a int, b text);
+ALTER TABLE test6b2 OF priv_testtype1;
CREATE TABLE test10b (a int[], b priv_testtype1[]);
CREATE TABLE test9b (a int, b int);
ALTER TABLE test9b ADD COLUMN c priv_testdomain1;
@@ -1184,6 +1189,7 @@ DROP FUNCTION priv_testfunc6b(b int);
DROP FUNCTION priv_testfunc7b(a int);
DROP TABLE test5b;
DROP TABLE test6b;
+DROP TABLE test6b2;
DROP TABLE test9b;
DROP TABLE test10b;
DROP TYPE test7b;
diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql
index 630cdc2f2d5..f2307460659 100644
--- a/src/test/regress/sql/privileges.sql
+++ b/src/test/regress/sql/privileges.sql
@@ -724,6 +724,8 @@ CREATE OPERATOR !+! (PROCEDURE = int4pl, LEFTARG = priv_testdomain1, RIGHTARG =
CREATE TABLE test5a (a int, b priv_testdomain1);
CREATE TABLE test6a OF priv_testtype1;
+CREATE TABLE test6a2 (a int, b text);
+ALTER TABLE test6a2 OF priv_testtype1;
CREATE TABLE test10a (a int[], b priv_testtype1[]);
CREATE TABLE test9a (a int, b int);
@@ -772,6 +774,8 @@ CREATE OPERATOR !! (PROCEDURE = priv_testfunc5b, RIGHTARG = priv_testdomain1);
CREATE TABLE test5b (a int, b priv_testdomain1);
CREATE TABLE test6b OF priv_testtype1;
+CREATE TABLE test6b2 (a int, b text);
+ALTER TABLE test6b2 OF priv_testtype1;
CREATE TABLE test10b (a int[], b priv_testtype1[]);
CREATE TABLE test9b (a int, b int);
@@ -819,6 +823,7 @@ DROP FUNCTION priv_testfunc6b(b int);
DROP FUNCTION priv_testfunc7b(a int);
DROP TABLE test5b;
DROP TABLE test6b;
+DROP TABLE test6b2;
DROP TABLE test9b;
DROP TABLE test10b;
DROP TYPE test7b;
[parent: 1a358b8f2a28]