diff options
author | Noah Misch <noah@leadboat.com> | 2013-07-12 18:21:22 -0400 |
---|---|---|
committer | Noah Misch <noah@leadboat.com> | 2013-07-12 18:25:41 -0400 |
commit | fb7c0ac42e1a8e3cde74e83e2c758ada8c62a35e (patch) | |
tree | b1d0681b57e7db1524b7afa9ae968ba536eabe8b /src/backend/commands/createas.c | |
parent | 7484f89daa33477e0027a86ae772f44fa99224ed (diff) | |
download | postgresql-fb7c0ac42e1a8e3cde74e83e2c758ada8c62a35e.tar.gz postgresql-fb7c0ac42e1a8e3cde74e83e2c758ada8c62a35e.zip |
Switch user ID to the object owner when populating a materialized view.
This makes superuser-issued REFRESH MATERIALIZED VIEW safe regardless of
the object's provenance. REINDEX is an earlier example of this pattern.
As a downside, functions called from materialized views must tolerate
running in a security-restricted operation. CREATE MATERIALIZED VIEW
need not change user ID. Nonetheless, avoid creation of materialized
views that will invariably fail REFRESH by making it, too, start a
security-restricted operation.
Back-patch to 9.3 so materialized views have this from the beginning.
Reviewed by Kevin Grittner.
Diffstat (limited to 'src/backend/commands/createas.c')
-rw-r--r-- | src/backend/commands/createas.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c index 2bfe5fba877..a3509d8c2a3 100644 --- a/src/backend/commands/createas.c +++ b/src/backend/commands/createas.c @@ -33,6 +33,7 @@ #include "commands/prepare.h" #include "commands/tablecmds.h" #include "commands/view.h" +#include "miscadmin.h" #include "parser/parse_clause.h" #include "rewrite/rewriteHandler.h" #include "storage/smgr.h" @@ -69,7 +70,11 @@ ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString, { Query *query = (Query *) stmt->query; IntoClause *into = stmt->into; + bool is_matview = (into->viewQuery != NULL); DestReceiver *dest; + Oid save_userid = InvalidOid; + int save_sec_context = 0; + int save_nestlevel = 0; List *rewritten; PlannedStmt *plan; QueryDesc *queryDesc; @@ -90,6 +95,7 @@ ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString, { ExecuteStmt *estmt = (ExecuteStmt *) query->utilityStmt; + Assert(!is_matview); /* excluded by syntax */ ExecuteQuery(estmt, into, queryString, params, dest, completionTag); return; @@ -97,6 +103,21 @@ ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString, Assert(query->commandType == CMD_SELECT); /* + * For materialized views, lock down security-restricted operations and + * arrange to make GUC variable changes local to this command. This is + * not necessary for security, but this keeps the behavior similar to + * REFRESH MATERIALIZED VIEW. Otherwise, one could create a materialized + * view not possible to refresh. + */ + if (is_matview) + { + GetUserIdAndSecContext(&save_userid, &save_sec_context); + SetUserIdAndSecContext(save_userid, + save_sec_context | SECURITY_RESTRICTED_OPERATION); + save_nestlevel = NewGUCNestLevel(); + } + + /* * Parse analysis was done already, but we still have to run the rule * rewriter. We do not do AcquireRewriteLocks: we assume the query either * came straight from the parser, or suitable locks were acquired by @@ -160,6 +181,15 @@ ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString, FreeQueryDesc(queryDesc); PopActiveSnapshot(); + + if (is_matview) + { + /* Roll back any GUC changes */ + AtEOXact_GUC(false, save_nestlevel); + + /* Restore userid and security context */ + SetUserIdAndSecContext(save_userid, save_sec_context); + } } /* |