Avoid repeated table name lookups in createPartitionTable()
authorAlexander Korotkov <[email protected]>
Thu, 22 Aug 2024 06:50:48 +0000 (09:50 +0300)
committerAlexander Korotkov <[email protected]>
Thu, 22 Aug 2024 06:50:48 +0000 (09:50 +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 13bb8811204323a9d0a52e0e7db0b08efeb2e1f6..52ce6b0c92a4572986716d979ecf5043161395cc 100644 (file)
@@ -20383,6 +20383,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. */
@@ -20406,7 +20407,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 c3f25582c383e7a1487e4f6b447d7c89e2551463..b7d98eb9f02e7ead63aaa616560c64d0aeaf07fa 100644 (file)
@@ -4138,6 +4138,7 @@ TableLikeClause:
                    n->relation = $2;
                    n->options = $3;
                    n->relationOid = InvalidOid;
+                   n->newRelationOid = InvalidOid;
                    $$ = (Node *) n;
                }
        ;
index b2ea8125c92423ecfc0529208b8dc7e701428dbc..b385175e7a2bd9d8050d4fa20d65bb66b55494ad 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