mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-30 12:01:24 +02:00
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.
This commit is contained in:
parent
448fee2e23
commit
f3ab5d4696
@ -105,7 +105,9 @@ CREATE MATERIALIZED VIEW <replaceable>table_name</replaceable>
|
|||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
A <xref linkend="sql-select">, <link linkend="sql-table">TABLE</link>,
|
A <xref linkend="sql-select">, <link linkend="sql-table">TABLE</link>,
|
||||||
or <xref linkend="sql-values"> command.
|
or <xref linkend="sql-values"> command. This query will run within a
|
||||||
|
security-restricted operation; in particular, calls to functions that
|
||||||
|
themselves create temporary tables will fail.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "commands/prepare.h"
|
#include "commands/prepare.h"
|
||||||
#include "commands/tablecmds.h"
|
#include "commands/tablecmds.h"
|
||||||
#include "commands/view.h"
|
#include "commands/view.h"
|
||||||
|
#include "miscadmin.h"
|
||||||
#include "parser/parse_clause.h"
|
#include "parser/parse_clause.h"
|
||||||
#include "rewrite/rewriteHandler.h"
|
#include "rewrite/rewriteHandler.h"
|
||||||
#include "storage/smgr.h"
|
#include "storage/smgr.h"
|
||||||
@ -69,7 +70,11 @@ ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString,
|
|||||||
{
|
{
|
||||||
Query *query = (Query *) stmt->query;
|
Query *query = (Query *) stmt->query;
|
||||||
IntoClause *into = stmt->into;
|
IntoClause *into = stmt->into;
|
||||||
|
bool is_matview = (into->viewQuery != NULL);
|
||||||
DestReceiver *dest;
|
DestReceiver *dest;
|
||||||
|
Oid save_userid = InvalidOid;
|
||||||
|
int save_sec_context = 0;
|
||||||
|
int save_nestlevel = 0;
|
||||||
List *rewritten;
|
List *rewritten;
|
||||||
PlannedStmt *plan;
|
PlannedStmt *plan;
|
||||||
QueryDesc *queryDesc;
|
QueryDesc *queryDesc;
|
||||||
@ -90,12 +95,28 @@ ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString,
|
|||||||
{
|
{
|
||||||
ExecuteStmt *estmt = (ExecuteStmt *) query->utilityStmt;
|
ExecuteStmt *estmt = (ExecuteStmt *) query->utilityStmt;
|
||||||
|
|
||||||
|
Assert(!is_matview); /* excluded by syntax */
|
||||||
ExecuteQuery(estmt, into, queryString, params, dest, completionTag);
|
ExecuteQuery(estmt, into, queryString, params, dest, completionTag);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Assert(query->commandType == CMD_SELECT);
|
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
|
* Parse analysis was done already, but we still have to run the rule
|
||||||
* rewriter. We do not do AcquireRewriteLocks: we assume the query either
|
* rewriter. We do not do AcquireRewriteLocks: we assume the query either
|
||||||
@ -160,6 +181,15 @@ ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString,
|
|||||||
FreeQueryDesc(queryDesc);
|
FreeQueryDesc(queryDesc);
|
||||||
|
|
||||||
PopActiveSnapshot();
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -122,6 +122,9 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
|
|||||||
RewriteRule *rule;
|
RewriteRule *rule;
|
||||||
List *actions;
|
List *actions;
|
||||||
Query *dataQuery;
|
Query *dataQuery;
|
||||||
|
Oid save_userid;
|
||||||
|
int save_sec_context;
|
||||||
|
int save_nestlevel;
|
||||||
Oid tableSpace;
|
Oid tableSpace;
|
||||||
Oid OIDNewHeap;
|
Oid OIDNewHeap;
|
||||||
DestReceiver *dest;
|
DestReceiver *dest;
|
||||||
@ -191,6 +194,16 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
|
|||||||
*/
|
*/
|
||||||
CheckTableNotInUse(matviewRel, "REFRESH MATERIALIZED VIEW");
|
CheckTableNotInUse(matviewRel, "REFRESH MATERIALIZED VIEW");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Switch to the owner's userid, so that any functions are run as that
|
||||||
|
* user. Also lock down security-restricted operations and arrange to
|
||||||
|
* make GUC variable changes local to this command.
|
||||||
|
*/
|
||||||
|
GetUserIdAndSecContext(&save_userid, &save_sec_context);
|
||||||
|
SetUserIdAndSecContext(matviewRel->rd_rel->relowner,
|
||||||
|
save_sec_context | SECURITY_RESTRICTED_OPERATION);
|
||||||
|
save_nestlevel = NewGUCNestLevel();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tentatively mark the matview as populated or not (this will roll back
|
* Tentatively mark the matview as populated or not (this will roll back
|
||||||
* if we fail later).
|
* if we fail later).
|
||||||
@ -217,6 +230,12 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
|
|||||||
RecentXmin, ReadNextMultiXactId());
|
RecentXmin, ReadNextMultiXactId());
|
||||||
|
|
||||||
RelationCacheInvalidateEntry(matviewOid);
|
RelationCacheInvalidateEntry(matviewOid);
|
||||||
|
|
||||||
|
/* Roll back any GUC changes */
|
||||||
|
AtEOXact_GUC(false, save_nestlevel);
|
||||||
|
|
||||||
|
/* Restore userid and security context */
|
||||||
|
SetUserIdAndSecContext(save_userid, save_sec_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user