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 b01edbe0170eb581852d026511c406b68ece35ca..70083b52a64de3ffd4d6229063bcbfcd1eba289b 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.350 2009/01/22 20:16:01 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.351 2009/02/24 01:38:09 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -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 6d28b1df2fd92a45e69387ea7df854801bf0f8b2..c7daed4e323acb46cef1eb65becc0efa3c6fc873 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.124 2009/01/22 20:16:01 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.125 2009/02/24 01:38:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -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 a813fd9a028cb30f506ef018c6552357fce7fd6a..f913f3b766155b717ce76a72e2574d0cc9a4a20a 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.107 2009/01/06 02:01:27 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.108 2009/02/24 01:38:09 tgl Exp $
  *
  * DESCRIPTION
  *   These routines take the parse tree and pick out the
@@ -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 ca87b15068f96821fc81cf8fa29815a3a95ddc18..03e08f1b4c0bfeaa22c040db83676145ed081755 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.131 2009/02/02 19:31:39 alvherre Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.132 2009/02/24 01:38:09 tgl Exp $
  *
  * DESCRIPTION
  *   The "DefineFoo" routines take the parse tree and pick out the
@@ -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 dd0695cf10ee7ac4594f16c0712c9d1fcd6851f3..11409cf349cefa9bfa2826b3b0f903eb51ba9ca0 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_type_fn.h,v 1.3 2009/01/01 17:23:58 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_type_fn.h,v 1.4 2009/02/24 01:38:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #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,