Repair a longstanding bug in CLUSTER and the rewriting variants of ALTER
authorTom Lane <[email protected]>
Tue, 24 Feb 2009 01:39:10 +0000 (01:39 +0000)
committerTom Lane <[email protected]>
Tue, 24 Feb 2009 01:39:10 +0000 (01:39 +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 870625afe185a626282ce548036f84fec99c7f34..41f3670f81aa459e3256d4a78c19ed1254bd3628 100644 (file)
@@ -70,7 +70,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);
@@ -629,13 +630,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 */
@@ -730,7 +733,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.
index 3c4b08512dba8b84be93d51680562e8169dc2ae4..60cc1eca873f70198742972e3bdc8b99b80237ba 100644 (file)
@@ -40,7 +40,7 @@
  * ----------------------------------------------------------------
  */
 Oid
-TypeShellMake(const char *typeName, Oid typeNamespace)
+TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
 {
        Relation        pg_type_desc;
        TupleDesc       tupDesc;
@@ -75,7 +75,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(0);         /* typlen */
        values[i++] = BoolGetDatum(false);      /* typbyval */
        values[i++] = CharGetDatum(0);          /* typtype */
@@ -117,7 +117,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace)
                                                                 typoid,
                                                                 InvalidOid,
                                                                 0,
-                                                                GetUserId(),
+                                                                ownerId,
                                                                 InvalidOid,
                                                                 InvalidOid,
                                                                 InvalidOid,
@@ -150,6 +150,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,
@@ -224,7 +225,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 */
@@ -323,7 +324,7 @@ TypeCreate(const char *typeName,
                                                                 typeObjectId,
                                                                 relationOid,
                                                                 relationKind,
-                                                                GetUserId(),
+                                                                ownerId,
                                                                 inputProcedure,
                                                                 outputProcedure,
                                                                 receiveProcedure,
index fef71ebf33553b841ab521470fc74d1a1666a204..181fb0a10e81f80a7621ff9d5ce7e1961f811e7a 100644 (file)
@@ -123,7 +123,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 ffd0f7ffaa681ffe174c0191f26d18707e00f567..e345226a1bea88395d270772d0cca48e4b0fce3c 100644 (file)
@@ -251,7 +251,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();
        }
@@ -338,6 +338,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 */
@@ -370,6 +371,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 */
@@ -732,6 +734,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 */
index edf7318252226992848da0f68dd334f6e8c913ff..10194d1eae77b20b9ffbd93b86ae8f97974725da 100644 (file)
@@ -550,12 +550,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,