Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

check runtime env #1749

Merged
merged 5 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions core/ebpf/SourceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "ebpf/include/SysAkApi.h"
#include "common/MachineInfoUtil.h"
#include "common/LogtailCommonFlags.h"
#include "app_config/AppConfig.h"

#include <string>
#include <filesystem>
Expand Down Expand Up @@ -62,8 +63,15 @@ SourceManager::~SourceManager() {
void SourceManager::Init() {
mHostIp = GetHostIp();
mHostName = GetHostName();
mHostPathPrefix = STRING_FLAG(default_container_host_path);
// load ebpf lib

// read host path prefix
if (AppConfig::GetInstance()->IsPurageContainerMode()) {
mHostPathPrefix = STRING_FLAG(default_container_host_path);
LOG_DEBUG(sLogger, ("running in container mode, would set host path prefix to ", mHostPathPrefix));
} else {
LOG_DEBUG(sLogger, ("running in host mode", "would not set host path prefix ..."));
}

mBinaryPath = GetProcessExecutionDir();
mFullLibName = "lib" + m_lib_name_ + ".so";
for (auto& x : mRunning) {
Expand Down
132 changes: 127 additions & 5 deletions core/ebpf/eBPFServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,126 @@
#include "logger/Logger.h"
#include "ebpf/include/export.h"
#include "common/LogtailCommonFlags.h"
#include "common/MachineInfoUtil.h"

DEFINE_FLAG_INT64(kernel_min_version_for_ebpf,
"the minimum kernel version that supported eBPF normal running, 4.19.0.0 -> 4019000000",
4019000000);

namespace logtail {
namespace ebpf {

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 EnvManager::IsSupportedEnv(nami::PluginType type) {
KayzzzZ marked this conversation as resolved.
Show resolved Hide resolved
if (!mInited) {
LOG_ERROR(sLogger, ("env manager not inited ...", ""));
return false;
}
bool status = false;
switch (type)
{
case nami::PluginType::NETWORK_OBSERVE:
status = mArchSupport && (mBTFSupport || m310Support);
break;
case nami::PluginType::FILE_SECURITY:
case nami::PluginType::NETWORK_SECURITY:
case nami::PluginType::PROCESS_SECURITY: {
status = mArchSupport && mBTFSupport;
break;
}
default:
status = false;
}
if (!status) {
LOG_WARNING(sLogger, ("runtime env not supported, plugin type: ", int(type))
("arch support is ", mArchSupport) ("btf support is ", mBTFSupport) ("310 support is ", m310Support));
}
return status;
}

bool EnvManager::AbleToLoadDyLib() {
return mArchSupport;
}

void EnvManager::InitEnvInfo() {
KayzzzZ marked this conversation as resolved.
Show resolved Hide resolved
if (mInited) return;
mInited = true;

#ifdef _MSC_VER
LOG_WARNING(sLogger, ("MS", "not supported"));
mArchSupport = false;
return;
#elif defined(__aarch64__)
LOG_WARNING(sLogger, ("aarch64", "not supported"));
mArchSupport = false;
return;
#elif defined(__arm__)
LOG_WARNING(sLogger, ("arm", "not supported"));
mArchSupport = false;
return;
#elif defined(__i386__)
LOG_WARNING(sLogger, ("i386", "not supported"));
mArchSupport = false;
return;
#endif
mArchSupport = true;
std::string release;
int64_t version;
GetKernelInfo(release, version);
LOG_INFO(sLogger, ("ebpf kernel release", release) ("kernel version", version));
if (release.empty()) {
LOG_WARNING(sLogger, ("cannot find kernel release", ""));
mBTFSupport = false;
return;
}
if (version >= INT64_FLAG(kernel_min_version_for_ebpf)) {
mBTFSupport = true;
return;
}
if (version / 1000000 != KERNEL_VERSION_310) {
LOG_WARNING(sLogger,
("unsupported kernel version, will not start eBPF plugin ... version", version));
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) {
m310Support = true;
return;
} else {
LOG_WARNING(sLogger,
("unsupported os for 310 kernel, will not start eBPF plugin ...", "")
("os", os)("version", osVersion));
m310Support = false;
return;
}
}
LOG_WARNING(sLogger,
("not redhat release, will not start eBPF plugin ...", ""));
m310Support = false;
return;
}

bool eBPFServer::IsSupportedEnv(nami::PluginType type) {
return mEnvMgr.IsSupportedEnv(type);
}

void eBPFServer::Init() {
if (mInited) {
return;
}
mEnvMgr.InitEnvInfo();
if (!mEnvMgr.AbleToLoadDyLib()) {
return;
}
mInited = true;
mSourceManager = std::make_unique<SourceManager>();
mSourceManager->Init();
// ebpf config
Expand All @@ -49,7 +161,6 @@ void eBPFServer::Init() {
mNetworkSecureCB = std::make_unique<SecurityHandler>(nullptr, -1, 0);
mProcessSecureCB = std::make_unique<SecurityHandler>(nullptr, -1, 0);
mFileSecureCB = std::make_unique<SecurityHandler>(nullptr, -1, 0);
mInited = true;
}

void eBPFServer::Stop() {
Expand Down Expand Up @@ -79,7 +190,8 @@ bool eBPFServer::StartPluginInternal(const std::string& pipeline_name, uint32_t

std::string prev_pipeline_name = CheckLoadedPipelineName(type);
if (prev_pipeline_name.size() && prev_pipeline_name != pipeline_name) {
LOG_WARNING(sLogger, ("pipeline already loaded, plugin type", int(type))("prev pipeline", prev_pipeline_name)("curr pipeline", pipeline_name));
LOG_WARNING(sLogger, ("pipeline already loaded, plugin type", int(type))
("prev pipeline", prev_pipeline_name)("curr pipeline", pipeline_name));
return false;
}

Expand Down Expand Up @@ -107,14 +219,17 @@ bool eBPFServer::StartPluginInternal(const std::string& pipeline_name, uint32_t
nami::NetworkObserveConfig nconfig;
nami::ObserverNetworkOption* opts = std::get<nami::ObserverNetworkOption*>(options);
if (opts->mEnableMetric) {
nconfig.enable_metric_ = true;
nconfig.measure_cb_ = [this](auto events, auto ts) { return mMeterCB->handle(std::move(events), ts); };
mMeterCB->UpdateContext(ctx, ctx->GetProcessQueueKey(), plugin_index);
}
if (opts->mEnableSpan) {
nconfig.enable_span_ = true;
nconfig.span_cb_ = [this](auto events) { return mSpanCB->handle(std::move(events)); };
mSpanCB->UpdateContext(ctx, ctx->GetProcessQueueKey(), plugin_index);
}
if (opts->mEnableLog) {
nconfig.enable_event_ = true;
nconfig.event_cb_ = [this](auto events) { return mEventCB->handle(std::move(events)); };
mEventCB->UpdateContext(ctx, ctx->GetProcessQueueKey(), plugin_index);
}
Expand Down Expand Up @@ -167,16 +282,20 @@ bool eBPFServer::EnablePlugin(const std::string& pipeline_name, uint32_t plugin_
nami::PluginType type,
const PipelineContext* ctx,
const std::variant<SecurityOptions*, nami::ObserverNetworkOption*> options) {
Init();
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(type)) {
return true;
}
std::string prev_pipeline = CheckLoadedPipelineName(type);
if (prev_pipeline == pipeline_name) {
UpdatePipelineName(type, "");
}
else {
} else {
LOG_WARNING(sLogger, ("prev pipeline", prev_pipeline)("curr pipeline", pipeline_name));
return true;
}
Expand All @@ -198,6 +317,9 @@ void eBPFServer::UpdatePipelineName(nami::PluginType type, const std::string& na
}

bool eBPFServer::SuspendPlugin(const std::string& pipeline_name, nami::PluginType type) {
if (!IsSupportedEnv(type)) {
return false;
}
// mark plugin status is update
bool ret = mSourceManager->SuspendPlugin(type);
if (ret) UpdateCBContext(type, nullptr, -1, -1);
Expand Down
21 changes: 21 additions & 0 deletions core/ebpf/eBPFServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,22 @@
namespace logtail {
namespace ebpf {

class EnvManager {
public:
void InitEnvInfo();
bool IsSupportedEnv(nami::PluginType type);
bool AbleToLoadDyLib();
private:
volatile bool mInited = false;

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;
Expand All @@ -48,6 +64,7 @@ class eBPFServer : public InputRunner {
void Stop() override;

std::string CheckLoadedPipelineName(nami::PluginType type);

void UpdatePipelineName(nami::PluginType type, const std::string& name);

bool EnablePlugin(const std::string& pipeline_name, uint32_t plugin_index,
Expand All @@ -61,6 +78,8 @@ class eBPFServer : public InputRunner {

bool HasRegisteredPlugins() const override;

bool IsSupportedEnv(nami::PluginType type);

private:
bool StartPluginInternal(const std::string& pipeline_name, uint32_t plugin_index,
nami::PluginType type,
Expand All @@ -86,6 +105,8 @@ class eBPFServer : public InputRunner {
eBPFAdminConfig mAdminConfig;
volatile bool mInited = false;

EnvManager mEnvMgr;

#ifdef APSARA_UNIT_TEST_MAIN
friend class eBPFServerUnittest;
#endif
Expand Down
4 changes: 4 additions & 0 deletions core/plugin/input/InputFileSecurity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ namespace logtail {
const std::string InputFileSecurity::sName = "input_file_security";

bool InputFileSecurity::Init(const Json::Value& config, Json::Value& optionalGoPipeline) {
ebpf::eBPFServer::GetInstance()->Init();
if (!ebpf::eBPFServer::GetInstance()->IsSupportedEnv(nami::PluginType::FILE_SECURITY)) {
return false;
}
std::string prev_pipeline_name = ebpf::eBPFServer::GetInstance()->CheckLoadedPipelineName(nami::PluginType::FILE_SECURITY);
std::string pipeline_name = mContext->GetConfigName();
if (prev_pipeline_name.size() && prev_pipeline_name != pipeline_name) {
Expand Down
4 changes: 4 additions & 0 deletions core/plugin/input/InputNetworkObserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ namespace logtail {
const std::string InputNetworkObserver::sName = "input_network_observer";

bool InputNetworkObserver::Init(const Json::Value& config, Json::Value& optionalGoPipeline) {
ebpf::eBPFServer::GetInstance()->Init();
if (!ebpf::eBPFServer::GetInstance()->IsSupportedEnv(nami::PluginType::NETWORK_OBSERVE)) {
return false;
}
std::string prev_pipeline_name = ebpf::eBPFServer::GetInstance()->CheckLoadedPipelineName(nami::PluginType::NETWORK_OBSERVE);
std::string pipeline_name = mContext->GetConfigName();
if (prev_pipeline_name.size() && prev_pipeline_name != pipeline_name) {
Expand Down
4 changes: 4 additions & 0 deletions core/plugin/input/InputNetworkSecurity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ 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) {
ebpf::eBPFServer::GetInstance()->Init();
if (!ebpf::eBPFServer::GetInstance()->IsSupportedEnv(nami::PluginType::NETWORK_SECURITY)) {
return false;
}
std::string prev_pipeline_name = ebpf::eBPFServer::GetInstance()->CheckLoadedPipelineName(nami::PluginType::NETWORK_SECURITY);
std::string pipeline_name = mContext->GetConfigName();
if (prev_pipeline_name.size() && prev_pipeline_name != pipeline_name) {
Expand Down
4 changes: 4 additions & 0 deletions core/plugin/input/InputProcessSecurity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ namespace logtail {
const std::string InputProcessSecurity::sName = "input_process_security";

bool InputProcessSecurity::Init(const Json::Value& config, Json::Value& optionalGoPipeline) {
ebpf::eBPFServer::GetInstance()->Init();
if (!ebpf::eBPFServer::GetInstance()->IsSupportedEnv(nami::PluginType::PROCESS_SECURITY)) {
return false;
}
std::string prev_pipeline_name = ebpf::eBPFServer::GetInstance()->CheckLoadedPipelineName(nami::PluginType::PROCESS_SECURITY);
std::string pipeline_name = mContext->GetConfigName();
if (prev_pipeline_name.size() && prev_pipeline_name != pipeline_name) {
Expand Down
39 changes: 39 additions & 0 deletions core/unittest/ebpf/eBPFServerUnittest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ class eBPFServerUnittest : public testing::Test {

void TestInitAndStop();

void TestEnvManager();

protected:
void SetUp() override {
config_ = new eBPFAdminConfig;
Expand Down Expand Up @@ -790,6 +792,42 @@ void eBPFServerUnittest::TestInitAndStop() {
EXPECT_EQ(false, ret);
}

void eBPFServerUnittest::TestEnvManager() {
eBPFServer::GetInstance()->mEnvMgr.InitEnvInfo();

EXPECT_TRUE(eBPFServer::GetInstance()->mEnvMgr.mArchSupport);
// 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);
Expand All @@ -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)
}
}

Expand Down
Loading