Add permission check for MERGE/SPLIT partition operations
authorAlexander Korotkov <akorotkov@postgresql.org>
Sun, 12 May 2024 21:00:21 +0000 (00:00 +0300)
committerAlexander Korotkov <akorotkov@postgresql.org>
Sun, 12 May 2024 21:00:21 +0000 (00:00 +0300)
Currently, we check only owner permission for the parent table before
MERGE/SPLIT partition operations.  This leads to a security hole when users
can get access to the data of partitions without permission.  This commit
fixes this problem by requiring owner permission on all the partitions
involved.

Reported-by: Alexander Lakhin
Discussion: https://postgr.es/m/0520c72e-8d97-245e-53f9-173beca2ab2e%40gmail.com
Author: Dmitry Koval, Alexander Korotkov

src/backend/parser/parse_utilcmd.c
src/test/regress/expected/partition_merge.out
src/test/regress/expected/partition_split.out
src/test/regress/sql/partition_merge.sql
src/test/regress/sql/partition_split.sql

index 6520bf9baa550c585fc30102c364adfb76bec494..0598e897d900adab2f0af596b188f75f9aa310b2 100644 (file)
@@ -3456,6 +3456,11 @@ checkPartition(Relation rel, Oid partRelOid)
                        RelationGetRelationName(partRel),
                        RelationGetRelationName(rel))));
 
+   /* Permissions checks */
+   if (!object_ownercheck(RelationRelationId, RelationGetRelid(partRel), GetUserId()))
+       aclcheck_error(ACLCHECK_NOT_OWNER, get_relkind_objtype(partRel->rd_rel->relkind),
+                      RelationGetRelationName(partRel));
+
    relation_close(partRel, AccessShareLock);
 }
 
index 52e5c3ce0dabde26231e28e6639df90d42179ab3..076264c88eb1d2e6894cfde1f701b75dac994f47 100644 (file)
@@ -881,6 +881,35 @@ ORDER BY c.relname;
 
 DROP TABLE t;
 DROP ACCESS METHOD partitions_merge_heap;
+-- Test permission checks.  The user needs to own the parent table and all
+-- the merging partitions to do the merge.
+CREATE ROLE regress_partition_merge_alice;
+CREATE ROLE regress_partition_merge_bob;
+SET SESSION AUTHORIZATION regress_partition_merge_alice;
+CREATE TABLE t (i int) PARTITION BY RANGE (i);
+CREATE TABLE tp_0_1 PARTITION OF t FOR VALUES FROM (0) TO (1);
+CREATE TABLE tp_1_2 PARTITION OF t FOR VALUES FROM (1) TO (2);
+SET SESSION AUTHORIZATION regress_partition_merge_bob;
+ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2;
+ERROR:  must be owner of table t
+RESET SESSION AUTHORIZATION;
+ALTER TABLE t OWNER TO regress_partition_merge_bob;
+SET SESSION AUTHORIZATION regress_partition_merge_bob;
+ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2;
+ERROR:  must be owner of table tp_0_1
+RESET SESSION AUTHORIZATION;
+ALTER TABLE tp_0_1 OWNER TO regress_partition_merge_bob;
+SET SESSION AUTHORIZATION regress_partition_merge_bob;
+ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2;
+ERROR:  must be owner of table tp_1_2
+RESET SESSION AUTHORIZATION;
+ALTER TABLE tp_1_2 OWNER TO regress_partition_merge_bob;
+SET SESSION AUTHORIZATION regress_partition_merge_bob;
+ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2;
+RESET SESSION AUTHORIZATION;
+DROP TABLE t;
+DROP ROLE regress_partition_merge_alice;
+DROP ROLE regress_partition_merge_bob;
 RESET search_path;
 --
 DROP SCHEMA partitions_merge_schema;
index 641e1acc3d75b930b659f67c6b11197bbcff911d..74e19d250e942e05cbc34c2b9267eda96f5473d6 100644 (file)
@@ -1514,6 +1514,35 @@ ORDER BY c.relname;
 
 DROP TABLE t;
 DROP ACCESS METHOD partition_split_heap;
+-- Test permission checks.  The user needs to own the parent table and the
+-- the partition to split to do the split.
+CREATE ROLE regress_partition_merge_alice;
+CREATE ROLE regress_partition_merge_bob;
+SET SESSION AUTHORIZATION regress_partition_merge_alice;
+CREATE TABLE t (i int) PARTITION BY RANGE (i);
+CREATE TABLE tp_0_2 PARTITION OF t FOR VALUES FROM (0) TO (2);
+SET SESSION AUTHORIZATION regress_partition_merge_bob;
+ALTER TABLE t SPLIT PARTITION tp_0_2 INTO
+  (PARTITION tp_0_1 FOR VALUES FROM (0) TO (1),
+   PARTITION tp_1_2 FOR VALUES FROM (1) TO (2));
+ERROR:  must be owner of table t
+RESET SESSION AUTHORIZATION;
+ALTER TABLE t OWNER TO regress_partition_merge_bob;
+SET SESSION AUTHORIZATION regress_partition_merge_bob;
+ALTER TABLE t SPLIT PARTITION tp_0_2 INTO
+  (PARTITION tp_0_1 FOR VALUES FROM (0) TO (1),
+   PARTITION tp_1_2 FOR VALUES FROM (1) TO (2));
+ERROR:  must be owner of table tp_0_2
+RESET SESSION AUTHORIZATION;
+ALTER TABLE tp_0_2 OWNER TO regress_partition_merge_bob;
+SET SESSION AUTHORIZATION regress_partition_merge_bob;
+ALTER TABLE t SPLIT PARTITION tp_0_2 INTO
+  (PARTITION tp_0_1 FOR VALUES FROM (0) TO (1),
+   PARTITION tp_1_2 FOR VALUES FROM (1) TO (2));
+RESET SESSION AUTHORIZATION;
+DROP TABLE t;
+DROP ROLE regress_partition_merge_alice;
+DROP ROLE regress_partition_merge_bob;
 --
 DROP SCHEMA partition_split_schema;
 DROP SCHEMA partition_split_schema2;
