Repair a longstanding bug in CLUSTER and the rewriting variants of ALTER
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 24 Feb 2009 01:38:10 +0000 (01:38 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 24 Feb 2009 01:38:10 +0000 (01:38 +0000)
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
src/backend/catalog/pg_type.c
src/backend/commands/functioncmds.c
src/backend/commands/typecmds.c
src/include/catalog/pg_type_fn.h

index 98290beb5a9f1f4a71d6867a87f2489bfd909d7e..3661b8f1699bd484771fd8f12f7fd379d9de6349 100644 (file)
@@ -79,6 +79,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, Node *expr,
@@ -784,6 +785,7 @@ AddNewRelationType(const char *typeName,
                                   Oid typeNamespace,
                                   Oid new_rel_oid,
                                   char new_rel_kind,
+                                  Oid ownerid,
                                   Oid new_array_type)
 {
        return
@@ -792,6 +794,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) */
                                   TYPCATEGORY_COMPOSITE, /* type-category (ditto) */
@@ -955,6 +958,7 @@ heap_create_with_catalog(const char *relname,
                                                                          relnamespace,
                                                                          relid,
                                                                          relkind,
+                                                                         ownerid,
                                                                          new_array_oid);
 
        /*
@@ -971,6 +975,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 */
                                   TYPCATEGORY_ARRAY, /* type-category (array) */
index 577634d969088bb42ba0d343a112454dc4330b2d..a17c5b59be71d9d0acccd94feed3156832dae85e 100644 (file)
@@ -47,7 +47,7 @@
  * ----------------------------------------------------------------
  */
 Oid
-TypeShellMake(const char *typeName, Oid typeNamespace)
+TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
 {
        Relation        pg_type_desc;
        TupleDesc       tupDesc;
@@ -87,7 +87,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 */
@@ -134,7 +134,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace)
                                                                 typoid,
                                                                 InvalidOid,
                                                                 0,
-                                                                GetUserId(),
+                                                                ownerId,
                                                                 F_SHELL_IN,
                                                                 F_SHELL_OUT,
                                                                 InvalidOid,
@@ -173,6 +173,7 @@ TypeCreate(Oid newTypeOid,
                   Oid typeNamespace,
                   Oid relationOid,             /* only for relation rowtypes */
                   char relationKind,   /* ditto */
+                  Oid ownerId,
                   int16 internalSize,
                   char typeType,
                   char typeCategory,
@@ -310,7 +311,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 */
@@ -380,7 +381,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 */
@@ -426,7 +427,7 @@ TypeCreate(Oid newTypeOid,
                                                                 typeObjectId,
                                                                 relationOid,
                                                                 relationKind,
-                                                                GetUserId(),
+                                                                ownerId,
                                                                 inputProcedure,
                                                                 outputProcedure,
                                                                 receiveProcedure,
index c0542ef3d6477357153ecdcbb14146c688a5d304..d8a9dae90bb85d9a61f0e723536460e1d5e79448 100644 (file)
@@ -144,7 +144,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));
        }
 
index bd82aa03f8549b68f53682873886c27466c48a9e..98e01e455b910d23253acf47a11af832b61475bd 100644 (file)
@@ -199,7 +199,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();
 
@@ -536,6 +536,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) */
                                   category,    /* type-category */
@@ -574,6 +575,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) */
                           TYPCATEGORY_ARRAY, /* type-category (array) */
@@ -1018,6 +1020,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) */
                                   category,    /* type-category */
@@ -1131,6 +1134,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) */
                                   TYPCATEGORY_ENUM,    /* type-category (enum type) */
@@ -1169,6 +1173,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) */
                           TYPCATEGORY_ARRAY, /* type-category (array) */
index 5fe754883a903cc04dd42b81107969034284d224..2c8cfb9640860d320ba8aa049d13195cd34fe1a7 100644 (file)
 #include "nodes/nodes.h"
 
 
-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 typeCategory,