summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNoah Misch2022-05-09 15:35:08 +0000
committerNoah Misch2022-05-09 15:35:12 +0000
commit88743d581e1bdedc13e4ca33c5a6597a5d2dbdc4 (patch)
tree0296a15ba8e01096ed35dac9c2ea26cda2465c25
parent35edcc0cee7bf7d4746e3e5b7966b1f0ec509560 (diff)
In REFRESH MATERIALIZED VIEW, set user ID before running user code.
It intended to, but did not, achieve this. Adopt the new standard of setting user ID just after locking the relation. Back-patch to v10 (all supported versions). Reviewed by Simon Riggs. Reported by Alvaro Herrera. Security: CVE-2022-1552
-rw-r--r--src/backend/commands/matview.c30
-rw-r--r--src/test/regress/expected/privileges.out16
-rw-r--r--src/test/regress/sql/privileges.sql17
3 files changed, 44 insertions, 19 deletions
diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c
index 2ba5172f7c6..b1fa88d88a1 100644
--- a/src/backend/commands/matview.c
+++ b/src/backend/commands/matview.c
@@ -167,6 +167,17 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
lockmode, 0,
RangeVarCallbackOwnsTable, NULL);
matviewRel = table_open(matviewOid, NoLock);
+ relowner = matviewRel->rd_rel->relowner;
+
+ /*
+ * 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(relowner,
+ save_sec_context | SECURITY_RESTRICTED_OPERATION);
+ save_nestlevel = NewGUCNestLevel();
/* Make sure it is a materialized view. */
if (matviewRel->rd_rel->relkind != RELKIND_MATVIEW)
@@ -269,19 +280,6 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
*/
SetMatViewPopulatedState(matviewRel, !stmt->skipData);
- relowner = matviewRel->rd_rel->relowner;
-
- /*
- * Switch to the owner's userid, so that any functions are run as that
- * user. Also arrange to make GUC variable changes local to this command.
- * Don't lock it down too tight to create a temporary table just yet. We
- * will switch modes when we are about to execute user code.
- */
- GetUserIdAndSecContext(&save_userid, &save_sec_context);
- SetUserIdAndSecContext(relowner,
- save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
- save_nestlevel = NewGUCNestLevel();
-
/* Concurrent refresh builds new data in temp tablespace, and does diff. */
if (concurrent)
{
@@ -304,12 +302,6 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
LockRelationOid(OIDNewHeap, AccessExclusiveLock);
dest = CreateTransientRelDestReceiver(OIDNewHeap);
- /*
- * Now lock down security-restricted operations.
- */
- SetUserIdAndSecContext(relowner,
- save_sec_context | SECURITY_RESTRICTED_OPERATION);
-
/* Generate the data, if wanted. */
if (!stmt->skipData)
processed = refresh_matview_datafill(dest, dataQuery, queryString);
diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out
index c3f88d3e234..1a62dde37b6 100644
--- a/src/test/regress/expected/privileges.out
+++ b/src/test/regress/expected/privileges.out
@@ -1511,6 +1511,22 @@ CONTEXT: SQL function "unwanted_grant" statement 1
SQL statement "SELECT unwanted_grant()"
PL/pgSQL function sro_trojan() line 1 at PERFORM
SQL function "mv_action" statement 1
+-- REFRESH MATERIALIZED VIEW CONCURRENTLY use of eval_const_expressions()
+SET SESSION AUTHORIZATION regress_sro_user;
+CREATE FUNCTION unwanted_grant_nofail(int) RETURNS int
+ IMMUTABLE LANGUAGE plpgsql AS $$
+BEGIN
+ PERFORM unwanted_grant();
+ RAISE WARNING 'owned';
+ RETURN 1;
+EXCEPTION WHEN OTHERS THEN
+ RETURN 2;
+END$$;
+CREATE MATERIALIZED VIEW sro_index_mv AS SELECT 1 AS c;
+CREATE UNIQUE INDEX ON sro_index_mv (c) WHERE unwanted_grant_nofail(1) > 0;
+\c -
+REFRESH MATERIALIZED VIEW CONCURRENTLY sro_index_mv;
+REFRESH MATERIALIZED VIEW sro_index_mv;
DROP OWNED BY regress_sro_user;
DROP ROLE regress_sro_user;
-- Admin options
diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql
index 30bc71a47cf..ebfa9d7d554 100644
--- a/src/test/regress/sql/privileges.sql
+++ b/src/test/regress/sql/privileges.sql
@@ -945,6 +945,23 @@ REFRESH MATERIALIZED VIEW sro_mv;
REFRESH MATERIALIZED VIEW sro_mv;
BEGIN; SET CONSTRAINTS ALL IMMEDIATE; REFRESH MATERIALIZED VIEW sro_mv; COMMIT;
+-- REFRESH MATERIALIZED VIEW CONCURRENTLY use of eval_const_expressions()
+SET SESSION AUTHORIZATION regress_sro_user;
+CREATE FUNCTION unwanted_grant_nofail(int) RETURNS int
+ IMMUTABLE LANGUAGE plpgsql AS $$
+BEGIN
+ PERFORM unwanted_grant();
+ RAISE WARNING 'owned';
+ RETURN 1;
+EXCEPTION WHEN OTHERS THEN
+ RETURN 2;
+END$$;
+CREATE MATERIALIZED VIEW sro_index_mv AS SELECT 1 AS c;
+CREATE UNIQUE INDEX ON sro_index_mv (c) WHERE unwanted_grant_nofail(1) > 0;
+\c -
+REFRESH MATERIALIZED VIEW CONCURRENTLY sro_index_mv;
+REFRESH MATERIALIZED VIEW sro_index_mv;
+
DROP OWNED BY regress_sro_user;
DROP ROLE regress_sro_user;