index 84a3462205ae1169dcdf86f24302428cd8a61131..9bfeb0d7ef303d202da4125ba7bdcac27376f503 100644 (file)
@@ -549,6 +549,39 @@ ORDER BY c.relname;
 DROP TABLE t;
 DROP ACCESS METHOD partitions_merge_heap;
 
+-- Test permission checks.  The user needs to own the parent table and all
+-- the merging partitions to do the merge.
+CREATE ROLE regress_partition_merge_alice;
+CREATE ROLE regress_partition_merge_bob;
+
+SET SESSION AUTHORIZATION regress_partition_merge_alice;
+CREATE TABLE t (i int) PARTITION BY RANGE (i);
+CREATE TABLE tp_0_1 PARTITION OF t FOR VALUES FROM (0) TO (1);
+CREATE TABLE tp_1_2 PARTITION OF t FOR VALUES FROM (1) TO (2);
+
+SET SESSION AUTHORIZATION regress_partition_merge_bob;
+ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2;
+RESET SESSION AUTHORIZATION;
+
+ALTER TABLE t OWNER TO regress_partition_merge_bob;
+SET SESSION AUTHORIZATION regress_partition_merge_bob;
+ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2;
+RESET SESSION AUTHORIZATION;
+
+ALTER TABLE tp_0_1 OWNER TO regress_partition_merge_bob;
+SET SESSION AUTHORIZATION regress_partition_merge_bob;
+ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2;
+RESET SESSION AUTHORIZATION;
+
+ALTER TABLE tp_1_2 OWNER TO regress_partition_merge_bob;
+SET SESSION AUTHORIZATION regress_partition_merge_bob;
+ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2;
+RESET SESSION AUTHORIZATION;
+
+DROP TABLE t;
+DROP ROLE regress_partition_merge_alice;
+DROP ROLE regress_partition_merge_bob;
+
 RESET search_path;
 
 --
index d2c687c41ba98054b01f8fe26393c778c0907c0d..bb52514b7ed79f2fc048638f12d94f1e845b02e7 100644 (file)
@@ -894,6 +894,39 @@ ORDER BY c.relname;
 DROP TABLE t;
 DROP ACCESS METHOD partition_split_heap;
 
+-- Test permission checks.  The user needs to own the parent table and the
+-- the partition to split to do the split.
+CREATE ROLE regress_partition_merge_alice;
+CREATE ROLE regress_partition_merge_bob;
+
+SET SESSION AUTHORIZATION regress_partition_merge_alice;
+CREATE TABLE t (i int) PARTITION BY RANGE (i);
+CREATE TABLE tp_0_2 PARTITION OF t FOR VALUES FROM (0) TO (2);
+
+SET SESSION AUTHORIZATION regress_partition_merge_bob;
+ALTER TABLE t SPLIT PARTITION tp_0_2 INTO
+  (PARTITION tp_0_1 FOR VALUES FROM (0) TO (1),
+   PARTITION tp_1_2 FOR VALUES FROM (1) TO (2));
+RESET SESSION AUTHORIZATION;
+
+ALTER TABLE t OWNER TO regress_partition_merge_bob;
+SET SESSION AUTHORIZATION regress_partition_merge_bob;
+ALTER TABLE t SPLIT PARTITION tp_0_2 INTO
+  (PARTITION tp_0_1 FOR VALUES FROM (0) TO (1),
+   PARTITION tp_1_2 FOR VALUES FROM (1) TO (2));
+RESET SESSION AUTHORIZATION;
+
+ALTER TABLE tp_0_2 OWNER TO regress_partition_merge_bob;
+SET SESSION AUTHORIZATION regress_partition_merge_bob;
+ALTER TABLE t SPLIT PARTITION tp_0_2 INTO
+  (PARTITION tp_0_1 FOR VALUES FROM (0) TO (1),
+   PARTITION tp_1_2 FOR VALUES FROM (1) TO (2));
+RESET SESSION AUTHORIZATION;
+
+DROP TABLE t;
+DROP ROLE regress_partition_merge_alice;
+DROP ROLE regress_partition_merge_bob;
+
 
 --
 DROP SCHEMA partition_split_schema;