From 53b287ecb7856e8d3af4bd5ff2400cabbc2b08fc Mon Sep 17 00:00:00 2001 From: "qianlu.kk" Date: Tue, 24 Sep 2024 19:32:25 +0800 Subject: [PATCH] update --- core/ebpf/eBPFServer.cpp | 102 ++++++++++++--------- core/ebpf/eBPFServer.h | 24 ++++- core/plugin/input/InputFileSecurity.cpp | 2 +- core/plugin/input/InputNetworkObserver.cpp | 2 +- core/plugin/input/InputNetworkSecurity.cpp | 2 +- core/plugin/input/InputProcessSecurity.cpp | 2 +- core/unittest/ebpf/eBPFServerUnittest.cpp | 39 ++++++++ 7 files changed, 121 insertions(+), 52 deletions(-) diff --git a/core/ebpf/eBPFServer.cpp b/core/ebpf/eBPFServer.cpp index d659163aef..2677152af7 100644 --- a/core/ebpf/eBPFServer.cpp +++ b/core/ebpf/eBPFServer.cpp @@ -37,65 +37,82 @@ static const uint16_t KERNEL_VERSION_310 = 3010; // for centos7 static const std::string KERNEL_NAME_CENTOS = "CentOS"; static const uint16_t KERNEL_CENTOS_MIN_VERSION = 7006; -bool eBPFServer::IsSupportedEnv() { - if (mCheckStatus.load() != int(CheckStatus::UNKNOWN)) { - return mCheckStatus.load() == int(CheckStatus::SUPPORT); +bool EnvManager::IsSupportedEnv(nami::PluginType type) { + if (!mInited) InitEnvInfo(); + switch (type) + { + case nami::PluginType::NETWORK_OBSERVE: + return mArchSupport && (mBTFSupport || m310Support); + case nami::PluginType::FILE_SECURITY: + case nami::PluginType::NETWORK_SECURITY: + case nami::PluginType::PROCESS_SECURITY: { + return mArchSupport && mBTFSupport; + } + default: + return false; } +} + +void EnvManager::InitEnvInfo() { + if (mInited) return; + mInited = true; + #ifdef _MSC_VER LOG_WARNING(sLogger, ("MS", "not supported")); - mCheckStatus = int(CheckStatus::NOT_SUPPORT); - return false; + mArchSupport = false; + return; #elif defined(__aarch64__) LOG_WARNING(sLogger, ("aarch64", "not supported")); - mCheckStatus = int(CheckStatus::NOT_SUPPORT); - return false; + mArchSupport = false; + return; #elif defined(__arm__) LOG_WARNING(sLogger, ("arm", "not supported")); - mCheckStatus = int(CheckStatus::NOT_SUPPORT); - return false; + mArchSupport = false; + return; #elif defined(__i386__) LOG_WARNING(sLogger, ("i386", "not supported")); - mCheckStatus = int(CheckStatus::NOT_SUPPORT); - return false; + mArchSupport = false; + return; #endif - std::string release; - int64_t version; - GetKernelInfo(release, version); - LOG_INFO(sLogger, ("ebpf kernel release", release) ("kernel version", version)); - if (release.empty()) { + mArchSupport = true; + GetKernelInfo(mRelease, mVersion); + LOG_INFO(sLogger, ("ebpf kernel release", mRelease) ("kernel version", mVersion)); + if (mRelease.empty()) { LOG_WARNING(sLogger, ("cannot find kernel release", "")); - mCheckStatus = int(CheckStatus::NOT_SUPPORT); - return false; + mBTFSupport = false; + return; } - if (version >= INT64_FLAG(kernel_min_version_for_ebpf)) { - mCheckStatus = int(CheckStatus::SUPPORT); - return true; + if (mVersion >= INT64_FLAG(kernel_min_version_for_ebpf)) { + mBTFSupport = true; + return; } - if (version / 1000000 != KERNEL_VERSION_310) { + if (mVersion / 1000000 != KERNEL_VERSION_310) { LOG_WARNING(sLogger, - ("unsupported kernel version, will not start eBPF plugin ... version", version)); - mCheckStatus = int(CheckStatus::NOT_SUPPORT); - return false; + ("unsupported kernel version, will not start eBPF plugin ... version", mVersion)); + m310Support = false; + return; } - std::string os; - int64_t osVersion; - if (GetRedHatReleaseInfo(os, osVersion, STRING_FLAG(default_container_host_path)) - || GetRedHatReleaseInfo(os, osVersion)) { - if(os == KERNEL_NAME_CENTOS && osVersion >= KERNEL_CENTOS_MIN_VERSION) { - mCheckStatus = int(CheckStatus::SUPPORT); - return true; + if (GetRedHatReleaseInfo(mOs, mOsVersion, STRING_FLAG(default_container_host_path)) + || GetRedHatReleaseInfo(mOs, mOsVersion)) { + if(mOs == KERNEL_NAME_CENTOS && mOsVersion >= KERNEL_CENTOS_MIN_VERSION) { + m310Support = false; + return; } else { LOG_WARNING(sLogger, ("unsupported os for 310 kernel, will not start eBPF plugin ...", "") - ("os", os)("version", osVersion)); - mCheckStatus = int(CheckStatus::NOT_SUPPORT); - return false; + ("os", mOs)("version", mOsVersion)); + m310Support = false; + return; } } LOG_WARNING(sLogger, ("not redhat release, will not start eBPF plugin ...", "")); - mCheckStatus = int(CheckStatus::NOT_SUPPORT); - return false; + m310Support = true; + return; +} + +bool eBPFServer::IsSupportedEnv(nami::PluginType type) { + return mEnvMgr.IsSupportedEnv(type); } void eBPFServer::Init() { @@ -103,10 +120,7 @@ void eBPFServer::Init() { return; } mInited = true; - // check running env, including aarch / kernel version / os - if (!IsSupportedEnv()) { - return; - } + mEnvMgr.InitEnvInfo(); mSourceManager = std::make_unique(); mSourceManager->Init(); // ebpf config @@ -246,14 +260,14 @@ bool eBPFServer::EnablePlugin(const std::string& pipeline_name, uint32_t plugin_ const PipelineContext* ctx, const std::variant options) { Init(); - if (!IsSupportedEnv()) { + if (!IsSupportedEnv(type)) { return false; } return StartPluginInternal(pipeline_name, plugin_index, type, ctx, options); } bool eBPFServer::DisablePlugin(const std::string& pipeline_name, nami::PluginType type) { - if (!IsSupportedEnv()) { + if (!IsSupportedEnv(type)) { return true; } std::string prev_pipeline = CheckLoadedPipelineName(type); @@ -281,7 +295,7 @@ void eBPFServer::UpdatePipelineName(nami::PluginType type, const std::string& na } bool eBPFServer::SuspendPlugin(const std::string& pipeline_name, nami::PluginType type) { - if (!IsSupportedEnv()) { + if (!IsSupportedEnv(type)) { return false; } // mark plugin status is update diff --git a/core/ebpf/eBPFServer.h b/core/ebpf/eBPFServer.h index ed11762fc1..e423fe4e26 100644 --- a/core/ebpf/eBPFServer.h +++ b/core/ebpf/eBPFServer.h @@ -33,6 +33,24 @@ namespace logtail { namespace ebpf { +class EnvManager { +public: + void InitEnvInfo(); + bool IsSupportedEnv(nami::PluginType type); +private: + volatile bool mInited = false; + std::string mRelease; + int64_t mVersion = -1; + std::string mOs; + int64_t mOsVersion; + std::atomic_bool mArchSupport = false; + std::atomic_bool mBTFSupport = false; + std::atomic_bool m310Support = false; +#ifdef APSARA_UNIT_TEST_MAIN + friend class eBPFServerUnittest; +#endif +}; + class eBPFServer : public InputRunner { public: eBPFServer(const eBPFServer&) = delete; @@ -62,7 +80,7 @@ class eBPFServer : public InputRunner { bool HasRegisteredPlugins() const override; - bool IsSupportedEnv(); + bool IsSupportedEnv(nami::PluginType type); private: bool StartPluginInternal(const std::string& pipeline_name, uint32_t plugin_index, @@ -89,9 +107,7 @@ class eBPFServer : public InputRunner { eBPFAdminConfig mAdminConfig; volatile bool mInited = false; - // TODO @qianlu.kk each plugin has it's own env requirements, so we need to implement an env checker class - enum class CheckStatus {UNKNOWN, SUPPORT, NOT_SUPPORT}; - std::atomic_int mCheckStatus = int(CheckStatus::UNKNOWN); + EnvManager mEnvMgr; #ifdef APSARA_UNIT_TEST_MAIN friend class eBPFServerUnittest; diff --git a/core/plugin/input/InputFileSecurity.cpp b/core/plugin/input/InputFileSecurity.cpp index bd8c2e6ca4..39351d86d9 100644 --- a/core/plugin/input/InputFileSecurity.cpp +++ b/core/plugin/input/InputFileSecurity.cpp @@ -26,7 +26,7 @@ namespace logtail { const std::string InputFileSecurity::sName = "input_file_security"; bool InputFileSecurity::Init(const Json::Value& config, Json::Value& optionalGoPipeline) { - if (!ebpf::eBPFServer::GetInstance()->IsSupportedEnv()) { + if (!ebpf::eBPFServer::GetInstance()->IsSupportedEnv(nami::PluginType::FILE_SECURITY)) { return false; } std::string prev_pipeline_name = ebpf::eBPFServer::GetInstance()->CheckLoadedPipelineName(nami::PluginType::FILE_SECURITY); diff --git a/core/plugin/input/InputNetworkObserver.cpp b/core/plugin/input/InputNetworkObserver.cpp index 443dda74ed..29eb674efb 100644 --- a/core/plugin/input/InputNetworkObserver.cpp +++ b/core/plugin/input/InputNetworkObserver.cpp @@ -26,7 +26,7 @@ namespace logtail { const std::string InputNetworkObserver::sName = "input_network_observer"; bool InputNetworkObserver::Init(const Json::Value& config, Json::Value& optionalGoPipeline) { - if (!ebpf::eBPFServer::GetInstance()->IsSupportedEnv()) { + if (!ebpf::eBPFServer::GetInstance()->IsSupportedEnv(nami::PluginType::NETWORK_OBSERVE)) { return false; } std::string prev_pipeline_name = ebpf::eBPFServer::GetInstance()->CheckLoadedPipelineName(nami::PluginType::NETWORK_OBSERVE); diff --git a/core/plugin/input/InputNetworkSecurity.cpp b/core/plugin/input/InputNetworkSecurity.cpp index b2acc3090b..9e2ef153ba 100644 --- a/core/plugin/input/InputNetworkSecurity.cpp +++ b/core/plugin/input/InputNetworkSecurity.cpp @@ -28,7 +28,7 @@ const std::string InputNetworkSecurity::sName = "input_network_security"; // update: init -> stop(false) -> start // stop: stop(true) bool InputNetworkSecurity::Init(const Json::Value& config, Json::Value& optionalGoPipeline) { - if (!ebpf::eBPFServer::GetInstance()->IsSupportedEnv()) { + if (!ebpf::eBPFServer::GetInstance()->IsSupportedEnv(nami::PluginType::NETWORK_SECURITY)) { return false; } std::string prev_pipeline_name = ebpf::eBPFServer::GetInstance()->CheckLoadedPipelineName(nami::PluginType::NETWORK_SECURITY); diff --git a/core/plugin/input/InputProcessSecurity.cpp b/core/plugin/input/InputProcessSecurity.cpp index 8a9663c05f..86c43ad03b 100644 --- a/core/plugin/input/InputProcessSecurity.cpp +++ b/core/plugin/input/InputProcessSecurity.cpp @@ -24,7 +24,7 @@ namespace logtail { const std::string InputProcessSecurity::sName = "input_process_security"; bool InputProcessSecurity::Init(const Json::Value& config, Json::Value& optionalGoPipeline) { - if (!ebpf::eBPFServer::GetInstance()->IsSupportedEnv()) { + if (!ebpf::eBPFServer::GetInstance()->IsSupportedEnv(nami::PluginType::PROCESS_SECURITY)) { return false; } std::string prev_pipeline_name = ebpf::eBPFServer::GetInstance()->CheckLoadedPipelineName(nami::PluginType::PROCESS_SECURITY); diff --git a/core/unittest/ebpf/eBPFServerUnittest.cpp b/core/unittest/ebpf/eBPFServerUnittest.cpp index 8a45a73242..988a6a3930 100644 --- a/core/unittest/ebpf/eBPFServerUnittest.cpp +++ b/core/unittest/ebpf/eBPFServerUnittest.cpp @@ -46,6 +46,8 @@ class eBPFServerUnittest : public testing::Test { void TestInitAndStop(); + void TestEnvManager(); + protected: void SetUp() override { config_ = new eBPFAdminConfig; @@ -790,6 +792,42 @@ void eBPFServerUnittest::TestInitAndStop() { EXPECT_EQ(false, ret); } +void eBPFServerUnittest::TestEnvManager() { + eBPFServer::GetInstance()->mEnvMgr.InitEnvInfo(); + + EXPECT_TRUE(eBPFServer::GetInstance()->mEnvMgr.mInited); + EXPECT_TRUE(eBPFServer::GetInstance()->mEnvMgr.mArchSupport); + EXPECT_TRUE(eBPFServer::GetInstance()->mEnvMgr.mVersion > 0); + EXPECT_TRUE(eBPFServer::GetInstance()->mEnvMgr.mRelease.size()); + // EXPECT_TRUE(eBPFServer::GetInstance()->mEnvMgr.mOsVersion.size()); + + eBPFServer::GetInstance()->mEnvMgr.m310Support = false; + eBPFServer::GetInstance()->mEnvMgr.mArchSupport = false; + eBPFServer::GetInstance()->mEnvMgr.mBTFSupport = true; + EXPECT_EQ(eBPFServer::GetInstance()->IsSupportedEnv(nami::PluginType::NETWORK_OBSERVE), false); + EXPECT_EQ(eBPFServer::GetInstance()->IsSupportedEnv(nami::PluginType::NETWORK_SECURITY), false); + EXPECT_EQ(eBPFServer::GetInstance()->IsSupportedEnv(nami::PluginType::PROCESS_SECURITY), false); + EXPECT_EQ(eBPFServer::GetInstance()->IsSupportedEnv(nami::PluginType::FILE_SECURITY), false); + + eBPFServer::GetInstance()->mEnvMgr.m310Support = false; + eBPFServer::GetInstance()->mEnvMgr.mArchSupport = true; + eBPFServer::GetInstance()->mEnvMgr.mBTFSupport = true; + + EXPECT_EQ(eBPFServer::GetInstance()->IsSupportedEnv(nami::PluginType::NETWORK_OBSERVE), true); + EXPECT_EQ(eBPFServer::GetInstance()->IsSupportedEnv(nami::PluginType::NETWORK_SECURITY), true); + EXPECT_EQ(eBPFServer::GetInstance()->IsSupportedEnv(nami::PluginType::PROCESS_SECURITY), true); + EXPECT_EQ(eBPFServer::GetInstance()->IsSupportedEnv(nami::PluginType::FILE_SECURITY), true); + + eBPFServer::GetInstance()->mEnvMgr.m310Support = true; + eBPFServer::GetInstance()->mEnvMgr.mArchSupport = true; + eBPFServer::GetInstance()->mEnvMgr.mBTFSupport = false; + + EXPECT_EQ(eBPFServer::GetInstance()->IsSupportedEnv(nami::PluginType::NETWORK_OBSERVE), true); + EXPECT_EQ(eBPFServer::GetInstance()->IsSupportedEnv(nami::PluginType::NETWORK_SECURITY), false); + EXPECT_EQ(eBPFServer::GetInstance()->IsSupportedEnv(nami::PluginType::PROCESS_SECURITY), false); + EXPECT_EQ(eBPFServer::GetInstance()->IsSupportedEnv(nami::PluginType::FILE_SECURITY), false); +} + UNIT_TEST_CASE(eBPFServerUnittest, TestDefaultEbpfParameters); UNIT_TEST_CASE(eBPFServerUnittest, TestDefaultAndLoadEbpfParameters); UNIT_TEST_CASE(eBPFServerUnittest, TestLoadEbpfParametersV1); @@ -800,6 +838,7 @@ UNIT_TEST_CASE(eBPFServerUnittest, TestEnableProcessPlugin) UNIT_TEST_CASE(eBPFServerUnittest, TestEnableNetworkSecurePlugin) UNIT_TEST_CASE(eBPFServerUnittest, TestEnableFileSecurePlugin) UNIT_TEST_CASE(eBPFServerUnittest, TestInitAndStop) +UNIT_TEST_CASE(eBPFServerUnittest, TestEnvManager) } }