Avoid repeated table name lookups in createPartitionTable()

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
pull/175/head
Alexander Korotkov 1 year ago
parent 9bb842f95e
commit 04158e7fa3
  1. 3
      src/backend/commands/tablecmds.c
  2. 1
      src/backend/parser/gram.y
  3. 6
      src/backend/tcop/utility.c
  4. 1
      src/include/nodes/parsenodes.h

@ -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

@ -4138,6 +4138,7 @@ TableLikeClause:
n->relation = $2;
n->options = $3;
n->relationOid = InvalidOid;
n->newRelationOid = InvalidOid;
$$ = (Node *) n;
}
;

@ -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
{

@ -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

Loading…
Cancel
Save