mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-15 08:20:16 +08:00
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:
parent
766948bedd
commit
f1b4aa2a84
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user