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..0e1d6a52d 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 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 eda2009ca..19ff019a9 100644 --- a/lib/config/expression.cpp +++ b/lib/config/expression.cpp @@ -909,6 +909,11 @@ 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)); + ExpressionResult nameres = m_Name->Evaluate(frame); CHECK_RESULT(nameres); @@ -943,6 +948,11 @@ 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)); + ExpressionResult typeres = m_Type->Evaluate(frame, dhint); CHECK_RESULT(typeres); Type::Ptr type = typeres.GetValue();