]> granicus.if.org Git - postgresql/commitdiff
Check for INSERT privileges in SELECT INTO / CREATE TABLE AS.
authorRobert Haas <rhaas@postgresql.org>
Tue, 22 Nov 2011 21:16:26 +0000 (16:16 -0500)
committerRobert Haas <rhaas@postgresql.org>
Tue, 22 Nov 2011 21:16:26 +0000 (16:16 -0500)
In the normal course of events, this matters only if ALTER DEFAULT
PRIVILEGES has been used to revoke default INSERT permission.  Whether
or not the new behavior is more or less likely to be what the user wants
when dealing only with the built-in privilege facilities is arguable,
but it's clearly better when using a loadable module such as sepgsql
that may use the hook in ExecCheckRTPerms to enforce additional
permissions checks.

KaiGai Kohei, reviewed by Albe Laurenz

src/backend/executor/execMain.c
src/test/regress/expected/select_into.out
src/test/regress/sql/select_into.sql

index fd7a9ed0339eed73b1523d84cacb8e8df55eb3f5..708831a5c34d1ee126994ca808cc3cda4c93814d 100644 (file)
@@ -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);
@@ -2516,6 +2518,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 = 1; 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
         */
index 503efe04fc224305c4659456bbd3affc5a0637e9..9ed4229b50600da4ed8cff51dd5303ff18fc2719 100644 (file)
@@ -11,3 +11,42 @@ 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 FOR ROLE selinto_user
+         REVOKE INSERT ON TABLES FROM selinto_user;
+GRANT ALL ON SCHEMA selinto_schema TO public;
+SET SESSION AUTHORIZATION selinto_user;
+SELECT * INTO TABLE selinto_schema.tmp1
+         FROM pg_class WHERE relname like '%a%';       -- Error
+ERROR:  permission denied for relation tmp1
+SELECT oid AS clsoid, relname, relnatts + 10 AS x
+         INTO selinto_schema.tmp2
+         FROM pg_class WHERE relname like '%b%';       -- Error
+ERROR:  permission denied for relation tmp2
+CREATE TABLE selinto_schema.tmp3 (a,b,c)
+          AS SELECT oid,relname,relacl FROM pg_class
+          WHERE relname like '%c%';    -- Error
+ERROR:  permission denied for relation tmp3
+RESET SESSION AUTHORIZATION;
+ALTER DEFAULT PRIVILEGES FOR ROLE selinto_user
+         GRANT INSERT ON TABLES TO selinto_user;
+SET SESSION AUTHORIZATION selinto_user;
+SELECT * INTO TABLE selinto_schema.tmp1
+         FROM pg_class WHERE relname like '%a%';       -- OK
+SELECT oid AS clsoid, relname, relnatts + 10 AS x
+         INTO selinto_schema.tmp2
+         FROM pg_class WHERE relname like '%b%';       -- OK
+CREATE TABLE selinto_schema.tmp3 (a,b,c)
+          AS SELECT oid,relname,relacl FROM pg_class
+          WHERE relname like '%c%';    -- OK
+RESET SESSION AUTHORIZATION;
+DROP SCHEMA selinto_schema CASCADE;
+NOTICE:  drop cascades to 3 other objects
+DETAIL:  drop cascades to table selinto_schema.tmp1
+drop cascades to table selinto_schema.tmp2
+drop cascades to table selinto_schema.tmp3
+DROP USER selinto_user;
index 2fa3d1e08ecd07a250203baa3aa14f3b993721d2..039d35cd34cd7acb99289fe16c16f589cb712075 100644 (file)
@@ -15,3 +15,40 @@ 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 FOR ROLE selinto_user
+         REVOKE INSERT ON TABLES FROM selinto_user;
+GRANT ALL ON SCHEMA selinto_schema TO public;
+
+SET SESSION AUTHORIZATION selinto_user;
+SELECT * INTO TABLE selinto_schema.tmp1
+         FROM pg_class WHERE relname like '%a%';       -- Error
+SELECT oid AS clsoid, relname, relnatts + 10 AS x
+         INTO selinto_schema.tmp2
+         FROM pg_class WHERE relname like '%b%';       -- Error
+CREATE TABLE selinto_schema.tmp3 (a,b,c)
+          AS SELECT oid,relname,relacl FROM pg_class
+          WHERE relname like '%c%';    -- Error
+RESET SESSION AUTHORIZATION;
+
+ALTER DEFAULT PRIVILEGES FOR ROLE selinto_user
+         GRANT INSERT ON TABLES TO selinto_user;
+
+SET SESSION AUTHORIZATION selinto_user;
+SELECT * INTO TABLE selinto_schema.tmp1
+         FROM pg_class WHERE relname like '%a%';       -- OK
+SELECT oid AS clsoid, relname, relnatts + 10 AS x
+         INTO selinto_schema.tmp2
+         FROM pg_class WHERE relname like '%b%';       -- OK
+CREATE TABLE selinto_schema.tmp3 (a,b,c)
+          AS SELECT oid,relname,relacl FROM pg_class
+          WHERE relname like '%c%';    -- OK
+RESET SESSION AUTHORIZATION;
+
+DROP SCHEMA selinto_schema CASCADE;
+DROP USER selinto_user;