]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Revert commit 606f350de9.
authorFujii Masao <fujii@postgresql.org>
Mon, 3 Feb 2020 03:43:51 +0000 (12:43 +0900)
committerFujii Masao <fujii@postgresql.org>
Mon, 3 Feb 2020 03:43:51 +0000 (12:43 +0900)
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

src/backend/commands/tablecmds.c
src/test/regress/expected/privileges.out
src/test/regress/sql/privileges.sql

index 5f46aaa9dad955ba0428c6a6b057153547d35ca0..7fcc3db14cb5f76e9a2e7dcec899cfe88d323ed8 100644 (file)
@@ -269,9 +269,7 @@ struct DropRelationCallbackState
 #define                ATT_COMPOSITE_TYPE              0x0010
 #define                ATT_FOREIGN_TABLE               0x0020
 
-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,
                                List **supOids, List **supconstr, int *supOidCount);
 static bool MergeCheckConstraint(List *constraints, char *name, Node *expr);
@@ -1048,11 +1046,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);
 
@@ -1088,15 +1082,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);
                        }
@@ -1130,9 +1116,7 @@ ExecuteTruncate(TruncateStmt *stmt)
                                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);
                        }
@@ -1340,45 +1324,30 @@ ExecuteTruncate(TruncateStmt *stmt)
  * 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 */
-       if (reltuple->relkind != RELKIND_RELATION)
+       if (rel->rd_rel->relkind != RELKIND_RELATION)
                ereport(ERROR,
                                (errcode(ERRCODE_WRONG_OBJECT_TYPE),
-                                errmsg("\"%s\" is not a table", relname)));
+                                errmsg("\"%s\" is not a table",
+                                               RelationGetRelationName(rel))));
 
-       if (!allowSystemTableMods && IsSystemClass(relid, reltuple))
+       /* Permissions checks */
+       aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
+                                                                 ACL_TRUNCATE);
+       if (aclresult != ACLCHECK_OK)
+               aclcheck_error(aclresult, ACL_KIND_CLASS,
+                                          RelationGetRelationName(rel));
+
+       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, ACL_KIND_CLASS, 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.
index 41645ad6cb37015035c5c5cf720a6b5a5c66a306..2d92698c4dcffb9a1dceb5dfe7b650521705e90e 100644 (file)
@@ -695,27 +695,6 @@ SELECT oid FROM atestp2; -- ok
 -----
 (0 rows)
 
--- child's permissions do not apply when operating on parent
-SET SESSION AUTHORIZATION regressuser1;
-REVOKE ALL ON atestc FROM regressuser2;
-GRANT ALL ON atestp1 TO regressuser2;
-SET SESSION AUTHORIZATION regressuser2;
-SELECT f2 FROM atestp1; -- ok
- f2 
-----
-(0 rows)
-
-SELECT f2 FROM atestc; -- fail
-ERROR:  permission denied for relation atestc
-DELETE FROM atestp1; -- ok
-DELETE FROM atestc; -- fail
-ERROR:  permission denied for relation atestc
-UPDATE atestp1 SET f1 = 1; -- ok
-UPDATE atestc SET f1 = 1; -- fail
-ERROR:  permission denied for relation atestc
-TRUNCATE atestp1; -- ok
-TRUNCATE atestc; -- fail
-ERROR:  permission denied for relation atestc
 -- privileges on functions, languages
 -- switch to superuser
 \c -
index 33955d559c896a92c3eee62241f7a1ca43eb9527..3ad2e39930a608ed53b04973366a8c25027d2f90 100644 (file)
@@ -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 regressuser1;
-REVOKE ALL ON atestc FROM regressuser2;
-GRANT ALL ON atestp1 TO regressuser2;
-SET SESSION AUTHORIZATION regressuser2;
-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