]> granicus.if.org Git - postgresql/commitdiff
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:49 +0000 (01:38 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 24 Feb 2009 01:38:49 +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.h

index 3f8c7eab47bc0e9eb149b71f8aaa383ec302f255..1d1e395d6f7a3a4d6dcfa9dd390ca53411122ccb 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.327 2008/01/01 19:45:48 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.327.2.1 2009/02/24 01:38:49 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -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 */
index 780d5134d9e946a0215362a1b95f7901b4b6d846..82a91ca225cb8713d678a7595f5b11a5903ba4f9 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.115 2008/01/01 19:45:48 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.115.2.1 2009/02/24 01:38:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -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,
index 066a8c9898e79ff01d406d25c9d837c3fad0ea14..0d42e2997cd43c764893bb3d482c383f43621bef 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.88 2008/01/01 19:45:49 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.88.2.1 2009/02/24 01:38:49 tgl Exp $
  *
  * DESCRIPTION
  *       These routines take the parse tree and pick out the
@@ -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));
        }
 
index 9528b58c5682f4c481d86e11a4ab91e80457be88..7e11b22f9f694d29811f03efc8f999053da9e316 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.113 2008/01/01 19:45:49 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.113.2.1 2009/02/24 01:38:49 tgl Exp $
  *
  * DESCRIPTION
  *       The "DefineFoo" routines take the parse tree and pick out the
@@ -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 */
index 7ece0af78c21fd7bc9724b6b739f68b420ab4f36..43acaaf925c571c9f9d4601fb8025dac6c997e6a 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.191 2008/01/01 19:45:57 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.191.2.1 2009/02/24 01:38:49 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -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,