From: Tom Lane Date: Tue, 24 Feb 2009 01:38:49 +0000 (+0000) Subject: Repair a longstanding bug in CLUSTER and the rewriting variants of ALTER X-Git-Url: http://waps.l3s.uni-hannover.de/gitweb/?a=commitdiff_plain;h=6739a89e847b32236514464401ab883e0a73baa1;p=users%2Fbernd%2Fpostgres.git 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. --- diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 87a4d7354f..02ccac3462 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -72,6 +72,7 @@ static Oid AddNewRelationType(const char *typeName, Oid typeNamespace, Oid new_rel_oid, char new_rel_kind, + Oid ownerid, Oid new_array_type); static void RelationRemoveInheritance(Oid relid); static void StoreRelCheck(Relation rel, char *ccname, char *ccbin); @@ -740,6 +741,7 @@ AddNewRelationType(const char *typeName, Oid typeNamespace, Oid new_rel_oid, char new_rel_kind, + Oid ownerid, Oid new_array_type) { return @@ -748,6 +750,7 @@ AddNewRelationType(const char *typeName, typeNamespace, /* type namespace */ new_rel_oid, /* relation oid */ new_rel_kind, /* relation kind */ + ownerid, /* owner's ID */ -1, /* internal size (varlena) */ TYPTYPE_COMPOSITE, /* type-type (composite) */ DEFAULT_TYPDELIM, /* default array delimiter */ @@ -908,6 +911,7 @@ heap_create_with_catalog(const char *relname, relnamespace, relid, relkind, + ownerid, new_array_oid); /* @@ -924,6 +928,7 @@ heap_create_with_catalog(const char *relname, relnamespace, /* Same namespace as parent */ InvalidOid, /* Not composite, no relationOid */ 0, /* relkind, also N/A here */ + ownerid, /* owner's ID */ -1, /* Internal size (varlena) */ TYPTYPE_BASE, /* Not composite - typelem is */ DEFAULT_TYPDELIM, /* default array delimiter */ diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index be459ac7ce..7a5f9dbe53 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -45,7 +45,7 @@ * ---------------------------------------------------------------- */ Oid -TypeShellMake(const char *typeName, Oid typeNamespace) +TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId) { Relation pg_type_desc; TupleDesc tupDesc; @@ -85,7 +85,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(TYPTYPE_PSEUDO); /* typtype */ @@ -130,7 +130,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace) typoid, InvalidOid, 0, - GetUserId(), + ownerId, F_SHELL_IN, F_SHELL_OUT, InvalidOid, @@ -169,6 +169,7 @@ TypeCreate(Oid newTypeOid, Oid typeNamespace, Oid relationOid, /* only for relation rowtypes */ char relationKind, /* ditto */ + Oid ownerId, int16 internalSize, char typeType, char typDelim, @@ -247,7 +248,7 @@ TypeCreate(Oid newTypeOid, 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 */ @@ -317,7 +318,7 @@ TypeCreate(Oid newTypeOid, /* * 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); /* trouble if caller wanted to force the OID */ @@ -363,7 +364,7 @@ TypeCreate(Oid newTypeOid, typeObjectId, relationOid, relationKind, - GetUserId(), + ownerId, inputProcedure, outputProcedure, receiveProcedure, diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 816422d55e..58992198c4 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -136,7 +136,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 a1394d8286..9227adbdcd 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -160,7 +160,7 @@ DefineType(List *names, List *parameters) */ if (!OidIsValid(typoid)) { - typoid = TypeShellMake(typeName, typeNamespace); + typoid = TypeShellMake(typeName, typeNamespace, GetUserId()); /* Make new shell type visible for modification below */ CommandCounterIncrement(); @@ -417,6 +417,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 */ TYPTYPE_BASE, /* type-type (base type) */ delimiter, /* array element delimiter */ @@ -453,6 +454,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 (always varlena) */ TYPTYPE_BASE, /* type-type (base type) */ DEFAULT_TYPDELIM, /* array element delimiter */ @@ -864,6 +866,7 @@ DefineDomain(CreateDomainStmt *stmt) domainNamespace, /* namespace */ InvalidOid, /* relation oid (n/a here) */ 0, /* relation kind (ditto) */ + GetUserId(), /* owner's ID */ internalLength, /* internal size */ TYPTYPE_DOMAIN, /* type-type (domain type) */ delimiter, /* array element delimiter */ @@ -1044,6 +1047,7 @@ DefineEnum(CreateEnumStmt *stmt) enumNamespace, /* namespace */ InvalidOid, /* relation oid (n/a here) */ 0, /* relation kind (ditto) */ + GetUserId(), /* owner's ID */ sizeof(Oid), /* internal size */ TYPTYPE_ENUM, /* type-type (enum type) */ DEFAULT_TYPDELIM, /* array element delimiter */ @@ -1080,6 +1084,7 @@ DefineEnum(CreateEnumStmt *stmt) enumNamespace, /* namespace */ InvalidOid, /* relation oid (n/a here) */ 0, /* relation kind (ditto) */ + GetUserId(), /* owner's ID */ -1, /* internal size (always varlena) */ TYPTYPE_BASE, /* type-type (base type) */ DEFAULT_TYPDELIM, /* array element delimiter */ diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h index ddaf74d21c..49fae1bb91 100644 --- a/src/include/catalog/pg_type.h +++ b/src/include/catalog/pg_type.h @@ -634,13 +634,16 @@ DATA(insert OID = 3500 ( anyenum PGNSP PGUID 4 t p t \054 0 0 0 anyenum_in any /* * 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(Oid newTypeOid, const char *typeName, Oid typeNamespace, Oid relationOid, char relationKind, + Oid ownerId, int16 internalSize, char typeType, char typDelim,