From e4f06dc12efaf14878288a175efcf50ce2318813 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 30 Apr 2002 01:26:26 +0000 Subject: [PATCH] Clean up loose ends remaining from schema privileges discussion. I concluded that RENAME should require CREATE privilege on the namespace as well as ownership of the table. --- doc/src/sgml/ref/grant.sgml | 4 +- src/backend/catalog/namespace.c | 9 +++- src/backend/tcop/utility.c | 68 ++++++++++++++++++++--------- src/backend/utils/cache/lsyscache.c | 28 +++++++++++- src/include/utils/lsyscache.h | 3 +- 5 files changed, 86 insertions(+), 26 deletions(-) diff --git a/doc/src/sgml/ref/grant.sgml b/doc/src/sgml/ref/grant.sgml index 1697f91929..226db71d68 100644 --- a/doc/src/sgml/ref/grant.sgml +++ b/doc/src/sgml/ref/grant.sgml @@ -1,5 +1,5 @@ @@ -161,6 +161,8 @@ GRANT { { CREATE | USAGE } [,...] | ALL [ PRIVILEGES ] } For schemas, allows new objects to be created within the schema. + To rename an existing object, you must own the object and + have this privilege for the containing schema. diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index 51ef7c3f8d..80ce60f8ab 100644 --- a/src/backend/catalog/namespace.c +++ b/src/backend/catalog/namespace.c @@ -13,7 +13,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.15 2002/04/29 22:15:07 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.16 2002/04/30 01:26:25 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1161,7 +1161,12 @@ GetTempTableNamespace(void) { /* * First use of this temp namespace in this database; create it. - * The temp namespaces are always owned by the superuser. + * The temp namespaces are always owned by the superuser. We + * leave their permissions at default --- i.e., no access except to + * superuser --- to ensure that unprivileged users can't peek + * at other backends' temp tables. This works because the places + * that access the temp namespace for my own backend skip permissions + * checks on it. */ namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_USESYSID); /* Advance command counter to make namespace visible */ diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 771f3d30cc..9a9c062559 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.152 2002/04/27 03:45:03 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.153 2002/04/30 01:26:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -374,25 +374,49 @@ ProcessUtility(Node *parsetree, case T_RenameStmt: { RenameStmt *stmt = (RenameStmt *) parsetree; + Oid relid; CheckOwnership(stmt->relation, true); + relid = RangeVarGetRelid(stmt->relation, false); + switch (stmt->renameType) { case RENAME_TABLE: - renamerel(RangeVarGetRelid(stmt->relation, false), - stmt->newname); + { + /* + * RENAME TABLE requires that we (still) hold CREATE + * rights on the containing namespace, as well as + * ownership of the table. But skip check for + * temp tables. + */ + Oid namespaceId = get_rel_namespace(relid); + + if (!isTempNamespace(namespaceId)) + { + AclResult aclresult; + + aclresult = pg_namespace_aclcheck(namespaceId, + GetUserId(), + ACL_CREATE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, + get_namespace_name(namespaceId)); + } + + renamerel(relid, stmt->newname); break; + } case RENAME_COLUMN: - renameatt(RangeVarGetRelid(stmt->relation, false), - stmt->oldname, /* old att name */ - stmt->newname, /* new att name */ - interpretInhOption(stmt->relation->inhOpt)); /* recursive? */ + renameatt(relid, + stmt->oldname, /* old att name */ + stmt->newname, /* new att name */ + interpretInhOption(stmt->relation->inhOpt)); /* recursive? */ break; case RENAME_TRIGGER: - renametrig(RangeVarGetRelid(stmt->relation, false), - stmt->oldname, /* old att name */ - stmt->newname); /* new att name */ + renametrig(relid, + stmt->oldname, /* old att name */ + stmt->newname); /* new att name */ break; case RENAME_RULE: elog(ERROR, "ProcessUtility: Invalid target for RENAME: %d", @@ -410,6 +434,9 @@ ProcessUtility(Node *parsetree, case T_AlterTableStmt: { AlterTableStmt *stmt = (AlterTableStmt *) parsetree; + Oid relid; + + relid = RangeVarGetRelid(stmt->relation, false); /* * Some or all of these functions are recursive to cover @@ -422,7 +449,7 @@ ProcessUtility(Node *parsetree, * Recursively add column to table and, * if requested, to descendants */ - AlterTableAddColumn(RangeVarGetRelid(stmt->relation, false), + AlterTableAddColumn(relid, interpretInhOption(stmt->relation->inhOpt), (ColumnDef *) stmt->def); break; @@ -431,18 +458,18 @@ ProcessUtility(Node *parsetree, * Recursively alter column default for table and, * if requested, for descendants */ - AlterTableAlterColumnDefault(RangeVarGetRelid(stmt->relation, false), + AlterTableAlterColumnDefault(relid, interpretInhOption(stmt->relation->inhOpt), stmt->name, stmt->def); break; case 'N': /* ALTER COLUMN DROP NOT NULL */ - AlterTableAlterColumnDropNotNull(RangeVarGetRelid(stmt->relation, false), + AlterTableAlterColumnDropNotNull(relid, interpretInhOption(stmt->relation->inhOpt), stmt->name); break; case 'O': /* ALTER COLUMN SET NOT NULL */ - AlterTableAlterColumnSetNotNull(RangeVarGetRelid(stmt->relation, false), + AlterTableAlterColumnSetNotNull(relid, interpretInhOption(stmt->relation->inhOpt), stmt->name); break; @@ -452,7 +479,7 @@ ProcessUtility(Node *parsetree, * Recursively alter column statistics for table and, * if requested, for descendants */ - AlterTableAlterColumnFlags(RangeVarGetRelid(stmt->relation, false), + AlterTableAlterColumnFlags(relid, interpretInhOption(stmt->relation->inhOpt), stmt->name, stmt->def, @@ -464,7 +491,7 @@ ProcessUtility(Node *parsetree, * Recursively drop column from table and, * if requested, from descendants */ - AlterTableDropColumn(RangeVarGetRelid(stmt->relation, false), + AlterTableDropColumn(relid, interpretInhOption(stmt->relation->inhOpt), stmt->name, stmt->behavior); @@ -474,7 +501,7 @@ ProcessUtility(Node *parsetree, * Recursively add constraint to table and, * if requested, to descendants */ - AlterTableAddConstraint(RangeVarGetRelid(stmt->relation, false), + AlterTableAddConstraint(relid, interpretInhOption(stmt->relation->inhOpt), (List *) stmt->def); break; @@ -483,21 +510,20 @@ ProcessUtility(Node *parsetree, * Recursively drop constraint from table and, * if requested, from descendants */ - AlterTableDropConstraint(RangeVarGetRelid(stmt->relation, false), + AlterTableDropConstraint(relid, interpretInhOption(stmt->relation->inhOpt), stmt->name, stmt->behavior); break; case 'E': /* CREATE TOAST TABLE */ - AlterTableCreateToastTable(RangeVarGetRelid(stmt->relation, false), - false); + AlterTableCreateToastTable(relid, false); break; case 'U': /* ALTER OWNER */ /* check that we are the superuser */ if (!superuser()) elog(ERROR, "ALTER TABLE: permission denied"); /* get_usesysid raises an error if no such user */ - AlterTableOwner(RangeVarGetRelid(stmt->relation, false), + AlterTableOwner(relid, get_usesysid(stmt->name)); break; default: /* oops */ diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index f6b98c5bee..ca3bd80e8a 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.71 2002/04/27 03:45:03 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.72 2002/04/30 01:26:26 tgl Exp $ * * NOTES * Eventually, the index information should go through here, too. @@ -708,6 +708,32 @@ get_rel_name(Oid relid) return NULL; } +/* + * get_rel_namespace + * + * Returns the pg_namespace OID associated with a given relation. + */ +Oid +get_rel_namespace(Oid relid) +{ + HeapTuple tp; + + tp = SearchSysCache(RELOID, + ObjectIdGetDatum(relid), + 0, 0, 0); + if (HeapTupleIsValid(tp)) + { + Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp); + Oid result; + + result = reltup->relnamespace; + ReleaseSysCache(tp); + return result; + } + else + return InvalidOid; +} + /* * get_rel_type_id * diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h index f57219df11..9f81225673 100644 --- a/src/include/utils/lsyscache.h +++ b/src/include/utils/lsyscache.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: lsyscache.h,v 1.50 2002/04/27 03:45:03 tgl Exp $ + * $Id: lsyscache.h,v 1.51 2002/04/30 01:26:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -42,6 +42,7 @@ extern Oid get_func_rettype(Oid funcid); extern char func_volatile(Oid funcid); extern Oid get_relname_relid(const char *relname, Oid relnamespace); extern char *get_rel_name(Oid relid); +extern Oid get_rel_namespace(Oid relid); extern Oid get_rel_type_id(Oid relid); extern bool get_typisdefined(Oid typid); extern int16 get_typlen(Oid typid);