|
|
a21a05 |
From ad6890564c9408c299460decf013c02ce8f44e2a Mon Sep 17 00:00:00 2001
|
|
|
a21a05 |
From: =?UTF-8?q?Patrik=20Novotn=C3=BD?= <panovotn@redhat.com>
|
|
|
a21a05 |
Date: Tue, 30 Mar 2021 11:27:29 +0200
|
|
|
a21a05 |
Subject: [PATCH] In security-restricted operations, block enqueue of at-commit
|
|
|
a21a05 |
user code.
|
|
|
a21a05 |
|
|
|
a21a05 |
Original commit: 0c3185e963d9f9dd0608214f7d732b84aa0888fe
|
|
|
a21a05 |
|
|
|
a21a05 |
Original commit message:
|
|
|
a21a05 |
|
|
|
a21a05 |
Specifically, this blocks DECLARE ... WITH HOLD and firing of deferred
|
|
|
a21a05 |
triggers within index expressions and materialized view queries. An
|
|
|
a21a05 |
attacker having permission to create non-temp objects in at least one
|
|
|
a21a05 |
schema could execute arbitrary SQL functions under the identity of the
|
|
|
a21a05 |
bootstrap superuser. One can work around the vulnerability by disabling
|
|
|
a21a05 |
autovacuum and not manually running ANALYZE, CLUSTER, REINDEX, CREATE
|
|
|
a21a05 |
INDEX, VACUUM FULL, or REFRESH MATERIALIZED VIEW. (Don't restore from
|
|
|
a21a05 |
pg_dump, since it runs some of those commands.) Plain VACUUM (without
|
|
|
a21a05 |
FULL) is safe, and all commands are fine when a trusted user owns the
|
|
|
a21a05 |
target object. Performance may degrade quickly under this workaround,
|
|
|
a21a05 |
however. Back-patch to 9.5 (all supported versions).
|
|
|
a21a05 |
---
|
|
|
a21a05 |
src/backend/commands/portalcmds.c | 6 ++++++
|
|
|
a21a05 |
src/backend/commands/trigger.c | 13 +++++++++++++
|
|
|
a21a05 |
2 files changed, 19 insertions(+)
|
|
|
a21a05 |
|
|
|
a21a05 |
diff --git a/src/backend/commands/portalcmds.c b/src/backend/commands/portalcmds.c
|
|
|
a21a05 |
index e458adfad1..ea1b198dc8 100644
|
|
|
a21a05 |
--- a/src/backend/commands/portalcmds.c
|
|
|
a21a05 |
+++ b/src/backend/commands/portalcmds.c
|
|
|
a21a05 |
@@ -27,6 +27,7 @@
|
|
|
a21a05 |
#include "commands/portalcmds.h"
|
|
|
a21a05 |
#include "executor/executor.h"
|
|
|
a21a05 |
#include "executor/tstoreReceiver.h"
|
|
|
a21a05 |
+#include "miscadmin.h"
|
|
|
a21a05 |
#include "tcop/pquery.h"
|
|
|
a21a05 |
#include "utils/memutils.h"
|
|
|
a21a05 |
#include "utils/snapmgr.h"
|
|
|
a21a05 |
@@ -67,6 +68,11 @@ PerformCursorOpen(PlannedStmt *stmt, ParamListInfo params,
|
|
|
a21a05 |
*/
|
|
|
a21a05 |
if (!(cstmt->options & CURSOR_OPT_HOLD))
|
|
|
a21a05 |
RequireTransactionChain(isTopLevel, "DECLARE CURSOR");
|
|
|
a21a05 |
+ else if (InSecurityRestrictedOperation())
|
|
|
a21a05 |
+ ereport(ERROR,
|
|
|
a21a05 |
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
|
|
a21a05 |
+ errmsg("cannot create a cursor WITH HOLD within security-restricted operation")));
|
|
|
a21a05 |
+
|
|
|
a21a05 |
|
|
|
a21a05 |
/*
|
|
|
a21a05 |
* Create a portal and copy the plan and queryString into its memory.
|
|
|
a21a05 |
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
|
|
|
a21a05 |
index 357313dffa..5a0c65fcaa 100644
|
|
|
a21a05 |
--- a/src/backend/commands/trigger.c
|
|
|
a21a05 |
+++ b/src/backend/commands/trigger.c
|
|
|
a21a05 |
@@ -3480,6 +3480,7 @@ afterTriggerMarkEvents(AfterTriggerEventList *events,
|
|
|
a21a05 |
bool immediate_only)
|
|
|
a21a05 |
{
|
|
|
a21a05 |
bool found = false;
|
|
|
a21a05 |
+ bool deferred_found = false;
|
|
|
a21a05 |
AfterTriggerEvent event;
|
|
|
a21a05 |
AfterTriggerEventChunk *chunk;
|
|
|
a21a05 |
|
|
|
a21a05 |
@@ -3515,6 +3516,7 @@ afterTriggerMarkEvents(AfterTriggerEventList *events,
|
|
|
a21a05 |
*/
|
|
|
a21a05 |
if (defer_it && move_list != NULL)
|
|
|
a21a05 |
{
|
|
|
a21a05 |
+ deferred_found = true;
|
|
|
a21a05 |
/* add it to move_list */
|
|
|
a21a05 |
afterTriggerAddEvent(move_list, event, evtshared);
|
|
|
a21a05 |
/* mark original copy "done" so we don't do it again */
|
|
|
a21a05 |
@@ -3522,6 +3524,17 @@ afterTriggerMarkEvents(AfterTriggerEventList *events,
|
|
|
a21a05 |
}
|
|
|
a21a05 |
}
|
|
|
a21a05 |
|
|
|
a21a05 |
+ /*
|
|
|
a21a05 |
+ * We could allow deferred triggers if, before the end of the
|
|
|
a21a05 |
+ * security-restricted operation, we were to verify that a SET CONSTRAINTS
|
|
|
a21a05 |
+ * ... IMMEDIATE has fired all such triggers. For now, don't bother.
|
|
|
a21a05 |
+ */
|
|
|
a21a05 |
+ if (deferred_found && InSecurityRestrictedOperation())
|
|
|
a21a05 |
+ ereport(ERROR,
|
|
|
a21a05 |
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
|
|
a21a05 |
+ errmsg("cannot fire deferred trigger within security-restricted operation")));
|
|
|
a21a05 |
+
|
|
|
a21a05 |
+
|
|
|
a21a05 |
return found;
|
|
|
a21a05 |
}
|
|
|
a21a05 |
|
|
|
a21a05 |
--
|
|
|
a21a05 |
2.26.2
|
|
|
a21a05 |
|