Check for INSERT privileges in SELECT INTO / CREATE TABLE AS.

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
This commit is contained in:
Robert Haas 2011-11-22 16:16:26 -05:00
parent 766948bedd
commit f1b4aa2a84
3 changed files with 93 additions and 0 deletions

View 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
*/

View 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;

View 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;