Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > d3c4bfd951c25dab3d8c83571c73f957 > files > 22

postgresql-8.1.23-10.el5_10.src.rpm

From b3e62c24fffc67cbb9b9aa1420d4fea38e8261cc Mon Sep 17 00:00:00 2001
From: Pavel Raiskup <praiskup@redhat.com>
Date: Sat, 22 Feb 2014 07:46:51 -0100
Subject: [PATCH] Fix for CVE-2014-0062

---
 src/backend/bootstrap/bootparse.y | 13 ++++++--
 src/backend/catalog/index.c       |  3 +-
 src/backend/commands/alter.c      |  4 +--
 src/backend/commands/indexcmds.c  | 15 +++++----
 src/backend/commands/tablecmds.c  | 65 +++++++++++++++++++++------------------
 src/backend/commands/trigger.c    | 24 ++++++++++++---
 src/backend/nodes/copyfuncs.c     |  1 +
 src/backend/nodes/equalfuncs.c    |  1 +
 src/backend/nodes/outfuncs.c      |  1 +
 src/backend/tcop/utility.c        | 49 +++++++++++++++++++++++------
 src/include/catalog/index.h       |  2 ++
 src/include/commands/defrem.h     |  2 +-
 src/include/commands/tablecmds.h  |  2 +-
 src/include/commands/trigger.h    |  3 +-
 src/include/nodes/parsenodes.h    |  1 +
 src/include/tcop/utility.h        |  2 +-
 16 files changed, 127 insertions(+), 61 deletions(-)

diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y
index a3b2285..1fbd5ea 100644
--- a/src/backend/bootstrap/bootparse.y
+++ b/src/backend/bootstrap/bootparse.y
@@ -27,6 +27,7 @@
 #include "bootstrap/bootstrap.h"
 #include "catalog/catalog.h"
 #include "catalog/heap.h"
+#include "catalog/namespace.h"
 #include "catalog/pg_am.h"
 #include "catalog/pg_attribute.h"
 #include "catalog/pg_authid.h"
