pgsql-v9.2-add-select-into-checks.v1.patch

application/octet-stream

Filename: pgsql-v9.2-add-select-into-checks.v1.patch
Type: application/octet-stream
Part: 0
Message: Add permission checks on SELECT INTO

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
Series: patch v9
File+
src/backend/executor/execMain.c 17 0
src/test/regress/expected/select_into.out 14 0
src/test/regress/sql/select_into.sql 16 0
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index fd7a9ed..4b28bfd 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -2395,6 +2395,8 @@ OpenIntoRel(QueryDesc *queryDesc)
 	Datum		reloptions;
 	Oid			intoRelationId;
 	DR_intorel *myState;
+	RangeTblEntry  *rte;
+	AttrNumber		attnum;
 	static char *validnsps[] = HEAP_RELOPT_NAMESPACES;
 
 	Assert(into);
@@ -2517,6 +2519,21 @@ OpenIntoRel(QueryDesc *queryDesc)
 	intoRelationDesc = heap_open(intoRelationId, AccessExclusiveLock);
 
 	/*
+	 * check INSERT permission on the constructed table.
+	 */
+	rte = makeNode(RangeTblEntry);
+	rte->rtekind = RTE_RELATION;
+	rte->relid = intoRelationId;
+	rte->relkind = RELKIND_RELATION;
+	rte->requiredPerms = ACL_INSERT;
+
+	for (attnum = 0; attnum < queryDesc->tupDesc->natts; attnum++)
+		rte->modifiedCols = bms_add_member(rte->modifiedCols,
+				attnum - FirstLowInvalidHeapAttributeNumber);
+
+	ExecCheckRTPerms(list_make1(rte), true);
+
+	/*
 	 * Now replace the query's DestReceiver with one for SELECT INTO
 	 */
 	queryDesc->dest = CreateDestReceiver(DestIntoRel);
diff --git a/src/test/regress/expected/select_into.out b/src/test/regress/expected/select_into.out
index 503efe0..777268e 100644
--- a/src/test/regress/expected/select_into.out
+++ b/src/test/regress/expected/select_into.out
@@ -11,3 +11,17 @@ SELECT *
    FROM onek2
    WHERE onek2.unique1 < 2;
 DROP TABLE tmp1;
+--
+-- SELECT INTO and INSERT permission, if owner is not allowed to insert.
+--
+CREATE SCHEMA selinto_schema;
+CREATE USER selinto_user;
+ALTER DEFAULT PRIVILEGES IN SCHEMA selinto_schema
+	  REVOKE INSERT ON TABLES FROM selinto_user;
+SET SESSION AUTHORIZATION selinto_user;
+SELECT * INTO TABLE selinto_schema.tmp1
+	  FROM onek WHERE onek.unique1 < 2;	-- Error
+ERROR:  permission denied for relation onek
+RESET SESSION AUTHORIZATION;
+DROP SCHEMA selinto_schema CASCADE;
+DROP USER selinto_user;
diff --git a/src/test/regress/sql/select_into.sql b/src/test/regress/sql/select_into.sql
index 2fa3d1e..4b4ff1c 100644
--- a/src/test/regress/sql/select_into.sql
+++ b/src/test/regress/sql/select_into.sql
@@ -15,3 +15,19 @@ SELECT *
    WHERE onek2.unique1 < 2;
 
 DROP TABLE tmp1;
+
+--
+-- SELECT INTO and INSERT permission, if owner is not allowed to insert.
+--
+CREATE SCHEMA selinto_schema;
+CREATE USER selinto_user;
+ALTER DEFAULT PRIVILEGES IN SCHEMA selinto_schema
+	  REVOKE INSERT ON TABLES FROM selinto_user;
+
+SET SESSION AUTHORIZATION selinto_user;
+SELECT * INTO TABLE selinto_schema.tmp1
+	  FROM onek WHERE onek.unique1 < 2;	-- Error
+RESET SESSION AUTHORIZATION;
+
+DROP SCHEMA selinto_schema CASCADE;
+DROP USER selinto_user;