]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Avoid repeated table name lookups in createPartitionTable()
authorAlexander Korotkov <akorotkov@postgresql.org>
Thu, 22 Aug 2024 06:50:48 +0000 (09:50 +0300)
committerAlexander Korotkov <akorotkov@postgresql.org>
Thu, 22 Aug 2024 06:52:54 +0000 (09:52 +0300)
Currently, createPartitionTable() opens newly created table using its name.
This approach is prone to privilege escalation attack, because we might end
up opening another table than we just created.

This commit address the issue above by opening newly created table by its
OID.  It appears to be tricky to get a relation OID out of ProcessUtility().
We have to extend TableLikeClause with new newRelationOid field, which is
filled within ProcessUtility() to be further accessed by caller.

Security: CVE-2014-0062
Reported-by: Noah Misch
Discussion: https://postgr.es/m/20240808171351.a9.nmisch%40google.com
Reviewed-by: Pavel Borisov, Dmitry Koval
src/backend/commands/tablecmds.c
src/backend/parser/gram.y
src/backend/tcop/utility.c
src/include/nodes/parsenodes.h

index d219d220691cf139f23567f418f55250d901ebf0..82dabe636f8a2b2cfbb5a3105f2fa75c1bb3a8d4 100644 (file)
@@ -20391,6 +20391,7 @@ createPartitionTable(RangeVar *newPartName, Relation modelRel,
        tlc->options = CREATE_TABLE_LIKE_ALL &
                ~(CREATE_TABLE_LIKE_INDEXES | CREATE_TABLE_LIKE_IDENTITY | CREATE_TABLE_LIKE_STATISTICS);
        tlc->relationOid = InvalidOid;
+       tlc->newRelationOid = InvalidOid;
        createStmt->tableElts = lappend(createStmt->tableElts, tlc);
 
        /* Need to make a wrapper PlannedStmt. */
@@ -20414,7 +20415,7 @@ createPartitionTable(RangeVar *newPartName, Relation modelRel,
         * Open the new partition with no lock, because we already have
         * AccessExclusiveLock placed there after creation.
         */
-       newRel = table_openrv(newPartName, NoLock);
+       newRel = table_open(tlc->newRelationOid, NoLock);
 
        /*
         * We intended to create the partition with the same persistence as the
index a043fd4c669a8ad13ead2aebf599d78a84ce8392..f92580c318191c3d549018afa76e1fc2642ea63b 100644 (file)
@@ -4138,6 +4138,7 @@ TableLikeClause:
                                        n->relation = $2;
                                        n->options = $3;
                                        n->relationOid = InvalidOid;
+                                       n->newRelationOid = InvalidOid;
                                        $$ = (Node *) n;
                                }
                ;
index fa66b8017edea238d327011013594a6bded91b3a..b317c9ae9d636e0bd9d899791b02590f8f16029e 100644 (file)
@@ -1225,6 +1225,12 @@ ProcessUtilitySlow(ParseState *pstate,
 
                                                        morestmts = expandTableLikeClause(table_rv, like);
                                                        stmts = list_concat(morestmts, stmts);
+
+                                                       /*
+                                                        * Store the OID of newly created relation to the
+                                                        * TableLikeClause for the caller to use it.
+                                                        */
+                                                       like->newRelationOid = address.objectId;
                                                }
                                                else
                                                {
index 85a62b538e50f9e00c669b40906531283dfdb3b3..577c4bfef765fbfc63cadcad2b7c3d8f72c54cfc 100644 (file)
@@ -754,6 +754,7 @@ typedef struct TableLikeClause
        RangeVar   *relation;
        bits32          options;                /* OR of TableLikeOption flags */
        Oid                     relationOid;    /* If table has been looked up, its OID */
+       Oid                     newRelationOid; /* OID of newly created table */
 } TableLikeClause;
 
 typedef enum TableLikeOption