From 080640122af4662d2fa86a1825442826522b779d Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Thu, 4 Mar 2021 12:13:22 +0100 Subject: [PATCH 1/3] Disallow nested config objects --- lib/config/configitem.cpp | 6 ++++++ lib/config/configitem.hpp | 7 +++++++ lib/config/expression.cpp | 6 ++++++ 3 files changed, 19 insertions(+) diff --git a/lib/config/configitem.cpp b/lib/config/configitem.cpp index 7687e50be..46bd99954 100644 --- a/lib/config/configitem.cpp +++ b/lib/config/configitem.cpp @@ -8,6 +8,7 @@ #include "config/configcompiler.hpp" #include "base/application.hpp" #include "base/configtype.hpp" +#include "base/defer.hpp" #include "base/objectlock.hpp" #include "base/convert.hpp" #include "base/logger.hpp" @@ -32,6 +33,8 @@ using namespace icinga; std::mutex ConfigItem::m_Mutex; +thread_local bool ConfigItem::m_CommitInProgress = false; + ConfigItem::TypeMap ConfigItem::m_Items; ConfigItem::TypeMap ConfigItem::m_DefaultTemplates; ConfigItem::ItemList ConfigItem::m_UnnamedItems; @@ -191,6 +194,9 @@ ConfigObject::Ptr ConfigItem::Commit(bool discard) if (m_Scope) m_Scope->CopyTo(frame.Locals); try { + m_CommitInProgress = true; + Defer resetCommitInProgress ([this]() { m_CommitInProgress = false; }); + m_Expression->Evaluate(frame, &debugHints); } catch (const std::exception& ex) { if (m_IgnoreOnError) { diff --git a/lib/config/configitem.hpp b/lib/config/configitem.hpp index bd04b47f4..2d0f9f891 100644 --- a/lib/config/configitem.hpp +++ b/lib/config/configitem.hpp @@ -64,6 +64,12 @@ public: static void RemoveIgnoredItems(const String& allowedConfigPath); + static inline + bool RunsInCommitContext() + { + return m_CommitInProgress; + } + private: Type::Ptr m_Type; /**< The object type. */ String m_Name; /**< The name. */ @@ -82,6 +88,7 @@ private: ConfigObject::Ptr m_Object; static std::mutex m_Mutex; + static thread_local bool m_CommitInProgress; typedef std::map ItemMap; typedef std::map TypeMap; diff --git a/lib/config/expression.cpp b/lib/config/expression.cpp index 4c8fd6c5a..bbcfc6796 100644 --- a/lib/config/expression.cpp +++ b/lib/config/expression.cpp @@ -909,6 +909,9 @@ ExpressionResult ApplyExpression::DoEvaluate(ScriptFrame& frame, DebugHint*) con if (frame.Sandboxed) BOOST_THROW_EXCEPTION(ScriptError("Apply rules are not allowed in sandbox mode.", m_DebugInfo)); + if (ConfigItem::RunsInCommitContext()) + BOOST_THROW_EXCEPTION(ScriptError("Nested objects are not allowed", m_DebugInfo)); + ExpressionResult nameres = m_Name->Evaluate(frame); CHECK_RESULT(nameres); @@ -932,6 +935,9 @@ ExpressionResult ObjectExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhi if (frame.Sandboxed) BOOST_THROW_EXCEPTION(ScriptError("Object definitions are not allowed in sandbox mode.", m_DebugInfo)); + if (ConfigItem::RunsInCommitContext()) + BOOST_THROW_EXCEPTION(ScriptError("Nested objects are not allowed", m_DebugInfo)); + ExpressionResult typeres = m_Type->Evaluate(frame, dhint); CHECK_RESULT(typeres); Type::Ptr type = typeres.GetValue(); From 81d20dc35a141e5280659ef8e3d99a2629c5ca99 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Wed, 13 Jul 2022 18:54:07 +0200 Subject: [PATCH 2/3] Prevent apply rule creation outside of an activation context just like object creation. --- lib/config/activationcontext.hpp | 6 ++++++ lib/config/applyrule.cpp | 3 +++ 2 files changed, 9 insertions(+) diff --git a/lib/config/activationcontext.hpp b/lib/config/activationcontext.hpp index e22f6b290..a2f9f9e1c 100644 --- a/lib/config/activationcontext.hpp +++ b/lib/config/activationcontext.hpp @@ -19,6 +19,12 @@ public: static ActivationContext::Ptr GetCurrentContext(); + static inline + void AssertOnContext() + { + GetCurrentContext(); + } + private: static void PushContext(const ActivationContext::Ptr& context); static void PopContext(); diff --git a/lib/config/applyrule.cpp b/lib/config/applyrule.cpp index fec461845..9df377d32 100644 --- a/lib/config/applyrule.cpp +++ b/lib/config/applyrule.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2012 Icinga GmbH // SPDX-License-Identifier: GPL-2.0-or-later +#include "config/activationcontext.hpp" #include "config/applyrule.hpp" #include "base/logger.hpp" #include @@ -62,6 +63,8 @@ void ApplyRule::AddRule(const String& sourceType, const String& targetType, cons const Expression::Ptr& expression, const Expression::Ptr& filter, const String& package, const String& fkvar, const String& fvvar, const Expression::Ptr& fterm, bool ignoreOnError, const DebugInfo& di, const Dictionary::Ptr& scope) { + ActivationContext::AssertOnContext(); + auto actualTargetType (&targetType); if (*actualTargetType == "") { From 275e466c59e1083d8c763a14d439b1fa0b729246 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Tue, 10 Mar 2026 11:35:33 +0100 Subject: [PATCH 3/3] Call `ActivationContext::AssertOnContext()` ASAP in `ObjectExpression::DoEvaluate()` and `ApplyExpression::DoEvaluate()`. --- lib/config/applyrule.cpp | 2 -- lib/config/expression.cpp | 4 ++++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/config/applyrule.cpp b/lib/config/applyrule.cpp index 9df377d32..0e1d6a52d 100644 --- a/lib/config/applyrule.cpp +++ b/lib/config/applyrule.cpp @@ -63,8 +63,6 @@ void ApplyRule::AddRule(const String& sourceType, const String& targetType, cons const Expression::Ptr& expression, const Expression::Ptr& filter, const String& package, const String& fkvar, const String& fvvar, const Expression::Ptr& fterm, bool ignoreOnError, const DebugInfo& di, const Dictionary::Ptr& scope) { - ActivationContext::AssertOnContext(); - auto actualTargetType (&targetType); if (*actualTargetType == "") { diff --git a/lib/config/expression.cpp b/lib/config/expression.cpp index bbcfc6796..449cb826c 100644 --- a/lib/config/expression.cpp +++ b/lib/config/expression.cpp @@ -909,6 +909,8 @@ ExpressionResult ApplyExpression::DoEvaluate(ScriptFrame& frame, DebugHint*) con if (frame.Sandboxed) BOOST_THROW_EXCEPTION(ScriptError("Apply rules are not allowed in sandbox mode.", m_DebugInfo)); + ActivationContext::AssertOnContext(); + if (ConfigItem::RunsInCommitContext()) BOOST_THROW_EXCEPTION(ScriptError("Nested objects are not allowed", m_DebugInfo)); @@ -935,6 +937,8 @@ ExpressionResult ObjectExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhi if (frame.Sandboxed) BOOST_THROW_EXCEPTION(ScriptError("Object definitions are not allowed in sandbox mode.", m_DebugInfo)); + ActivationContext::AssertOnContext(); + if (ConfigItem::RunsInCommitContext()) BOOST_THROW_EXCEPTION(ScriptError("Nested objects are not allowed", m_DebugInfo));