From b8fcef692da8742104181e79db0be1155a781ad2 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 24 Feb 2009 01:39:01 +0000 Subject: [PATCH] Repair a longstanding bug in CLUSTER and the rewriting variants of ALTER TABLE: if the command is executed by someone other than the table owner (eg, a superuser) and the table has a toast table, the toast table's pg_type row ends up with the wrong typowner, ie, the command issuer not the table owner. This is quite harmless for most purposes, since no interesting permissions checks consult the pg_type row. However, it could lead to unexpected failures if one later tries to drop the role that issued the command (in 8.1 or 8.2), or strange warnings from pg_dump afterwards (in 8.3 and up, which will allow the DROP ROLE because we don't create a "redundant" owner dependency for table rowtypes). Problem identified by Cott Lang. Back-patch to 8.1. The problem is actually far older --- the CLUSTER variant can be demonstrated in 7.0 --- but it's mostly cosmetic before 8.1 because we didn't track ownership dependencies before 8.1. Also, fixing it before 8.1 would require changing the call signature of heap_create_with_catalog(), which seems to carry a nontrivial risk of breaking add-on modules. --- src/backend/catalog/heap.c | 12 ++++++++---- src/backend/catalog/pg_type.c | 15 ++++++++------- src/backend/commands/functioncmds.c | 4 ++-- src/backend/commands/typecmds.c | 7 +++++-- src/include/catalog/pg_type.h | 7 +++++-- 5 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index d6822c73c69..72a97b8b7a2 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.314 2006/11/05 22:42:08 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.314.2.1 2009/02/24 01:39:01 tgl Exp $ * * * INTERFACE ROUTINES @@ -69,7 +69,8 @@ static void AddNewRelationTuple(Relation pg_class_desc, static Oid AddNewRelationType(const char *typeName, Oid typeNamespace, Oid new_rel_oid, - char new_rel_kind); + char new_rel_kind, + Oid ownerid); static void RelationRemoveInheritance(Oid relid); static void StoreRelCheck(Relation rel, char *ccname, char *ccbin); static void StoreConstraints(Relation rel, TupleDesc tupdesc); @@ -710,13 +711,15 @@ static Oid AddNewRelationType(const char *typeName, Oid typeNamespace, Oid new_rel_oid, - char new_rel_kind) + char new_rel_kind, + Oid ownerid) { return TypeCreate(typeName, /* type name */ typeNamespace, /* type namespace */ new_rel_oid, /* relation oid */ new_rel_kind, /* relation kind */ + ownerid, /* owner's ID */ -1, /* internal size (varlena) */ 'c', /* type-type (complex) */ ',', /* default array delimiter */ @@ -812,7 +815,8 @@ heap_create_with_catalog(const char *relname, new_type_oid = AddNewRelationType(relname, relnamespace, relid, - relkind); + relkind, + ownerid); /* * now create an entry in pg_class for the relation. diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index 32de0b90dc1..a6a2d99596d 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.108 2006/10/04 00:29:50 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.108.2.1 2009/02/24 01:39:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -42,7 +42,7 @@ * ---------------------------------------------------------------- */ Oid -TypeShellMake(const char *typeName, Oid typeNamespace) +TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId) { Relation pg_type_desc; TupleDesc tupDesc; @@ -82,7 +82,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace) namestrcpy(&name, typeName); values[i++] = NameGetDatum(&name); /* typname */ values[i++] = ObjectIdGetDatum(typeNamespace); /* typnamespace */ - values[i++] = ObjectIdGetDatum(GetUserId()); /* typowner */ + values[i++] = ObjectIdGetDatum(ownerId); /* typowner */ values[i++] = Int16GetDatum(sizeof(int4)); /* typlen */ values[i++] = BoolGetDatum(true); /* typbyval */ values[i++] = CharGetDatum('p'); /* typtype */ @@ -124,7 +124,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace) typoid, InvalidOid, 0, - GetUserId(), + ownerId, F_SHELL_IN, F_SHELL_OUT, InvalidOid, @@ -157,6 +157,7 @@ TypeCreate(const char *typeName, Oid typeNamespace, Oid relationOid, /* only for 'c'atalog types */ char relationKind, /* ditto */ + Oid ownerId, int16 internalSize, char typeType, char typDelim, @@ -231,7 +232,7 @@ TypeCreate(const char *typeName, namestrcpy(&name, typeName); values[i++] = NameGetDatum(&name); /* typname */ values[i++] = ObjectIdGetDatum(typeNamespace); /* typnamespace */ - values[i++] = ObjectIdGetDatum(GetUserId()); /* typowner */ + values[i++] = ObjectIdGetDatum(ownerId); /* typowner */ values[i++] = Int16GetDatum(internalSize); /* typlen */ values[i++] = BoolGetDatum(passedByValue); /* typbyval */ values[i++] = CharGetDatum(typeType); /* typtype */ @@ -298,7 +299,7 @@ TypeCreate(const char *typeName, /* * shell type must have been created by same owner */ - if (((Form_pg_type) GETSTRUCT(tup))->typowner != GetUserId()) + if (((Form_pg_type) GETSTRUCT(tup))->typowner != ownerId) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, typeName); /* @@ -336,7 +337,7 @@ TypeCreate(const char *typeName, typeObjectId, relationOid, relationKind, - GetUserId(), + ownerId, inputProcedure, outputProcedure, receiveProcedure, diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index cd712564123..99832cd326e 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.80 2006/10/06 17:13:58 petere Exp $ + * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.80.2.1 2009/02/24 01:39:01 tgl Exp $ * * DESCRIPTION * These routines take the parse tree and pick out the @@ -122,7 +122,7 @@ compute_return_type(TypeName *returnType, Oid languageOid, if (aclresult != ACLCHECK_OK) aclcheck_error(aclresult, ACL_KIND_NAMESPACE, get_namespace_name(namespaceId)); - rettype = TypeShellMake(typname, namespaceId); + rettype = TypeShellMake(typname, namespaceId, GetUserId()); Assert(OidIsValid(rettype)); } diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 2b2b45208e1..21d8521eb01 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.97.2.2 2007/06/20 18:15:57 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.97.2.3 2009/02/24 01:39:01 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -146,7 +146,7 @@ DefineType(List *names, List *parameters) 0, 0); if (!OidIsValid(typoid)) { - typoid = TypeShellMake(typeName, typeNamespace); + typoid = TypeShellMake(typeName, typeNamespace, GetUserId()); /* Make new shell type visible for modification below */ CommandCounterIncrement(); @@ -374,6 +374,7 @@ DefineType(List *names, List *parameters) typeNamespace, /* namespace */ InvalidOid, /* relation oid (n/a here) */ 0, /* relation kind (ditto) */ + GetUserId(), /* owner's ID */ internalLength, /* internal size */ 'b', /* type-type (base type) */ delimiter, /* array element delimiter */ @@ -406,6 +407,7 @@ DefineType(List *names, List *parameters) typeNamespace, /* namespace */ InvalidOid, /* relation oid (n/a here) */ 0, /* relation kind (ditto) */ + GetUserId(), /* owner's ID */ -1, /* internal size */ 'b', /* type-type (base type) */ DEFAULT_TYPDELIM, /* array element delimiter */ @@ -774,6 +776,7 @@ DefineDomain(CreateDomainStmt *stmt) domainNamespace, /* namespace */ InvalidOid, /* relation oid (n/a here) */ 0, /* relation kind (ditto) */ + GetUserId(), /* owner's ID */ internalLength, /* internal size */ 'd', /* type-type (domain type) */ delimiter, /* array element delimiter */ diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h index 5afe0c851ad..3dca12429c4 100644 --- a/src/include/catalog/pg_type.h +++ b/src/include/catalog/pg_type.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.172.2.1 2006/12/28 01:09:04 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.172.2.2 2009/02/24 01:39:01 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -552,12 +552,15 @@ DATA(insert OID = 2283 ( anyelement PGNSP PGUID 4 t p t \054 0 0 anyelement_in /* * prototypes for functions in pg_type.c */ -extern Oid TypeShellMake(const char *typeName, Oid typeNamespace); +extern Oid TypeShellMake(const char *typeName, + Oid typeNamespace, + Oid ownerId); extern Oid TypeCreate(const char *typeName, Oid typeNamespace, Oid relationOid, char relationKind, + Oid ownerId, int16 internalSize, char typeType, char typDelim, -- 2.39.5