aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFujii Masao <fujii@postgresql.org>2020-02-03 12:40:22 +0900
committerFujii Masao <fujii@postgresql.org>2020-02-03 12:40:22 +0900
commitea7857dddb54c371f70be7215ea3b72cb70265bf (patch)
treeca16deae8120ff753c3f02fd9a47726454f7fdc3
parent600387f5dd286d6ca72a578b09ef3765f45d95e6 (diff)
downloadpostgresql-ea7857dddb54c371f70be7215ea3b72cb70265bf.tar.gz
postgresql-ea7857dddb54c371f70be7215ea3b72cb70265bf.zip
Revert commit a5b652f3a0.
This commit reverts the fix "Make inherited TRUNCATE perform access permission checks on parent table only" only in the back branches. It's not hard to imagine that there are some applications expecting the old behavior and the fix breaks their security. To avoid this compatibility problem, we decided to apply the fix only in HEAD and revert it in all supported back branches. Discussion: https://postgr.es/m/21015.1580400165@sss.pgh.pa.us
-rw-r--r--src/backend/commands/tablecmds.c70
-rw-r--r--src/test/regress/expected/privileges.out21
-rw-r--r--src/test/regress/sql/privileges.sql14
3 files changed, 19 insertions, 86 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 9b0dc3fd10d..38386fb9cf9 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -300,9 +300,7 @@ struct DropRelationCallbackState
#define child_dependency_type(child_is_partition) \
((child_is_partition) ? DEPENDENCY_AUTO : DEPENDENCY_NORMAL)
-static void truncate_check_rel(Oid relid, Form_pg_class reltuple);
-static void truncate_check_perms(Oid relid, Form_pg_class reltuple);
-static void truncate_check_activity(Relation rel);
+static void truncate_check_rel(Relation rel);
static List *MergeAttributes(List *schema, List *supers, char relpersistence,
bool is_partition, List **supOids, List **supconstr,
int *supOidCount);
@@ -1383,11 +1381,7 @@ ExecuteTruncate(TruncateStmt *stmt)
heap_close(rel, lockmode);
continue;
}
-
- truncate_check_rel(myrelid, rel->rd_rel);
- truncate_check_perms(myrelid, rel->rd_rel);
- truncate_check_activity(rel);
-
+ truncate_check_rel(rel);
rels = lappend(rels, rel);
relids = lappend_oid(relids, myrelid);
/* Log this relation only if needed for logical decoding */
@@ -1426,15 +1420,7 @@ ExecuteTruncate(TruncateStmt *stmt)
continue;
}
- /*
- * Inherited TRUNCATE commands perform access
- * permission checks on the parent table only.
- * So we skip checking the children's permissions
- * and don't call truncate_check_perms() here.
- */
- truncate_check_rel(RelationGetRelid(rel), rel->rd_rel);
- truncate_check_activity(rel);
-
+ truncate_check_rel(rel);
rels = lappend(rels, rel);
relids = lappend_oid(relids, childrelid);
/* Log this relation only if needed for logical decoding */
@@ -1517,9 +1503,7 @@ ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged,
ereport(NOTICE,
(errmsg("truncate cascades to table \"%s\"",
RelationGetRelationName(rel))));
- truncate_check_rel(relid, rel->rd_rel);
- truncate_check_perms(relid, rel->rd_rel);
- truncate_check_activity(rel);
+ truncate_check_rel(rel);
rels = lappend(rels, rel);
relids = lappend_oid(relids, relid);
/* Log this relation only if needed for logical decoding */
@@ -1775,51 +1759,35 @@ ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged,
* Check that a given rel is safe to truncate. Subroutine for ExecuteTruncate
*/
static void
-truncate_check_rel(Oid relid, Form_pg_class reltuple)
+truncate_check_rel(Relation rel)
{
- char *relname = NameStr(reltuple->relname);
+ AclResult aclresult;
/*
* Only allow truncate on regular tables and partitioned tables (although,
* the latter are only being included here for the following checks; no
* physical truncation will occur in their case.)
*/
- if (reltuple->relkind != RELKIND_RELATION &&
- reltuple->relkind != RELKIND_PARTITIONED_TABLE)
+ if (rel->rd_rel->relkind != RELKIND_RELATION &&
+ rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("\"%s\" is not a table", relname)));
+ errmsg("\"%s\" is not a table",
+ RelationGetRelationName(rel))));
+
+ /* Permissions checks */
+ aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
+ ACL_TRUNCATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, get_relkind_objtype(rel->rd_rel->relkind),
+ RelationGetRelationName(rel));
- if (!allowSystemTableMods && IsSystemClass(relid, reltuple))
+ if (!allowSystemTableMods && IsSystemRelation(rel))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied: \"%s\" is a system catalog",
- relname)));
-}
-
-/*
- * Check that current user has the permission to truncate given relation.
- */
-static void
-truncate_check_perms(Oid relid, Form_pg_class reltuple)
-{
- char *relname = NameStr(reltuple->relname);
- AclResult aclresult;
-
- /* Permissions checks */
- aclresult = pg_class_aclcheck(relid, GetUserId(), ACL_TRUNCATE);
- if (aclresult != ACLCHECK_OK)
- aclcheck_error(aclresult, get_relkind_objtype(reltuple->relkind),
- relname);
-}
+ RelationGetRelationName(rel))));
-/*
- * Set of extra sanity checks to check if a given relation is safe to
- * truncate.
- */
-static void
-truncate_check_activity(Relation rel)
-{
/*
* Don't allow truncate on temp tables of other backends ... their local
* buffer manager is not going to cope.
diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out
index 6221601c5d4..a8346e17174 100644
--- a/src/test/regress/expected/privileges.out
+++ b/src/test/regress/expected/privileges.out
@@ -695,27 +695,6 @@ SELECT oid FROM atestp2; -- ok
-----
(0 rows)
--- child's permissions do not apply when operating on parent
-SET SESSION AUTHORIZATION regress_priv_user1;
-REVOKE ALL ON atestc FROM regress_priv_user2;
-GRANT ALL ON atestp1 TO regress_priv_user2;
-SET SESSION AUTHORIZATION regress_priv_user2;
-SELECT f2 FROM atestp1; -- ok
- f2
-----
-(0 rows)
-
-SELECT f2 FROM atestc; -- fail
-ERROR: permission denied for table atestc
-DELETE FROM atestp1; -- ok
-DELETE FROM atestc; -- fail
-ERROR: permission denied for table atestc
-UPDATE atestp1 SET f1 = 1; -- ok
-UPDATE atestc SET f1 = 1; -- fail
-ERROR: permission denied for table atestc
-TRUNCATE atestp1; -- ok
-TRUNCATE atestc; -- fail
-ERROR: permission denied for table atestc
-- privileges on functions, languages
-- switch to superuser
\c -
diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql
index c25157b32d8..c1e42d1be2f 100644
--- a/src/test/regress/sql/privileges.sql
+++ b/src/test/regress/sql/privileges.sql
@@ -446,20 +446,6 @@ SELECT fy FROM atestp2; -- ok
SELECT atestp2 FROM atestp2; -- ok
SELECT oid FROM atestp2; -- ok
--- child's permissions do not apply when operating on parent
-SET SESSION AUTHORIZATION regress_priv_user1;
-REVOKE ALL ON atestc FROM regress_priv_user2;
-GRANT ALL ON atestp1 TO regress_priv_user2;
-SET SESSION AUTHORIZATION regress_priv_user2;
-SELECT f2 FROM atestp1; -- ok
-SELECT f2 FROM atestc; -- fail
-DELETE FROM atestp1; -- ok
-DELETE FROM atestc; -- fail
-UPDATE atestp1 SET f1 = 1; -- ok
-UPDATE atestc SET f1 = 1; -- fail
-TRUNCATE atestp1; -- ok
-TRUNCATE atestc; -- fail
-
-- privileges on functions, languages
-- switch to superuser