aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/createas.c
diff options
context:
space:
mode:
authorNoah Misch <noah@leadboat.com>2013-07-12 18:21:22 -0400
committerNoah Misch <noah@leadboat.com>2013-07-12 18:25:41 -0400
commitfb7c0ac42e1a8e3cde74e83e2c758ada8c62a35e (patch)
treeb1d0681b57e7db1524b7afa9ae968ba536eabe8b /src/backend/commands/createas.c
parent7484f89daa33477e0027a86ae772f44fa99224ed (diff)
downloadpostgresql-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.c30
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);
+ }
}
/*