@@ -242,9 +243,13 @@ Boot_InsertStmt:
 Boot_DeclareIndexStmt:
 		  XDECLARE INDEX boot_ident oidspec ON boot_ident USING boot_ident LPAREN boot_index_params RPAREN
 				{
+					Oid		relationId;
 					do_start();
 
-					DefineIndex(makeRangeVar(NULL, LexIDStr($6)),
+					relationId = RangeVarGetRelid(makeRangeVar(NULL, LexIDStr($6)),
+												  false);
+
+					DefineIndex(relationId,
 								LexIDStr($3),
 								$4,
 								LexIDStr($8),
@@ -260,9 +265,13 @@ Boot_DeclareIndexStmt:
 Boot_DeclareUniqueIndexStmt:
 		  XDECLARE UNIQUE INDEX boot_ident oidspec ON boot_ident USING boot_ident LPAREN boot_index_params RPAREN
 				{
+					Oid		relationId;
 					do_start();
 
-					DefineIndex(makeRangeVar(NULL, LexIDStr($7)),
+					relationId = RangeVarGetRelid(makeRangeVar(NULL, LexIDStr($7)),
+												  false);
+
+					DefineIndex(relationId,
 								LexIDStr($4),
 								$5,
 								LexIDStr($9),
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index d39b810..a8ffec1 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -64,7 +64,6 @@ static void UpdateIndexRelation(Oid indexoid, Oid heapoid,
 					IndexInfo *indexInfo,
 					Oid *classOids,
 					bool primary);
-static Oid	IndexGetRelation(Oid indexId);
 static void UpdateStats(Oid relid, double reltuples);
 
 
@@ -1632,7 +1631,7 @@ IndexBuildHeapScan(Relation heapRelation,
  * IndexGetRelation: given an index's relation OID, get the OID of the
  * relation it is an index on.	Uses the system cache.
  */
-static Oid
+Oid
 IndexGetRelation(Oid indexId)
 {
 	HeapTuple	tuple;
diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c
index 23cf8bf..c5c857a 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -91,9 +91,8 @@ ExecRenameStmt(RenameStmt *stmt)
 			{
 				Oid			relid;
 
-				CheckRelationOwnership(stmt->relation, true);
-
 				relid = RangeVarGetRelid(stmt->relation, false);
+				CheckRelationOwnership(relid, true);
 
 				switch (stmt->renameType)
 				{
@@ -159,7 +158,6 @@ ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
 
 		case OBJECT_SEQUENCE:
 		case OBJECT_TABLE:
-			CheckRelationOwnership(stmt->relation, true);
 			AlterTableNamespace(stmt->relation, stmt->newschema);
 			break;
 
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 81ab2e8..ca75a02 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -60,7 +60,8 @@ static bool relationHasPrimaryKey(Relation rel);
  * DefineIndex
  *		Creates a new index.
  *
- * 'heapRelation': the relation the index will apply to.
+ * 'relationId': the OID of the heap relation on which the index is to be
+ *		created
  * 'indexRelationName': the name for the new index, or NULL to indicate
  *		that a nonconflicting default name should be picked.
  * 'indexRelationId': normally InvalidOid, but during bootstrap can be
@@ -84,7 +85,7 @@ static bool relationHasPrimaryKey(Relation rel);
  * 'quiet': suppress the NOTICE chatter ordinarily provided for constraints.
  */
 void
-DefineIndex(RangeVar *heapRelation,
+DefineIndex(Oid relationId,
 			char *indexRelationName,
 			Oid indexRelationId,
 			char *accessMethodName,
@@ -102,7 +103,6 @@ DefineIndex(RangeVar *heapRelation,
 {
 	Oid		   *classObjectId;
 	Oid			accessMethodId;
-	Oid			relationId;
 	Oid			namespaceId;
 	Oid			tablespaceId;
 	Relation	rel;
@@ -127,8 +127,11 @@ DefineIndex(RangeVar *heapRelation,
 
 	/*
 	 * Open heap relation, acquire a suitable lock on it, remember its OID
+	 *
+	 * NB: Caller is responsible for making sure that relationId refers
+	 * to the relation on which the index should be built.
 	 */
-	rel = heap_openrv(heapRelation, ShareLock);
+	rel = heap_open(relationId, ShareLock);
 
 	/* Note: during bootstrap may see uncataloged relation */
 	if (rel->rd_rel->relkind != RELKIND_RELATION &&
@@ -136,9 +139,9 @@ DefineIndex(RangeVar *heapRelation,
 		ereport(ERROR,
 				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
 				 errmsg("\"%s\" is not a table",
-						heapRelation->relname)));
+						RelationGetRelationName(rel))));
 
-	relationId = RelationGetRelid(rel);
+	relationId = RelationGetRelid(rel); /* empty operation? */
 	namespaceId = RelationGetNamespace(rel);
 
 	/*
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 3d2e385..04a79c6 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -53,6 +53,7 @@
 #include "parser/parse_type.h"
 #include "rewrite/rewriteHandler.h"
 #include "storage/smgr.h"
+#include "tcop/utility.h"
 #include "utils/acl.h"
 #include "utils/builtins.h"
 #include "utils/fmgroids.h"
@@ -180,8 +181,8 @@ static Oid transformFkeyCheckAttrs(Relation pkrel,
 						Oid *opclasses);
 static void validateForeignKeyConstraint(FkConstraint *fkconstraint,
 							 Relation rel, Relation pkrel);
-static void createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
-						 Oid constrOid);
+static void createForeignKeyTriggers(Relation rel, Oid refRelOid,
+							FkConstraint *fkconstraint, Oid constrOid);
 static char *fkMatchTypeToString(char match_type);
 static void ATController(Relation rel, List *cmds, bool recurse);
 static void ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
@@ -1862,9 +1863,9 @@ CheckTableNotInUse(Relation rel, const char *stmt)
  * the whole operation; we don't have to do anything special to clean up.
  */
 void
-AlterTable(AlterTableStmt *stmt)
+AlterTable(Oid relid, AlterTableStmt *stmt)
 {
-	Relation rel = relation_openrv(stmt->relation, AccessExclusiveLock);
+	Relation rel = relation_open(relid, AccessExclusiveLock);
 
 	CheckTableNotInUse(rel, "ALTER TABLE");
 
@@ -3776,7 +3777,7 @@ ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
 	/* suppress notices when rebuilding existing index */
 	quiet = is_rebuild;
 
-	DefineIndex(stmt->relation, /* relation */
+	DefineIndex(RelationGetRelid(rel), /* relation */
 				stmt->idxname,	/* index name */
 				InvalidOid,		/* no predefined OID */
 				stmt->accessMethod,		/* am name */
@@ -3916,7 +3917,10 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
 	 * table; trying to start with a lesser lock will just create a risk of
 	 * deadlock.)
 	 */
-	pkrel = heap_openrv(fkconstraint->pktable, AccessExclusiveLock);
+	if (OidIsValid(fkconstraint->old_pktable_oid))
+		pkrel = heap_open(fkconstraint->old_pktable_oid, AccessExclusiveLock);
+	else
+		pkrel = heap_openrv(fkconstraint->pktable, AccessExclusiveLock);
 
 	/*
 	 * Validity and permissions checks
@@ -4107,7 +4111,8 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
 	/*
 	 * Create the triggers that will enforce the constraint.
 	 */
-	createForeignKeyTriggers(rel, fkconstraint, constrOid);
+	createForeignKeyTriggers(rel, RelationGetRelid(pkrel), fkconstraint,
+							 constrOid);
 
 	/*
 	 * Close pk table, but keep lock until we've committed.
@@ -4459,7 +4464,7 @@ validateForeignKeyConstraint(FkConstraint *fkconstraint,
 }
 
 static void
-CreateFKCheckTrigger(RangeVar *myRel, FkConstraint *fkconstraint,
+CreateFKCheckTrigger(Oid myRelOid, Oid refRelOid, FkConstraint *fkconstraint,
 					 ObjectAddress *constrobj, ObjectAddress *trigobj,
 					 bool on_insert)
 {
@@ -4469,7 +4474,7 @@ CreateFKCheckTrigger(RangeVar *myRel, FkConstraint *fkconstraint,
 
 	fk_trigger = makeNode(CreateTrigStmt);
 	fk_trigger->trigname = fkconstraint->constr_name;
-	fk_trigger->relation = myRel;
+	fk_trigger->relation = NULL;
 	fk_trigger->before = false;
 	fk_trigger->row = true;
 
@@ -4495,7 +4500,7 @@ CreateFKCheckTrigger(RangeVar *myRel, FkConstraint *fkconstraint,
 	fk_trigger->args = lappend(fk_trigger->args,
 							   makeString(fkconstraint->constr_name));
 	fk_trigger->args = lappend(fk_trigger->args,
-							   makeString(myRel->relname));
+							   makeString(get_rel_name(myRelOid)));
 	fk_trigger->args = lappend(fk_trigger->args,
 							   makeString(fkconstraint->pktable->relname));
 	fk_trigger->args = lappend(fk_trigger->args,
@@ -4512,7 +4517,7 @@ CreateFKCheckTrigger(RangeVar *myRel, FkConstraint *fkconstraint,
 		fk_trigger->args = lappend(fk_trigger->args, lfirst(pk_attr));
 	}
 
-	trigobj->objectId = CreateTrigger(fk_trigger, true);
+	trigobj->objectId = CreateTrigger(fk_trigger, myRelOid, refRelOid, true);
 
 	/* Register dependency from trigger to constraint */
 	recordDependencyOn(trigobj, constrobj, DEPENDENCY_INTERNAL);
@@ -4525,21 +4530,17 @@ CreateFKCheckTrigger(RangeVar *myRel, FkConstraint *fkconstraint,
  * Create the triggers that implement an FK constraint.
  */
 static void
-createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
-						 Oid constrOid)
+createForeignKeyTriggers(Relation rel, Oid refRelOid,
+						 FkConstraint *fkconstraint, Oid constrOid)
 {
-	RangeVar   *myRel;
+	Oid			myRelOid;
 	CreateTrigStmt *fk_trigger;
 	ListCell   *fk_attr;
 	ListCell   *pk_attr;
 	ObjectAddress trigobj,
 				constrobj;
 
-	/*
-	 * Reconstruct a RangeVar for my relation (not passed in, unfortunately).
-	 */
-	myRel = makeRangeVar(get_namespace_name(RelationGetNamespace(rel)),
-						 pstrdup(RelationGetRelationName(rel)));
+	myRelOid = RelationGetRelid(rel);
 
 	/*
 	 * Preset objectAddress fields
@@ -4557,8 +4558,10 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
 	 * Build and execute a CREATE CONSTRAINT TRIGGER statement for the CHECK
 	 * action for both INSERTs and UPDATEs on the referencing table.
 	 */
-	CreateFKCheckTrigger(myRel, fkconstraint, &constrobj, &trigobj, true);
-	CreateFKCheckTrigger(myRel, fkconstraint, &constrobj, &trigobj, false);
+	CreateFKCheckTrigger(myRelOid, refRelOid, fkconstraint,
+						 &constrobj, &trigobj, true);
+	CreateFKCheckTrigger(myRelOid, refRelOid, fkconstraint,
+						 &constrobj, &trigobj, false);
 
 	/*
 	 * Build and execute a CREATE CONSTRAINT TRIGGER statement for the ON
@@ -4566,14 +4569,14 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
 	 */
 	fk_trigger = makeNode(CreateTrigStmt);
 	fk_trigger->trigname = fkconstraint->constr_name;
-	fk_trigger->relation = fkconstraint->pktable;
+	fk_trigger->relation = NULL;
 	fk_trigger->before = false;
 	fk_trigger->row = true;
 	fk_trigger->actions[0] = 'd';
 	fk_trigger->actions[1] = '\0';
 
 	fk_trigger->isconstraint = true;
-	fk_trigger->constrrel = myRel;
+	fk_trigger->constrrel = rel;
 	switch (fkconstraint->fk_del_action)
 	{
 		case FKCONSTR_ACTION_NOACTION:
@@ -4611,7 +4614,7 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
 	fk_trigger->args = lappend(fk_trigger->args,
 							   makeString(fkconstraint->constr_name));
 	fk_trigger->args = lappend(fk_trigger->args,
-							   makeString(myRel->relname));
+							   makeString(get_rel_name(myRelOid)));
 	fk_trigger->args = lappend(fk_trigger->args,
 							   makeString(fkconstraint->pktable->relname));
 	fk_trigger->args = lappend(fk_trigger->args,
@@ -4623,7 +4626,7 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
 		fk_trigger->args = lappend(fk_trigger->args, lfirst(pk_attr));
 	}
 
-	trigobj.objectId = CreateTrigger(fk_trigger, true);
+	trigobj.objectId = CreateTrigger(fk_trigger, refRelOid, myRelOid, true);
 
 	/* Register dependency from trigger to constraint */
 	recordDependencyOn(&trigobj, &constrobj, DEPENDENCY_INTERNAL);
@@ -4637,13 +4640,13 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
 	 */
 	fk_trigger = makeNode(CreateTrigStmt);
 	fk_trigger->trigname = fkconstraint->constr_name;
-	fk_trigger->relation = fkconstraint->pktable;
+	fk_trigger->relation = NULL;
 	fk_trigger->before = false;
 	fk_trigger->row = true;
 	fk_trigger->actions[0] = 'u';
 	fk_trigger->actions[1] = '\0';
 	fk_trigger->isconstraint = true;
-	fk_trigger->constrrel = myRel;
+	fk_trigger->constrrel = rel;
 	switch (fkconstraint->fk_upd_action)
 	{
 		case FKCONSTR_ACTION_NOACTION:
@@ -4681,7 +4684,7 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
 	fk_trigger->args = lappend(fk_trigger->args,
 							   makeString(fkconstraint->constr_name));
 	fk_trigger->args = lappend(fk_trigger->args,
-							   makeString(myRel->relname));
+							   makeString(get_rel_name(myRelOid)));
 	fk_trigger->args = lappend(fk_trigger->args,
 							   makeString(fkconstraint->pktable->relname));
 	fk_trigger->args = lappend(fk_trigger->args,
@@ -4693,7 +4696,7 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
 		fk_trigger->args = lappend(fk_trigger->args, lfirst(pk_attr));
 	}
 
-	trigobj.objectId = CreateTrigger(fk_trigger, true);
+	trigobj.objectId = CreateTrigger(fk_trigger, refRelOid, myRelOid, true);
 
 	/* Register dependency from trigger to constraint */
 	recordDependencyOn(&trigobj, &constrobj, DEPENDENCY_INTERNAL);
@@ -6230,7 +6233,8 @@ needs_toast_table(Relation rel)
 /*
  * Execute ALTER TABLE SET SCHEMA
  *
- * Note: caller must have checked ownership of the relation already
+ * WARNING WARNING WARNING: In previous *minor* releases the caller was
+ * responsible for checking ownership of the relation, but now we do it here.
  */
 void
 AlterTableNamespace(RangeVar *relation, const char *newschema)
@@ -6251,6 +6255,7 @@ AlterTableNamespace(RangeVar *relation, const char *newschema)
 						RelationGetRelationName(rel))));
 
 	relid = RelationGetRelid(rel);
+	CheckRelationOwnership(relid, true);
 	oldNspOid = RelationGetNamespace(rel);
 
 	/* get schema OID and check its permissions */
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index ace9924..2d79fae 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -58,13 +58,21 @@ static void AfterTriggerSaveEvent(ResultRelInfo *relinfo, int event,
 /*
  * Create a trigger.  Returns the OID of the created trigger.
  *
+ * relOid, if nonzero, is the relation on which the trigger should be
+ * created.  If zero, the name provided in the statement will be looked up.
+ *
+ * refRelOid, if nonzero, is the relation to which the constraint trigger
+ * refers.  If zero, the constraint relation name provided in the statement
+ * will be looked up as needed.
+ *
  * forConstraint, if true, says that this trigger is being created to
  * implement a constraint.	The caller will then be expected to make
  * a pg_depend entry linking the trigger to that constraint (and thereby
  * to the owning relation(s)).
  */
 Oid
-CreateTrigger(CreateTrigStmt *stmt, bool forConstraint)
+CreateTrigger(CreateTrigStmt *stmt, Oid relOid, Oid refRelOid,
+			  bool forConstraint)
 {
 	int16		tgtype;
 	int2vector *tgattr;
@@ -90,10 +98,18 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint)
 	ObjectAddress myself,
 				referenced;
 
-	rel = heap_openrv(stmt->relation, AccessExclusiveLock);
+	if (OidIsValid(relOid))
+		rel = heap_open(relOid, AccessExclusiveLock);
+	else
+		rel = heap_openrv(stmt->relation, AccessExclusiveLock);
 
 	if (stmt->constrrel != NULL)
-		constrrelid = RangeVarGetRelid(stmt->constrrel, false);
+	{
+		if (OidIsValid(refRelOid))
+			constrrelid = refRelOid;
+		else
+			constrrelid = RangeVarGetRelid(stmt->constrrel, false);
+	}
 	else if (stmt->isconstraint)
 	{
 		/*
@@ -266,7 +282,7 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint)
 			ereport(ERROR,
 					(errcode(ERRCODE_DUPLICATE_OBJECT),
 				  errmsg("trigger \"%s\" for relation \"%s\" already exists",
-						 trigname, stmt->relation->relname)));
+						 trigname, RelationGetRelationName(rel))));
 		found++;
 	}
 	systable_endscan(tgscan);
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 8cb209a..76e69f8 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -1335,6 +1335,7 @@ _copyFkConstraint(FkConstraint *from)
 	COPY_SCALAR_FIELD(deferrable);
 	COPY_SCALAR_FIELD(initdeferred);
 	COPY_SCALAR_FIELD(skip_validation);
+	COPY_SCALAR_FIELD(old_pktable_oid);
 
 	return newnode;
 }
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 1940d78..7665432 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1701,6 +1701,7 @@ _equalFkConstraint(FkConstraint *a, FkConstraint *b)
 	COMPARE_SCALAR_FIELD(deferrable);
 	COMPARE_SCALAR_FIELD(initdeferred);
 	COMPARE_SCALAR_FIELD(skip_validation);
+	COMPARE_SCALAR_FIELD(old_pktable_oid);
 
 	return true;
 }
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 75a9fa3..25ca107 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -1764,6 +1764,7 @@ _outFkConstraint(StringInfo str, FkConstraint *node)
 	WRITE_BOOL_FIELD(deferrable);
 	WRITE_BOOL_FIELD(initdeferred);
 	WRITE_BOOL_FIELD(skip_validation);
+	WRITE_OID_FIELD(old_pktable_oid);
 }
 
 
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 3845267..28af83f 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -50,12 +50,15 @@
 #include "rewrite/rewriteDefine.h"
 #include "rewrite/rewriteRemove.h"
 #include "storage/fd.h"
+#include "storage/lmgr.h"
 #include "tcop/pquery.h"
 #include "tcop/utility.h"
 #include "utils/acl.h"
 #include "utils/guc.h"
 #include "utils/lsyscache.h"
 #include "utils/syscache.h"
+#include "utils/lsyscache.h"
+#include "utils/relcache.h"
 
 
 /*
@@ -192,12 +195,10 @@ CheckDropPermissions(RangeVar *rel, char rightkind)
  * except when allowSystemTableMods is true.
  */
 void
-CheckRelationOwnership(RangeVar *rel, bool noCatalogs)
+CheckRelationOwnership(Oid relOid, bool noCatalogs)
 {
-	Oid			relOid;
 	HeapTuple	tuple;
 
-	relOid = RangeVarGetRelid(rel, false);
 	tuple = SearchSysCache(RELOID,
 						   ObjectIdGetDatum(relOid),
 						   0, 0, 0);
@@ -206,7 +207,7 @@ CheckRelationOwnership(RangeVar *rel, bool noCatalogs)
 
 	if (!pg_class_ownercheck(relOid, GetUserId()))
 		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
-					   rel->relname);
+					   get_rel_name(relOid));
 
 	if (noCatalogs)
 	{
@@ -215,7 +216,7 @@ CheckRelationOwnership(RangeVar *rel, bool noCatalogs)
 			ereport(ERROR,
 					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
 					 errmsg("permission denied: \"%s\" is a system catalog",
-							rel->relname)));
+							get_rel_name(relOid))));
 	}
 
 	ReleaseSysCache(tuple);
@@ -655,8 +656,24 @@ ProcessUtility(Node *parsetree,
 			break;
 
 		case T_AlterTableStmt:
-			AlterTable((AlterTableStmt *) parsetree);
-			break;
+			{
+				/*
+				 * This change is probably not completely necessary but keep the
+				 * backport consistent.
+				 */
+				AlterTableStmt *atstmt = (AlterTableStmt *) parsetree;
+				Oid			relid;
+
+				/*
+				 * Look up the relation OID just once, right here at the
+				 * beginning, so that we don't end up repeating the name
+				 * lookup later and latching onto a different relation
+				 * partway through.
+				 */
+				relid = RangeVarGetRelid(atstmt->relation, false);
+				AlterTable(relid, atstmt);
+				break;
+			}
 
 		case T_AlterDomainStmt:
 			{
@@ -764,10 +781,21 @@ ProcessUtility(Node *parsetree,
 		case T_IndexStmt:		/* CREATE INDEX */
 			{
 				IndexStmt  *stmt = (IndexStmt *) parsetree;
+				Oid			relid;
 
-				CheckRelationOwnership(stmt->relation, true);
+				/*
+				 * Look up the relation OID just once, right here at the
+				 * beginning, so that we don't end up repeating the name
+				 * lookup later and latching onto a different relation
+				 * partway through.  To avoid lock upgrade hazards, it's
+				 * important that we take the strongest lock that will
+				 * eventually be needed here, so the lockmode calculation
+				 * needs to match what DefineIndex() does.
+				 */
+				relid = RangeVarGetRelid(stmt->relation, false);
+				CheckRelationOwnership(relid, true);
 
-				DefineIndex(stmt->relation,		/* relation */
+				DefineIndex(relid,		/* relation */
 							stmt->idxname,		/* index name */
 							InvalidOid, /* no predefined OID */
 							stmt->accessMethod, /* am name */
@@ -943,7 +971,8 @@ ProcessUtility(Node *parsetree,
 			break;
 
 		case T_CreateTrigStmt:
-			CreateTrigger((CreateTrigStmt *) parsetree, false);
+			CreateTrigger((CreateTrigStmt *) parsetree, InvalidOid,
+						  InvalidOid, false);
 			break;
 
 		case T_DropPropertyStmt:
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index 7f41201..a39ef25 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -72,4 +72,6 @@ extern double IndexBuildHeapScan(Relation heapRelation,
 extern void reindex_index(Oid indexId);
 extern bool reindex_relation(Oid relid, bool toast_too);
 
+extern Oid	IndexGetRelation(Oid indexId);
+
 #endif   /* INDEX_H */
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 462d084..4548360 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -18,7 +18,7 @@
 
 
 /* commands/indexcmds.c */
-extern void DefineIndex(RangeVar *heapRelation,
+extern void DefineIndex(Oid relationId,
 			char *indexRelationName,
 			Oid indexRelationId,
 			char *accessMethodName,
diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h
index 7e00b9e..2c89567 100644
--- a/src/include/commands/tablecmds.h
+++ b/src/include/commands/tablecmds.h
@@ -22,7 +22,7 @@ extern Oid	DefineRelation(CreateStmt *stmt, char relkind);
 
 extern void RemoveRelation(const RangeVar *relation, DropBehavior behavior);
 
-extern void AlterTable(AlterTableStmt *stmt);
+extern void AlterTable(Oid relid, AlterTableStmt *stmt);
 
 extern void AlterTableInternal(Oid relid, List *cmds, bool recurse);
 
diff --git a/src/include/commands/trigger.h b/src/include/commands/trigger.h
index 464f8d4..14f5982 100644
--- a/src/include/commands/trigger.h
+++ b/src/include/commands/trigger.h
@@ -105,7 +105,8 @@ typedef struct TriggerData
 #define RI_MAX_ARGUMENTS		(RI_FIRST_ATTNAME_ARGNO + (RI_MAX_NUMKEYS * 2))
 
 
-extern Oid	CreateTrigger(CreateTrigStmt *stmt, bool forConstraint);
+extern Oid	CreateTrigger(CreateTrigStmt *stmt, Oid relOid, Oid refRelOid,
+						  bool forConstraint);
 
 extern void DropTrigger(Oid relid, const char *trigname,
 			DropBehavior behavior);
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 4fff844..04ceaea 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1081,6 +1081,7 @@ typedef struct FkConstraint
 	bool		deferrable;		/* DEFERRABLE */
 	bool		initdeferred;	/* INITIALLY DEFERRED */
 	bool		skip_validation;	/* skip validation of existing rows? */
+	Oid			old_pktable_oid; /* pg_constraint.confrelid of my former self */
 } FkConstraint;
 
 
diff --git a/src/include/tcop/utility.h b/src/include/tcop/utility.h
index f6cfaec..a7453a0 100644
--- a/src/include/tcop/utility.h
+++ b/src/include/tcop/utility.h
@@ -30,6 +30,6 @@ extern const char *CreateQueryTag(Query *parsetree);
 
 extern bool QueryIsReadOnly(Query *parsetree);
 
-extern void CheckRelationOwnership(RangeVar *rel, bool noCatalogs);
+extern void CheckRelationOwnership(Oid relOid, bool noCatalogs);
 
 #endif   /* UTILITY_H */
-- 
1.8.5.3