From 51355e66be3eeec6ebe79faa88324c788e5a3829 Mon Sep 17 00:00:00 2001 From: fly_1997 Date: Wed, 27 Nov 2024 05:13:26 +0800 Subject: [PATCH 3/5] fix failed to connect to the sdk and command execution is stuck --- src/common/utils.cpp | 16 ++++ src/common/utils.h | 1 + .../collect/system/command/command_base.cpp | 48 +++++++++++- .../collect/system/command/command_base.h | 9 +++ .../system/command/command_collector.cpp | 9 ++- src/plugin/collect/system/kernel_config.cpp | 1 + src/plugin_mgr/config.cpp | 17 ----- src/plugin_mgr/config.h | 1 - src/plugin_mgr/message_manager.cpp | 76 +++++++++++++++++-- src/plugin_mgr/message_manager.h | 3 +- src/sdk/oe_client.cpp | 12 ++- 11 files changed, 160 insertions(+), 33 deletions(-) diff --git a/src/common/utils.cpp b/src/common/utils.cpp index 4e12a57..a300a6a 100644 --- a/src/common/utils.cpp +++ b/src/common/utils.cpp @@ -156,4 +156,20 @@ std::vector SplitString(const std::string &str, const std::string & } return tokens; } +bool CreateDir(const std::string &path) +{ + size_t pos = 0; + do { + pos = path.find_first_of("/", pos + 1); + std::string subPath = path.substr(0, pos); + struct stat buffer; + if (stat(subPath.c_str(), &buffer) == 0) { + continue; + } + if (mkdir(subPath.c_str(), S_IRWXU | S_IRWXG) != 0) { + return false; + } + } while (pos != std::string::npos); + return true; +} } diff --git a/src/common/utils.h b/src/common/utils.h index ba787fe..48b72bd 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -28,6 +28,7 @@ bool EndWith(const std::string &s, const std::string &ending); std::string Concat(const std::vector& strings, const std::string &split); // Separate "str" with the separator "split" std::vector SplitString(const std::string &str, const std::string &split); +bool CreateDir(const std::string &path); } #endif // !COMMON_UTILS_H \ No newline at end of file diff --git a/src/plugin/collect/system/command/command_base.cpp b/src/plugin/collect/system/command/command_base.cpp index d5a30dd..bf658b8 100644 --- a/src/plugin/collect/system/command/command_base.cpp +++ b/src/plugin/collect/system/command/command_base.cpp @@ -10,6 +10,45 @@ * See the Mulan PSL v2 for more details. ******************************************************************************/ #include "command_base.h" +#include +#include + +int PopenProcess::Pclose() +{ + if (fclose(stream) == EOF) { + return -1; + } + stream = nullptr; + if (kill(pid, SIGTERM) == -1) { + return -1; + } + return 0; +} + +void PopenProcess::Popen(const std::string &cmd) +{ + int pipeFd[2]; + if (pipe(pipeFd) == -1) { + return; + } + pid = fork(); + if (pid == -1) { + close(pipeFd[0]); + close(pipeFd[1]); + } else if (pid == 0) { + close(pipeFd[0]); + dup2(pipeFd[1], STDOUT_FILENO); + close(pipeFd[1]); + execl("/bin/bash", "bash", "-c", cmd.data(), nullptr); + _exit(1); + } + close(pipeFd[1]); + stream = fdopen(pipeFd[0], "r"); + if (!stream) { + close(pipeFd[0]); + return; + } +} CommandBase::CommandBase() { @@ -23,18 +62,19 @@ CommandBase::CommandBase() bool CommandBase::ValidateArgs(const oeaware::Topic& topic) { auto cmd = GetCommand(topic); - FILE *pipe = popen(cmd.c_str(), "r"); - if (!pipe) { + PopenProcess p; + p.Popen(cmd); + if (!p.stream) { return false; } char buffer[128]; bool isValid = false; - if (fgets(buffer, sizeof(buffer), pipe) != nullptr) { + if (fgets(buffer, sizeof(buffer), p.stream) != nullptr) { if (strstr(buffer, "Linux") != nullptr || strstr(buffer, "procs") != nullptr) { isValid = true; } } - pclose(pipe); + p.Pclose(); return isValid; } diff --git a/src/plugin/collect/system/command/command_base.h b/src/plugin/collect/system/command/command_base.h index eb75c49..a6d7627 100644 --- a/src/plugin/collect/system/command/command_base.h +++ b/src/plugin/collect/system/command/command_base.h @@ -44,4 +44,13 @@ public: void Close(); }; +class PopenProcess { +public: + int Pclose(); + void Popen(const std::string &cmd); + + FILE *stream; + pid_t pid; +}; + #endif diff --git a/src/plugin/collect/system/command/command_collector.cpp b/src/plugin/collect/system/command/command_collector.cpp index 6c54555..640a406 100644 --- a/src/plugin/collect/system/command/command_collector.cpp +++ b/src/plugin/collect/system/command/command_collector.cpp @@ -32,15 +32,16 @@ CommandCollector::CommandCollector(): oeaware::Interface() void CommandCollector::CollectThread(const oeaware::Topic &topic, CommandBase* collector) { std::string cmd = collector->GetCommand(topic); - FILE* pipe = popen(cmd.c_str(), "r"); - if (!pipe) { + PopenProcess p; + p.Popen(cmd); + if (!p.stream) { return; } char buffer[256]; - while (collector->isRunning && fgets(buffer, sizeof(buffer), pipe) != nullptr) { + while (collector->isRunning && fgets(buffer, sizeof(buffer), p.stream) != nullptr) { collector->ParseLine(std::string(buffer)); } - pclose(pipe); + p.Pclose(); collector->Close(); } diff --git a/src/plugin/collect/system/kernel_config.cpp b/src/plugin/collect/system/kernel_config.cpp index 63aafea..6bdfc8a 100644 --- a/src/plugin/collect/system/kernel_config.cpp +++ b/src/plugin/collect/system/kernel_config.cpp @@ -113,6 +113,7 @@ static bool IsSymlink(const std::string &path) } return S_ISLNK(st.st_mode); } + void KernelConfig::GetAllEth() { const std::string path = "/sys/class/net"; diff --git a/src/plugin_mgr/config.cpp b/src/plugin_mgr/config.cpp index 341880b..8cd1432 100644 --- a/src/plugin_mgr/config.cpp +++ b/src/plugin_mgr/config.cpp @@ -15,23 +15,6 @@ #include "default_path.h" namespace oeaware { -bool CreateDir(const std::string &path) -{ - size_t pos = 0; - do { - pos = path.find_first_of("/", pos + 1); - std::string subPath = path.substr(0, pos); - struct stat buffer; - if (stat(subPath.c_str(), &buffer) == 0) { - continue; - } - if (mkdir(subPath.c_str(), S_IRWXU | S_IRWXG) != 0) { - return false; - } - } while (pos != std::string::npos); - return true; -} - bool CheckPluginList(YAML::Node pluginListItem) { if (pluginListItem["name"].IsNull()) { diff --git a/src/plugin_mgr/config.h b/src/plugin_mgr/config.h index 640ab00..19e6d33 100644 --- a/src/plugin_mgr/config.h +++ b/src/plugin_mgr/config.h @@ -130,7 +130,6 @@ private: }; std::string GetPath(); -bool CreateDir(const std::string &path); } #endif diff --git a/src/plugin_mgr/message_manager.cpp b/src/plugin_mgr/message_manager.cpp index 1ffa4cc..bfa5b0c 100644 --- a/src/plugin_mgr/message_manager.cpp +++ b/src/plugin_mgr/message_manager.cpp @@ -11,6 +11,7 @@ ******************************************************************************/ #include "message_manager.h" #include +#include #include #include "default_path.h" #include "utils.h" @@ -41,15 +42,56 @@ int Epoll::EventWait(struct epoll_event *events, int maxEvents, int timeout) return epoll_wait(epfd, events, maxEvents, timeout); } +static std::vector GetUserFromGroup(const std::string &groupName) +{ + std::vector users; + std::ifstream file("/etc/group"); + if (!file.is_open()) { + return users; + } + std::string line; + size_t userPartIndex = 3; + while (std::getline(file, line)) { + std::vector parts = SplitString(line, ":"); + if (parts.size() > userPartIndex && parts[0] == groupName) { + std::vector userParts = SplitString(parts[userPartIndex], ","); + users.insert(users.end(), userParts.begin(), userParts.end()); + break; + } + } + file.close(); + return users; +} + +static int GetUid(const std::string &name) +{ + struct passwd pwd; + struct passwd *result; + char buf[1024]; + int res = getpwnam_r(name.c_str(), &pwd, buf, sizeof(buf), &result); + if (res != 0 || result == nullptr) { + return -1; + } + return pwd.pw_uid; +} + void TcpSocket::InitGroups() { std::vector groupNames{"oeaware", "root"}; + groups[0].emplace_back(0); for (auto &groupName : groupNames) { auto gid = GetGidByGroupName(groupName); if (gid < 0) { continue; } - groups.emplace_back(gid); + auto users = GetUserFromGroup(groupName); + for (auto &user : users) { + auto uid = GetUid(user); + if (uid < 0) { + continue; + } + groups[gid].emplace_back(uid); + } } } @@ -68,6 +110,11 @@ bool TcpSocket::StartListen() ERROR(logger, path << " chmod error!"); return false; } + std::string cmd = "setfacl -m g:oeaware:rw " + path; + auto ret = system(cmd.c_str()); + if (ret) { + WARN(logger, "failed to set the communication permission of the oeaware user group."); + } if (domainSocket->Listen() < 0) { ERROR(logger, "listen error!"); return false; @@ -136,7 +183,6 @@ static void GetEventResult(Message &msg, EventResultQueue sendMessage) } const int DISCONNECTED = -1; -const int DISCONNECTED_AND_UNSUBCRIBE = -2; void TcpMessageHandler::Init(EventQueue newRecvMessage, EventResultQueue newSendMessage, EventQueue newRecvData) { @@ -240,6 +286,23 @@ void TcpMessageHandler::Start() } } +bool TcpSocket::CheckFileGroups(const std::string &path) +{ + struct stat st; + if (lstat(path.c_str(), &st) < 0) { + return false; + } + for (auto &p : groups) { + bool ok = std::any_of(p.second.begin(), p.second.end(), [&](uid_t uid) { + return uid == st.st_uid; + }); + if (ok) { + return true; + } + } + return false; +} + void TcpSocket::SaveConnection() { struct sockaddr_un un; @@ -255,12 +318,12 @@ void TcpSocket::SaveConnection() memcpy_s(name, maxNameLength, un.sun_path, len); name[len] = 0; bool isSdk = false; - if (strcmp(name, DEFAULT_SDK_CONN_PATH.c_str()) == 0) { + if (len > 0) { isSdk = true; } // check permission - if (isSdk && !CheckFileGroups(DEFAULT_SDK_CONN_PATH, groups)) { - WARN(logger, "sdk permission error"); + if (isSdk && !CheckFileGroups(name)) { + WARN(logger, "sdk permission error, " << name); return; } if (!epoll->EventCtl(EPOLL_CTL_ADD, conn)) { @@ -274,6 +337,9 @@ void TcpSocket::SaveConnection() type |= CMD_CONN; } tcpMessageHandler.AddConn(conn, type); + if (isSdk) { + INFO(logger, "a sdk connection is established, " << name); + } DEBUG(logger, "client connected!"); } diff --git a/src/plugin_mgr/message_manager.h b/src/plugin_mgr/message_manager.h index 38f544d..3c67096 100644 --- a/src/plugin_mgr/message_manager.h +++ b/src/plugin_mgr/message_manager.h @@ -73,12 +73,13 @@ private: bool StartListen(); void SaveConnection(); void HandleEvents(struct epoll_event *events, int num); + bool CheckFileGroups(const std::string &path); private: log4cplus::Logger logger; std::unique_ptr domainSocket; std::unique_ptr epoll; TcpMessageHandler tcpMessageHandler; - std::vector groups; + std::unordered_map> groups; const int maxRequestNum = 20; const int maxNameLength = 108; }; diff --git a/src/sdk/oe_client.cpp b/src/sdk/oe_client.cpp index 9452a37..040433a 100644 --- a/src/sdk/oe_client.cpp +++ b/src/sdk/oe_client.cpp @@ -80,7 +80,17 @@ void Impl::HandleRecv() } int Impl::Init() { - domainSocket = std::make_shared(DEFAULT_SDK_CONN_PATH); + auto home = getenv("HOME"); + std::string homeDir; + if (home == nullptr) { + homeDir = "/var/run/oeAware"; + } else { + homeDir = home; + homeDir += "/.oeaware"; + } + + CreateDir(homeDir); + domainSocket = std::make_shared(homeDir + "/oeaware-sdk.sock"); domainSocket->SetRemotePath(DEFAULT_SERVER_LISTEN_PATH); resultQueue = std::make_shared>(); int sock = domainSocket->Socket(); -- 2.33.0