From 899b2f65ca0310b17e865d42782131164d9377c3 Mon Sep 17 00:00:00 2001 From: iritb Date: Sun, 29 Dec 2024 12:12:07 +0200 Subject: [PATCH 01/18] Add cgroup parsing to retrieve container ID from /proc/[pid]/cgroup --- ProcessInfo.cpp | 67 +++++++++++++++++++++++++++++++++++++++++++++++++ ProcessInfo.h | 3 +++ ProcessTree.cpp | 15 +++++++++++ ProcessTree.h | 1 + 4 files changed, 86 insertions(+) diff --git a/ProcessInfo.cpp b/ProcessInfo.cpp index d478a6b..a68f864 100644 --- a/ProcessInfo.cpp +++ b/ProcessInfo.cpp @@ -369,6 +369,64 @@ int ProcessInfo::read_and_parse_status(int pid) { return 0; } +int ProcessInfo::read_and_parse_cgroup(int pid) { + std::array path; + std::array data; + + snprintf(path.data(), path.size(), "/proc/%d/cgroup", pid); + + int fd = ::open(path.data(), O_RDONLY | O_CLOEXEC); + if (fd < 0) { + if (errno != ENOENT && errno != ESRCH) { + std::cerr << "Failed to open /proc/" << pid << "/cgroup: " << strerror(errno) << std::endl; + } + return -1; + } + + auto nr = ::read(fd, data.data(), data.size()); + if (nr <= 0) { + close(fd); + if (nr < 0 && errno != ENOENT && errno != ESRCH) { + std::cerr << "Failed to read /proc/" << pid << "/cgroup: " << strerror(errno) << std::endl; + } + return -1; + } + close(fd); + + char *ptr = data.data(); + char *end = ptr + nr; + + const char *containerd_prefix = "/containerd-"; + const size_t containerd_prefix_len = strlen(containerd_prefix); + const char *docker_prefix = "/docker/"; + const size_t docker_prefix_len = strlen(docker_prefix); + + while (ptr < end) { + char *line_end = strchr(ptr, '\n'); + if (line_end == nullptr) { + line_end = end; + } + + // Check for containerd format + char *containerd_pos = strstr(ptr, containerd_prefix); + if (containerd_pos != nullptr && containerd_pos < line_end) { + _container_id = std::string(containerd_pos + containerd_prefix_len, 12); // Extract the first 12 characters of the container ID + return 0; + } + + // Check for Docker format + char *docker_pos = strstr(ptr, docker_prefix); + if (docker_pos != nullptr && docker_pos < line_end) { + _container_id = std::string(docker_pos + docker_prefix_len, 12); // Extract the first 12 characters of the container ID + return 0; + } + + ptr = line_end + 1; + } + + return 1; +} + bool ProcessInfo::read(int pid) { std::array path; @@ -390,6 +448,14 @@ bool ProcessInfo::read(int pid) { return false; } + pret = read_and_parse_cgroup(pid); + if (pret != 0) { + if (pret > 0) { + Logger::Warn("Failed to parse /proc/%d/cgroup", pid); + } + return false; + } + auto exe_status = read_link(path.data(), _exe); if (exe_status < 0) { // EACCES (Permission denied) will be seen occasionally (probably due to racy nature of /proc iteration) @@ -471,6 +537,7 @@ void ProcessInfo::clear() { _cmdline.clear(); _cmdline_truncated = false; _starttime_str.clear(); + _container_id.clear(); } std::unique_ptr ProcessInfo::Open(int cmdline_size_limit) { diff --git a/ProcessInfo.h b/ProcessInfo.h index 9026115..77ab951 100644 --- a/ProcessInfo.h +++ b/ProcessInfo.h @@ -45,6 +45,7 @@ class ProcessInfo { inline int egid() { return _egid; } inline int sgid() { return _sgid; } inline int fsgid() { return _fsgid; } + inline std::string_view container_id() { return std::string_view(_container_id.data(), _container_id.size()); } inline std::string_view comm() { return std::string_view(_comm.data(), _comm_size); } inline std::string exe() { return _exe; } @@ -61,6 +62,7 @@ class ProcessInfo { int read_and_parse_stat(int pid); int read_and_parse_status(int pid); + int read_and_parse_cgroup(int pid); bool read(int pid); void clear(); @@ -89,6 +91,7 @@ class ProcessInfo { std::vector _cmdline; std::string _starttime_str; bool _cmdline_truncated; + std::string _container_id; }; #endif //AUOMS_PROCESS_INFO_H diff --git a/ProcessTree.cpp b/ProcessTree.cpp index 97a2e8a..407f1ac 100644 --- a/ProcessTree.cpp +++ b/ProcessTree.cpp @@ -427,6 +427,14 @@ std::shared_ptr ProcessTree::AddProcess(enum ProcessTreeSource _processes[pid] = process; } + // Call ReadProcEntry to ensure container ID is set if it's still empty + if (process->_containerid.empty()) { + auto p_temp = ReadProcEntry(pid); + if (p_temp) { + process->_containerid = p_temp->_cgroupContainerId; + } + } + return process; } @@ -497,6 +505,12 @@ std::shared_ptr ProcessTree::GetInfoForPid(int pid) struct Ancestor anc = {process->_ppid, parentproc->_exe}; process->_ancestors.emplace_back(anc); } + + // If container ID is still empty, set it to be the cgroup container ID + if (process->_containerid.empty()) { + process->_containerid = process->_cgroupContainerId; + } + _processes[pid] = process; ApplyFlags(process); } @@ -660,6 +674,7 @@ std::shared_ptr ProcessTree::ReadProcEntry(int pid) process->_gid = pinfo->gid(); process->_ppid = pinfo->ppid(); process->_exe = pinfo->exe(); + process->_cgroupContainerId = pinfo->container_id(); pinfo->format_cmdline(process->_cmdline); process->_containeridfromhostprocess = ExtractContainerId(process->_exe, process->_cmdline); return process; diff --git a/ProcessTree.h b/ProcessTree.h index 741725d..5b4275b 100644 --- a/ProcessTree.h +++ b/ProcessTree.h @@ -178,6 +178,7 @@ class ProcessTreeItem { std::string _exe; std::string _containerid; std::string _containeridfromhostprocess; + std::string _cgroupContainerId; std::string _cmdline; std::bitset _flags; bool _exited; From 13ea7dbbf68eb6979160bb5604c0faa69e376f69 Mon Sep 17 00:00:00 2001 From: iritb Date: Sun, 29 Dec 2024 18:03:16 +0200 Subject: [PATCH 02/18] Replace std::cerr with Logger::Warn for cgroup error handling --- ProcessInfo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ProcessInfo.cpp b/ProcessInfo.cpp index a68f864..2791737 100644 --- a/ProcessInfo.cpp +++ b/ProcessInfo.cpp @@ -378,7 +378,7 @@ int ProcessInfo::read_and_parse_cgroup(int pid) { int fd = ::open(path.data(), O_RDONLY | O_CLOEXEC); if (fd < 0) { if (errno != ENOENT && errno != ESRCH) { - std::cerr << "Failed to open /proc/" << pid << "/cgroup: " << strerror(errno) << std::endl; + Logger::Warn("Failed to open /proc/%d/cgroup: %s", pid, strerror(errno)); } return -1; } @@ -387,7 +387,7 @@ int ProcessInfo::read_and_parse_cgroup(int pid) { if (nr <= 0) { close(fd); if (nr < 0 && errno != ENOENT && errno != ESRCH) { - std::cerr << "Failed to read /proc/" << pid << "/cgroup: " << strerror(errno) << std::endl; + Logger::Warn("Failed to read /proc/%d/cgroup: %s", pid, strerror(errno)); } return -1; } From d561908e34f46f6d73479d91841cf6a7fabb039d Mon Sep 17 00:00:00 2001 From: iritb Date: Thu, 2 Jan 2025 15:33:54 +0200 Subject: [PATCH 03/18] Add support for reading container IDs from system.slice Docker format in cgroup parsing --- ProcessInfo.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ProcessInfo.cpp b/ProcessInfo.cpp index 2791737..7079348 100644 --- a/ProcessInfo.cpp +++ b/ProcessInfo.cpp @@ -400,6 +400,8 @@ int ProcessInfo::read_and_parse_cgroup(int pid) { const size_t containerd_prefix_len = strlen(containerd_prefix); const char *docker_prefix = "/docker/"; const size_t docker_prefix_len = strlen(docker_prefix); + const char *system_docker_prefix = "/system.slice/docker-"; + const size_t system_docker_prefix_len = strlen(system_docker_prefix); while (ptr < end) { char *line_end = strchr(ptr, '\n'); @@ -411,6 +413,7 @@ int ProcessInfo::read_and_parse_cgroup(int pid) { char *containerd_pos = strstr(ptr, containerd_prefix); if (containerd_pos != nullptr && containerd_pos < line_end) { _container_id = std::string(containerd_pos + containerd_prefix_len, 12); // Extract the first 12 characters of the container ID + Logger::Info("Read Container id (1) from cgroup for /proc/%d/cgroup: %s", pid, _container_id); return 0; } @@ -418,6 +421,15 @@ int ProcessInfo::read_and_parse_cgroup(int pid) { char *docker_pos = strstr(ptr, docker_prefix); if (docker_pos != nullptr && docker_pos < line_end) { _container_id = std::string(docker_pos + docker_prefix_len, 12); // Extract the first 12 characters of the container ID + Logger::Info("Read Container id (2) from cgroup for /proc/%d/cgroup: %s", pid, _container_id); + return 0; + } + + // Check for system.slice Docker format + char *system_docker_pos = strstr(ptr, system_docker_prefix); + if (system_docker_pos != nullptr && system_docker_pos < line_end) { + _container_id = std::string(system_docker_pos + system_docker_prefix_len, 12); // Extract the first 12 characters of the container ID + Logger::Info("Read Container id (3) from cgroup for /proc/%d/cgroup: %s", pid, _container_id); return 0; } From 0f9da62b7b2b79726268740e760ceec7438428c5 Mon Sep 17 00:00:00 2001 From: iritb Date: Thu, 2 Jan 2025 18:35:50 +0200 Subject: [PATCH 04/18] Add debug and info logging for cgroup parsing in ProcessInfo --- ProcessInfo.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ProcessInfo.cpp b/ProcessInfo.cpp index 7079348..a93bb2a 100644 --- a/ProcessInfo.cpp +++ b/ProcessInfo.cpp @@ -396,6 +396,8 @@ int ProcessInfo::read_and_parse_cgroup(int pid) { char *ptr = data.data(); char *end = ptr + nr; + Logger::Debug("Read /proc/%d/cgroup: %.*s", pid, nr, data.data()); + const char *containerd_prefix = "/containerd-"; const size_t containerd_prefix_len = strlen(containerd_prefix); const char *docker_prefix = "/docker/"; @@ -409,6 +411,8 @@ int ProcessInfo::read_and_parse_cgroup(int pid) { line_end = end; } + Logger::Info("Processing line: %.*s", static_cast(line_end - ptr), ptr); + // Check for containerd format char *containerd_pos = strstr(ptr, containerd_prefix); if (containerd_pos != nullptr && containerd_pos < line_end) { @@ -430,11 +434,14 @@ int ProcessInfo::read_and_parse_cgroup(int pid) { if (system_docker_pos != nullptr && system_docker_pos < line_end) { _container_id = std::string(system_docker_pos + system_docker_prefix_len, 12); // Extract the first 12 characters of the container ID Logger::Info("Read Container id (3) from cgroup for /proc/%d/cgroup: %s", pid, _container_id); + Logger::Warn("Read Container id (3) from cgroup for /proc/%d/cgroup: %s", pid, _container_id); return 0; } ptr = line_end + 1; } + + Logger::Warn("No container ID found in /proc/%d/cgroup", pid); return 1; } @@ -460,6 +467,8 @@ bool ProcessInfo::read(int pid) { return false; } + Logger::Info("Read cgroup for %d", pid); + Logger::Warn("Read cgroup for %d", pid); pret = read_and_parse_cgroup(pid); if (pret != 0) { if (pret > 0) { From b5f8dfd9a735a7a602182e7a9368c9cff47abb43 Mon Sep 17 00:00:00 2001 From: iritb Date: Thu, 2 Jan 2025 18:41:26 +0200 Subject: [PATCH 05/18] Fix container ID logging to use c_str() for proper string handling in cgroup parsing --- ProcessInfo.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ProcessInfo.cpp b/ProcessInfo.cpp index a93bb2a..56ad793 100644 --- a/ProcessInfo.cpp +++ b/ProcessInfo.cpp @@ -417,7 +417,7 @@ int ProcessInfo::read_and_parse_cgroup(int pid) { char *containerd_pos = strstr(ptr, containerd_prefix); if (containerd_pos != nullptr && containerd_pos < line_end) { _container_id = std::string(containerd_pos + containerd_prefix_len, 12); // Extract the first 12 characters of the container ID - Logger::Info("Read Container id (1) from cgroup for /proc/%d/cgroup: %s", pid, _container_id); + Logger::Info("Read Container id (1) from cgroup for /proc/%d/cgroup: %s", pid, _container_id.c_str()); return 0; } @@ -425,7 +425,7 @@ int ProcessInfo::read_and_parse_cgroup(int pid) { char *docker_pos = strstr(ptr, docker_prefix); if (docker_pos != nullptr && docker_pos < line_end) { _container_id = std::string(docker_pos + docker_prefix_len, 12); // Extract the first 12 characters of the container ID - Logger::Info("Read Container id (2) from cgroup for /proc/%d/cgroup: %s", pid, _container_id); + Logger::Info("Read Container id (2) from cgroup for /proc/%d/cgroup: %s", pid, _container_id.c_str()); return 0; } @@ -433,14 +433,14 @@ int ProcessInfo::read_and_parse_cgroup(int pid) { char *system_docker_pos = strstr(ptr, system_docker_prefix); if (system_docker_pos != nullptr && system_docker_pos < line_end) { _container_id = std::string(system_docker_pos + system_docker_prefix_len, 12); // Extract the first 12 characters of the container ID - Logger::Info("Read Container id (3) from cgroup for /proc/%d/cgroup: %s", pid, _container_id); - Logger::Warn("Read Container id (3) from cgroup for /proc/%d/cgroup: %s", pid, _container_id); + Logger::Info("Read Container id (3) from cgroup for /proc/%d/cgroup: %s", pid, _container_id.c_str()); + Logger::Warn("Read Container id (3) from cgroup for /proc/%d/cgroup: %s", pid, _container_id.c_str()); return 0; } ptr = line_end + 1; } - + Logger::Warn("No container ID found in /proc/%d/cgroup", pid); return 1; From e8e2369dae69959f2a0c1dd6566bf16b101194ea Mon Sep 17 00:00:00 2001 From: iritb Date: Thu, 2 Jan 2025 18:51:37 +0200 Subject: [PATCH 06/18] Remove debug logging for cgroup data read in ProcessInfo --- ProcessInfo.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/ProcessInfo.cpp b/ProcessInfo.cpp index 56ad793..2ec25fb 100644 --- a/ProcessInfo.cpp +++ b/ProcessInfo.cpp @@ -396,8 +396,6 @@ int ProcessInfo::read_and_parse_cgroup(int pid) { char *ptr = data.data(); char *end = ptr + nr; - Logger::Debug("Read /proc/%d/cgroup: %.*s", pid, nr, data.data()); - const char *containerd_prefix = "/containerd-"; const size_t containerd_prefix_len = strlen(containerd_prefix); const char *docker_prefix = "/docker/"; From 632cfbffd8f0fba733c6fb2d3973d91f3a9e9b1d Mon Sep 17 00:00:00 2001 From: iritb Date: Sat, 4 Jan 2025 11:35:49 +0200 Subject: [PATCH 07/18] logs --- ProcessInfo.cpp | 9 +++------ ProcessTree.cpp | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/ProcessInfo.cpp b/ProcessInfo.cpp index 2ec25fb..c0ee871 100644 --- a/ProcessInfo.cpp +++ b/ProcessInfo.cpp @@ -409,8 +409,6 @@ int ProcessInfo::read_and_parse_cgroup(int pid) { line_end = end; } - Logger::Info("Processing line: %.*s", static_cast(line_end - ptr), ptr); - // Check for containerd format char *containerd_pos = strstr(ptr, containerd_prefix); if (containerd_pos != nullptr && containerd_pos < line_end) { @@ -432,15 +430,12 @@ int ProcessInfo::read_and_parse_cgroup(int pid) { if (system_docker_pos != nullptr && system_docker_pos < line_end) { _container_id = std::string(system_docker_pos + system_docker_prefix_len, 12); // Extract the first 12 characters of the container ID Logger::Info("Read Container id (3) from cgroup for /proc/%d/cgroup: %s", pid, _container_id.c_str()); - Logger::Warn("Read Container id (3) from cgroup for /proc/%d/cgroup: %s", pid, _container_id.c_str()); return 0; } ptr = line_end + 1; } - Logger::Warn("No container ID found in /proc/%d/cgroup", pid); - return 1; } @@ -466,12 +461,14 @@ bool ProcessInfo::read(int pid) { } Logger::Info("Read cgroup for %d", pid); - Logger::Warn("Read cgroup for %d", pid); pret = read_and_parse_cgroup(pid); if (pret != 0) { if (pret > 0) { Logger::Warn("Failed to parse /proc/%d/cgroup", pid); } + else{ + Logger::Warn("Wrong cgroup format for /proc/%d/cgroup", pid); + } return false; } diff --git a/ProcessTree.cpp b/ProcessTree.cpp index 407f1ac..1765c50 100644 --- a/ProcessTree.cpp +++ b/ProcessTree.cpp @@ -335,6 +335,9 @@ std::shared_ptr ProcessTree::AddProcess(enum ProcessTreeSource std::shared_ptr process; std::string containerid = ExtractContainerId(exe, cmdline); + + Logger::Info("AddProcess: pid=%d containerId=%s cmdline=%s", pid, containerid.c_str(), cmdline.c_str()); + auto it = _processes.find(pid); if (it != _processes.end()) { process = it->second; @@ -346,6 +349,7 @@ std::shared_ptr ProcessTree::AddProcess(enum ProcessTreeSource process->_exe = exe; process->_cmdline = cmdline; process->_containeridfromhostprocess = containerid; + Logger::Info("1 irit _pid=%d, _containeridfromhostprocess=%s", process->_pid, process->_containeridfromhostprocess.c_str()); } if (ppid != process->_ppid) { auto it2 = _processes.find(process->_ppid); @@ -367,6 +371,9 @@ std::shared_ptr ProcessTree::AddProcess(enum ProcessTreeSource } else { process->_containerid = parentproc->_containerid; } + + Logger::Info("2 irit _pid=%d, _containerid=%s", process->_pid, process->_containerid.c_str()); + } process->_ancestors = parentproc->_ancestors; struct Ancestor anc = {ppid, parentproc->_exe}; @@ -394,6 +401,8 @@ std::shared_ptr ProcessTree::AddProcess(enum ProcessTreeSource } else { p->_containerid = process->_containerid; } + + Logger::Info("3 irit _pid=%d, _containerid=%s", process->_pid, process->_containerid.c_str()); } p->_ancestors = process->_ancestors; struct Ancestor anc = {pid, exe}; @@ -418,6 +427,8 @@ std::shared_ptr ProcessTree::AddProcess(enum ProcessTreeSource process->_containeridfromhostprocess = containerid; process->_containerid = parentproc->_containerid; } + + Logger::Info("4 irit _pid=%d, _containerid=%s", process->_pid, process->_containerid.c_str()); } process->_ancestors = parentproc->_ancestors; struct Ancestor anc = {ppid, parentproc->_exe}; @@ -433,6 +444,8 @@ std::shared_ptr ProcessTree::AddProcess(enum ProcessTreeSource if (p_temp) { process->_containerid = p_temp->_cgroupContainerId; } + + Logger::Info("5 irit _pid=%d, _containerid=%s", process->_pid, process->_containerid.c_str()); } return process; @@ -501,6 +514,8 @@ std::shared_ptr ProcessTree::GetInfoForPid(int pid) } else { process->_containerid = parentproc->_containerid; } + + Logger::Info("6 irit _pid=%d, _containerid=%s", process->_pid, process->_containerid.c_str()); process->_ancestors = parentproc->_ancestors; struct Ancestor anc = {process->_ppid, parentproc->_exe}; process->_ancestors.emplace_back(anc); @@ -562,6 +577,9 @@ void ProcessTree::PopulateTree() auto process = std::make_shared(ProcessTreeSource_procfs, pid, ppid, uid, gid, exe, cmdline); process->_containeridfromhostprocess = ExtractContainerId(exe, cmdline); _processes[pid] = process; + + Logger::Info("7 irit _pid=%d, _containeridfromhostprocess=%s", process->_pid, process->_containeridfromhostprocess.c_str()); + } for (auto& p : _processes) { @@ -596,6 +614,8 @@ void ProcessTree::PopulateTree() auto process = p.second; if( !(process->_containeridfromhostprocess).empty()) { SetContainerId(process, process->_containeridfromhostprocess); + + Logger::Info("Populate containerid 8 irit _pid=%d, _containeridfromhostprocess=%s", process->_pid, process->_containeridfromhostprocess.c_str()); } } } @@ -677,6 +697,9 @@ std::shared_ptr ProcessTree::ReadProcEntry(int pid) process->_cgroupContainerId = pinfo->container_id(); pinfo->format_cmdline(process->_cmdline); process->_containeridfromhostprocess = ExtractContainerId(process->_exe, process->_cmdline); + + Log::Info("ReadProcEntry: irit pid=%d _cgroupContainerId=%s _containeridfromhostprocess=%s", pid, process->_cgroupContainerId.c_str(), process->_containeridfromhostprocess.c_str()); + return process; } From 3191adf60bffef6e5e31b76e07e724c30aeb0db8 Mon Sep 17 00:00:00 2001 From: iritb Date: Sat, 4 Jan 2025 22:16:31 +0200 Subject: [PATCH 08/18] typo --- ProcessTree.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ProcessTree.cpp b/ProcessTree.cpp index 1765c50..28fc46a 100644 --- a/ProcessTree.cpp +++ b/ProcessTree.cpp @@ -698,7 +698,7 @@ std::shared_ptr ProcessTree::ReadProcEntry(int pid) pinfo->format_cmdline(process->_cmdline); process->_containeridfromhostprocess = ExtractContainerId(process->_exe, process->_cmdline); - Log::Info("ReadProcEntry: irit pid=%d _cgroupContainerId=%s _containeridfromhostprocess=%s", pid, process->_cgroupContainerId.c_str(), process->_containeridfromhostprocess.c_str()); + Logger::Info("ReadProcEntry: irit pid=%d _cgroupContainerId=%s _containeridfromhostprocess=%s", pid, process->_cgroupContainerId.c_str(), process->_containeridfromhostprocess.c_str()); return process; } From 400690c95cd01016d3554ed9a20c1b4ada614804 Mon Sep 17 00:00:00 2001 From: iritb Date: Sun, 5 Jan 2025 13:35:20 +0200 Subject: [PATCH 09/18] Update logging messages in ProcessTree and RawEventProcessor to include 'IB' prefix for better traceability --- ProcessTree.cpp | 24 ++++++++++++++---------- RawEventProcessor.cpp | 2 ++ auoms.cpp | 2 +- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/ProcessTree.cpp b/ProcessTree.cpp index 28fc46a..55fefcf 100644 --- a/ProcessTree.cpp +++ b/ProcessTree.cpp @@ -336,7 +336,7 @@ std::shared_ptr ProcessTree::AddProcess(enum ProcessTreeSource std::string containerid = ExtractContainerId(exe, cmdline); - Logger::Info("AddProcess: pid=%d containerId=%s cmdline=%s", pid, containerid.c_str(), cmdline.c_str()); + Logger::Info("IB AddProcess: pid=%d containerId=%s cmdline=%s", pid, containerid.c_str(), cmdline.c_str()); auto it = _processes.find(pid); if (it != _processes.end()) { @@ -349,7 +349,7 @@ std::shared_ptr ProcessTree::AddProcess(enum ProcessTreeSource process->_exe = exe; process->_cmdline = cmdline; process->_containeridfromhostprocess = containerid; - Logger::Info("1 irit _pid=%d, _containeridfromhostprocess=%s", process->_pid, process->_containeridfromhostprocess.c_str()); + Logger::Info("1 IB _pid=%d, _containeridfromhostprocess=%s", process->_pid, process->_containeridfromhostprocess.c_str()); } if (ppid != process->_ppid) { auto it2 = _processes.find(process->_ppid); @@ -372,7 +372,7 @@ std::shared_ptr ProcessTree::AddProcess(enum ProcessTreeSource process->_containerid = parentproc->_containerid; } - Logger::Info("2 irit _pid=%d, _containerid=%s", process->_pid, process->_containerid.c_str()); + Logger::Info("2 IB _pid=%d, _containerid=%s", process->_pid, process->_containerid.c_str()); } process->_ancestors = parentproc->_ancestors; @@ -402,7 +402,7 @@ std::shared_ptr ProcessTree::AddProcess(enum ProcessTreeSource p->_containerid = process->_containerid; } - Logger::Info("3 irit _pid=%d, _containerid=%s", process->_pid, process->_containerid.c_str()); + Logger::Info("3 IB _pid=%d, _containerid=%s", process->_pid, process->_containerid.c_str()); } p->_ancestors = process->_ancestors; struct Ancestor anc = {pid, exe}; @@ -428,7 +428,7 @@ std::shared_ptr ProcessTree::AddProcess(enum ProcessTreeSource process->_containerid = parentproc->_containerid; } - Logger::Info("4 irit _pid=%d, _containerid=%s", process->_pid, process->_containerid.c_str()); + Logger::Info("4 IB _pid=%d, _containerid=%s", process->_pid, process->_containerid.c_str()); } process->_ancestors = parentproc->_ancestors; struct Ancestor anc = {ppid, parentproc->_exe}; @@ -445,7 +445,7 @@ std::shared_ptr ProcessTree::AddProcess(enum ProcessTreeSource process->_containerid = p_temp->_cgroupContainerId; } - Logger::Info("5 irit _pid=%d, _containerid=%s", process->_pid, process->_containerid.c_str()); + Logger::Info("5 IB _pid=%d, _containerid=%s", process->_pid, process->_containerid.c_str()); } return process; @@ -515,7 +515,7 @@ std::shared_ptr ProcessTree::GetInfoForPid(int pid) process->_containerid = parentproc->_containerid; } - Logger::Info("6 irit _pid=%d, _containerid=%s", process->_pid, process->_containerid.c_str()); + Logger::Info("6 IB _pid=%d, _containerid=%s", process->_pid, process->_containerid.c_str()); process->_ancestors = parentproc->_ancestors; struct Ancestor anc = {process->_ppid, parentproc->_exe}; process->_ancestors.emplace_back(anc); @@ -578,7 +578,7 @@ void ProcessTree::PopulateTree() process->_containeridfromhostprocess = ExtractContainerId(exe, cmdline); _processes[pid] = process; - Logger::Info("7 irit _pid=%d, _containeridfromhostprocess=%s", process->_pid, process->_containeridfromhostprocess.c_str()); + Logger::Info("7 IB _pid=%d, _containeridfromhostprocess=%s", process->_pid, process->_containeridfromhostprocess.c_str()); } @@ -615,7 +615,7 @@ void ProcessTree::PopulateTree() if( !(process->_containeridfromhostprocess).empty()) { SetContainerId(process, process->_containeridfromhostprocess); - Logger::Info("Populate containerid 8 irit _pid=%d, _containeridfromhostprocess=%s", process->_pid, process->_containeridfromhostprocess.c_str()); + Logger::Info("Populate containerid 8 IB _pid=%d, _containeridfromhostprocess=%s", process->_pid, process->_containeridfromhostprocess.c_str()); } } } @@ -685,11 +685,15 @@ std::shared_ptr ProcessTree::ReadProcEntry(int pid) { std::shared_ptr process = std::make_shared(ProcessTreeSource_procfs, pid); + Logger::Info("ReadProcEntry: IB pid=%d Before OpenPid", pid); + auto pinfo = ProcessInfo::OpenPid(pid, CMDLINE_SIZE_LIMIT); if (!pinfo) { return nullptr; } + Logger::Info("ReadProcEntry: IB pid=%d After OpenPid", pid); + process->_uid = pinfo->uid(); process->_gid = pinfo->gid(); process->_ppid = pinfo->ppid(); @@ -698,7 +702,7 @@ std::shared_ptr ProcessTree::ReadProcEntry(int pid) pinfo->format_cmdline(process->_cmdline); process->_containeridfromhostprocess = ExtractContainerId(process->_exe, process->_cmdline); - Logger::Info("ReadProcEntry: irit pid=%d _cgroupContainerId=%s _containeridfromhostprocess=%s", pid, process->_cgroupContainerId.c_str(), process->_containeridfromhostprocess.c_str()); + Logger::Info("ReadProcEntry: IB pid=%d _cgroupContainerId=%s _containeridfromhostprocess=%s", pid, process->_cgroupContainerId.c_str(), process->_containeridfromhostprocess.c_str()); return process; } diff --git a/RawEventProcessor.cpp b/RawEventProcessor.cpp index 95c81c8..227d9ce 100644 --- a/RawEventProcessor.cpp +++ b/RawEventProcessor.cpp @@ -701,6 +701,8 @@ bool RawEventProcessor::process_syscall_event(const Event& event) { std::string containerid; + Logger::Info("IB Processing syscall event: syscall=%s pid=%d ppid=%d uid=%d gid=%d exe=%s", _syscall.c_str(), _pid, _ppid, uid, gid, exe.c_str()); + if (_processTree) { if (!_syscall.empty() && starts_with(_syscall, "execve")) { if (!exe.empty() && exe.front() == '"' && exe.back() == '"') { diff --git a/auoms.cpp b/auoms.cpp index c704954..62b0528 100644 --- a/auoms.cpp +++ b/auoms.cpp @@ -273,7 +273,7 @@ int main(int argc, char**argv) { virt_limit = config.GetUint64("virt_limit"); } - bool use_syslog = true; + bool use_syslog = false; if (config.HasKey("use_syslog")) { use_syslog = config.GetBool("use_syslog"); } From 436ceef89246fa55d922bae9a1bdfbb878f879be Mon Sep 17 00:00:00 2001 From: iritb Date: Sun, 5 Jan 2025 16:32:52 +0200 Subject: [PATCH 10/18] Remove unnecessary logging statements in ProcessInfo and ProcessTree for cleaner output --- ProcessInfo.cpp | 4 ---- ProcessTree.cpp | 26 +------------------------- RawEventProcessor.cpp | 2 -- auoms.cpp | 2 +- 4 files changed, 2 insertions(+), 32 deletions(-) diff --git a/ProcessInfo.cpp b/ProcessInfo.cpp index c0ee871..8ca3684 100644 --- a/ProcessInfo.cpp +++ b/ProcessInfo.cpp @@ -413,7 +413,6 @@ int ProcessInfo::read_and_parse_cgroup(int pid) { char *containerd_pos = strstr(ptr, containerd_prefix); if (containerd_pos != nullptr && containerd_pos < line_end) { _container_id = std::string(containerd_pos + containerd_prefix_len, 12); // Extract the first 12 characters of the container ID - Logger::Info("Read Container id (1) from cgroup for /proc/%d/cgroup: %s", pid, _container_id.c_str()); return 0; } @@ -421,7 +420,6 @@ int ProcessInfo::read_and_parse_cgroup(int pid) { char *docker_pos = strstr(ptr, docker_prefix); if (docker_pos != nullptr && docker_pos < line_end) { _container_id = std::string(docker_pos + docker_prefix_len, 12); // Extract the first 12 characters of the container ID - Logger::Info("Read Container id (2) from cgroup for /proc/%d/cgroup: %s", pid, _container_id.c_str()); return 0; } @@ -429,7 +427,6 @@ int ProcessInfo::read_and_parse_cgroup(int pid) { char *system_docker_pos = strstr(ptr, system_docker_prefix); if (system_docker_pos != nullptr && system_docker_pos < line_end) { _container_id = std::string(system_docker_pos + system_docker_prefix_len, 12); // Extract the first 12 characters of the container ID - Logger::Info("Read Container id (3) from cgroup for /proc/%d/cgroup: %s", pid, _container_id.c_str()); return 0; } @@ -460,7 +457,6 @@ bool ProcessInfo::read(int pid) { return false; } - Logger::Info("Read cgroup for %d", pid); pret = read_and_parse_cgroup(pid); if (pret != 0) { if (pret > 0) { diff --git a/ProcessTree.cpp b/ProcessTree.cpp index 55fefcf..e82538f 100644 --- a/ProcessTree.cpp +++ b/ProcessTree.cpp @@ -334,9 +334,7 @@ std::shared_ptr ProcessTree::AddProcess(enum ProcessTreeSource std::unique_lock process_write_lock(_process_write_mutex); std::shared_ptr process; - std::string containerid = ExtractContainerId(exe, cmdline); - - Logger::Info("IB AddProcess: pid=%d containerId=%s cmdline=%s", pid, containerid.c_str(), cmdline.c_str()); + std::string containerid = ExtractContainerId(exe, cmdline); auto it = _processes.find(pid); if (it != _processes.end()) { @@ -349,7 +347,6 @@ std::shared_ptr ProcessTree::AddProcess(enum ProcessTreeSource process->_exe = exe; process->_cmdline = cmdline; process->_containeridfromhostprocess = containerid; - Logger::Info("1 IB _pid=%d, _containeridfromhostprocess=%s", process->_pid, process->_containeridfromhostprocess.c_str()); } if (ppid != process->_ppid) { auto it2 = _processes.find(process->_ppid); @@ -371,9 +368,6 @@ std::shared_ptr ProcessTree::AddProcess(enum ProcessTreeSource } else { process->_containerid = parentproc->_containerid; } - - Logger::Info("2 IB _pid=%d, _containerid=%s", process->_pid, process->_containerid.c_str()); - } process->_ancestors = parentproc->_ancestors; struct Ancestor anc = {ppid, parentproc->_exe}; @@ -401,8 +395,6 @@ std::shared_ptr ProcessTree::AddProcess(enum ProcessTreeSource } else { p->_containerid = process->_containerid; } - - Logger::Info("3 IB _pid=%d, _containerid=%s", process->_pid, process->_containerid.c_str()); } p->_ancestors = process->_ancestors; struct Ancestor anc = {pid, exe}; @@ -427,8 +419,6 @@ std::shared_ptr ProcessTree::AddProcess(enum ProcessTreeSource process->_containeridfromhostprocess = containerid; process->_containerid = parentproc->_containerid; } - - Logger::Info("4 IB _pid=%d, _containerid=%s", process->_pid, process->_containerid.c_str()); } process->_ancestors = parentproc->_ancestors; struct Ancestor anc = {ppid, parentproc->_exe}; @@ -444,8 +434,6 @@ std::shared_ptr ProcessTree::AddProcess(enum ProcessTreeSource if (p_temp) { process->_containerid = p_temp->_cgroupContainerId; } - - Logger::Info("5 IB _pid=%d, _containerid=%s", process->_pid, process->_containerid.c_str()); } return process; @@ -515,7 +503,6 @@ std::shared_ptr ProcessTree::GetInfoForPid(int pid) process->_containerid = parentproc->_containerid; } - Logger::Info("6 IB _pid=%d, _containerid=%s", process->_pid, process->_containerid.c_str()); process->_ancestors = parentproc->_ancestors; struct Ancestor anc = {process->_ppid, parentproc->_exe}; process->_ancestors.emplace_back(anc); @@ -577,9 +564,6 @@ void ProcessTree::PopulateTree() auto process = std::make_shared(ProcessTreeSource_procfs, pid, ppid, uid, gid, exe, cmdline); process->_containeridfromhostprocess = ExtractContainerId(exe, cmdline); _processes[pid] = process; - - Logger::Info("7 IB _pid=%d, _containeridfromhostprocess=%s", process->_pid, process->_containeridfromhostprocess.c_str()); - } for (auto& p : _processes) { @@ -614,8 +598,6 @@ void ProcessTree::PopulateTree() auto process = p.second; if( !(process->_containeridfromhostprocess).empty()) { SetContainerId(process, process->_containeridfromhostprocess); - - Logger::Info("Populate containerid 8 IB _pid=%d, _containeridfromhostprocess=%s", process->_pid, process->_containeridfromhostprocess.c_str()); } } } @@ -685,15 +667,11 @@ std::shared_ptr ProcessTree::ReadProcEntry(int pid) { std::shared_ptr process = std::make_shared(ProcessTreeSource_procfs, pid); - Logger::Info("ReadProcEntry: IB pid=%d Before OpenPid", pid); - auto pinfo = ProcessInfo::OpenPid(pid, CMDLINE_SIZE_LIMIT); if (!pinfo) { return nullptr; } - Logger::Info("ReadProcEntry: IB pid=%d After OpenPid", pid); - process->_uid = pinfo->uid(); process->_gid = pinfo->gid(); process->_ppid = pinfo->ppid(); @@ -702,8 +680,6 @@ std::shared_ptr ProcessTree::ReadProcEntry(int pid) pinfo->format_cmdline(process->_cmdline); process->_containeridfromhostprocess = ExtractContainerId(process->_exe, process->_cmdline); - Logger::Info("ReadProcEntry: IB pid=%d _cgroupContainerId=%s _containeridfromhostprocess=%s", pid, process->_cgroupContainerId.c_str(), process->_containeridfromhostprocess.c_str()); - return process; } diff --git a/RawEventProcessor.cpp b/RawEventProcessor.cpp index 227d9ce..95c81c8 100644 --- a/RawEventProcessor.cpp +++ b/RawEventProcessor.cpp @@ -701,8 +701,6 @@ bool RawEventProcessor::process_syscall_event(const Event& event) { std::string containerid; - Logger::Info("IB Processing syscall event: syscall=%s pid=%d ppid=%d uid=%d gid=%d exe=%s", _syscall.c_str(), _pid, _ppid, uid, gid, exe.c_str()); - if (_processTree) { if (!_syscall.empty() && starts_with(_syscall, "execve")) { if (!exe.empty() && exe.front() == '"' && exe.back() == '"') { diff --git a/auoms.cpp b/auoms.cpp index 62b0528..c704954 100644 --- a/auoms.cpp +++ b/auoms.cpp @@ -273,7 +273,7 @@ int main(int argc, char**argv) { virt_limit = config.GetUint64("virt_limit"); } - bool use_syslog = false; + bool use_syslog = true; if (config.HasKey("use_syslog")) { use_syslog = config.GetBool("use_syslog"); } From b1bdd3dda5f775669a8c7a788283a8da3f7483bd Mon Sep 17 00:00:00 2001 From: iritb Date: Sun, 5 Jan 2025 16:42:51 +0200 Subject: [PATCH 11/18] Clean up whitespace in ProcessTree.cpp for improved code readability --- ProcessTree.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ProcessTree.cpp b/ProcessTree.cpp index e82538f..7774b42 100644 --- a/ProcessTree.cpp +++ b/ProcessTree.cpp @@ -334,7 +334,7 @@ std::shared_ptr ProcessTree::AddProcess(enum ProcessTreeSource std::unique_lock process_write_lock(_process_write_mutex); std::shared_ptr process; - std::string containerid = ExtractContainerId(exe, cmdline); + std::string containerid = ExtractContainerId(exe, cmdline); auto it = _processes.find(pid); if (it != _processes.end()) { @@ -502,7 +502,6 @@ std::shared_ptr ProcessTree::GetInfoForPid(int pid) } else { process->_containerid = parentproc->_containerid; } - process->_ancestors = parentproc->_ancestors; struct Ancestor anc = {process->_ppid, parentproc->_exe}; process->_ancestors.emplace_back(anc); @@ -679,7 +678,6 @@ std::shared_ptr ProcessTree::ReadProcEntry(int pid) process->_cgroupContainerId = pinfo->container_id(); pinfo->format_cmdline(process->_cmdline); process->_containeridfromhostprocess = ExtractContainerId(process->_exe, process->_cmdline); - return process; } From a0c74ee29ff5c77038854e28ad9f034a42429643 Mon Sep 17 00:00:00 2001 From: iritb Date: Tue, 7 Jan 2025 13:25:10 +0200 Subject: [PATCH 12/18] Refactor ProcessInfo to extract container ID parsing logic into a separate method and add unit tests for various formats --- CMakeLists.txt | 1 + ProcessInfo.cpp | 82 ++++++++++++++++++++++++-------------------- ProcessInfoTests.cpp | 46 +++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 38 deletions(-) create mode 100644 ProcessInfoTests.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ea85308..dac6dae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -465,6 +465,7 @@ add_test(EventProcessor ${CMAKE_BINARY_DIR}/EventProcessorTests --log_sink=Event add_executable(ProcessTreeTests auoms_version.h ProcessTreeTests.cpp + ProcessInfoTests.cpp Event.cpp Signals.cpp Logger.cpp diff --git a/ProcessInfo.cpp b/ProcessInfo.cpp index 8ca3684..30f3bb1 100644 --- a/ProcessInfo.cpp +++ b/ProcessInfo.cpp @@ -369,32 +369,9 @@ int ProcessInfo::read_and_parse_status(int pid) { return 0; } -int ProcessInfo::read_and_parse_cgroup(int pid) { - std::array path; - std::array data; - - snprintf(path.data(), path.size(), "/proc/%d/cgroup", pid); - - int fd = ::open(path.data(), O_RDONLY | O_CLOEXEC); - if (fd < 0) { - if (errno != ENOENT && errno != ESRCH) { - Logger::Warn("Failed to open /proc/%d/cgroup: %s", pid, strerror(errno)); - } - return -1; - } - - auto nr = ::read(fd, data.data(), data.size()); - if (nr <= 0) { - close(fd); - if (nr < 0 && errno != ENOENT && errno != ESRCH) { - Logger::Warn("Failed to read /proc/%d/cgroup: %s", pid, strerror(errno)); - } - return -1; - } - close(fd); - - char *ptr = data.data(); - char *end = ptr + nr; +int ProcessInfo::ExtractCGroupContainerId(const std::string& content) { + const char* ptr = content.c_str(); + const char* line_end = nullptr; const char *containerd_prefix = "/containerd-"; const size_t containerd_prefix_len = strlen(containerd_prefix); @@ -403,31 +380,32 @@ int ProcessInfo::read_and_parse_cgroup(int pid) { const char *system_docker_prefix = "/system.slice/docker-"; const size_t system_docker_prefix_len = strlen(system_docker_prefix); - while (ptr < end) { - char *line_end = strchr(ptr, '\n'); - if (line_end == nullptr) { - line_end = end; - } - + while ((line_end = strchr(ptr, '\n')) != nullptr) { // Check for containerd format char *containerd_pos = strstr(ptr, containerd_prefix); if (containerd_pos != nullptr && containerd_pos < line_end) { - _container_id = std::string(containerd_pos + containerd_prefix_len, 12); // Extract the first 12 characters of the container ID - return 0; + if (containerd_pos + containerd_prefix_len + 12 <= line_end) { + _container_id = std::string(containerd_pos + containerd_prefix_len, 12); // Extract the first 12 characters of the container ID + return 0; + } } // Check for Docker format char *docker_pos = strstr(ptr, docker_prefix); if (docker_pos != nullptr && docker_pos < line_end) { - _container_id = std::string(docker_pos + docker_prefix_len, 12); // Extract the first 12 characters of the container ID - return 0; + if (docker_pos + docker_prefix_len + 12 <= line_end) { + _container_id = std::string(docker_pos + docker_prefix_len, 12); // Extract the first 12 characters of the container ID + return 0; + } } // Check for system.slice Docker format char *system_docker_pos = strstr(ptr, system_docker_prefix); if (system_docker_pos != nullptr && system_docker_pos < line_end) { - _container_id = std::string(system_docker_pos + system_docker_prefix_len, 12); // Extract the first 12 characters of the container ID - return 0; + if (system_docker_pos + system_docker_prefix_len + 12 <= line_end) { + _container_id = std::string(system_docker_pos + system_docker_prefix_len, 12); // Extract the first 12 characters of the container ID + return 0; + } } ptr = line_end + 1; @@ -436,6 +414,34 @@ int ProcessInfo::read_and_parse_cgroup(int pid) { return 1; } +int ProcessInfo::read_and_parse_cgroup(int pid) { + std::array path; + std::array data; + + snprintf(path.data(), path.size(), "/proc/%d/cgroup", pid); + + int fd = ::open(path.data(), O_RDONLY | O_CLOEXEC); + if (fd < 0) { + if (errno != ENOENT && errno != ESRCH) { + Logger::Warn("Failed to open /proc/%d/cgroup: %s", pid, strerror(errno)); + } + return -1; + } + + auto nr = ::read(fd, data.data(), data.size()); + if (nr <= 0) { + close(fd); + if (nr < 0 && errno != ENOENT && errno != ESRCH) { + Logger::Warn("Failed to read /proc/%d/cgroup: %s", pid, strerror(errno)); + } + return -1; + } + close(fd); + + std::string content(data.data(), nr); + return ExtractCGroupContainerId(content); +} + bool ProcessInfo::read(int pid) { std::array path; diff --git a/ProcessInfoTests.cpp b/ProcessInfoTests.cpp new file mode 100644 index 0000000..45ceb61 --- /dev/null +++ b/ProcessInfoTests.cpp @@ -0,0 +1,46 @@ +/* + microsoft-oms-auditd-plugin + + Copyright (c) Microsoft Corporation + + All rights reserved. + + MIT License + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#define BOOST_TEST_MODULE ProcessInfoTests +#include + +#include "ProcessInfo.h" +#include "Logger.h" +#include "StringUtils.h" +#include + +BOOST_AUTO_TEST_CASE(container_id_extraction_test) { + ProcessInfo processInfo; + + // Test containerd format + std::string containerd_line = "some text /containerd-ebe83cd204c5 more text\n"; + BOOST_CHECK_EQUAL(processInfo.ExtractCGroupContainerId(containerd_line), 0); + BOOST_CHECK_EQUAL(processInfo.GetContainerId(), "ebe83cd204c5"); + + // Test Docker format + std::string docker_line = "some text /docker/ebe83cd204c5 more text\n"; + BOOST_CHECK_EQUAL(processInfo.ExtractCGroupContainerId(docker_line), 0); + BOOST_CHECK_EQUAL(processInfo.GetContainerId(), "ebe83cd204c5"); + + // Test system.slice Docker format + std::string system_docker_line = "some text /system.slice/docker-ebe83cd204c5 more text\n"; + BOOST_CHECK_EQUAL(processInfo.ExtractCGroupContainerId(system_docker_line), 0); + BOOST_CHECK_EQUAL(processInfo.GetContainerId(), "ebe83cd204c5"); + + // Test invalid format + std::string invalid_line = "some text without container id\n"; + BOOST_CHECK_NE(processInfo.ExtractCGroupContainerId(invalid_line), 0); +} \ No newline at end of file From 9ffe10802ae6d1ce19333a48232c6cea0e3c8465 Mon Sep 17 00:00:00 2001 From: iritb Date: Tue, 7 Jan 2025 15:12:35 +0200 Subject: [PATCH 13/18] Add ExtractCGroupContainerId method to ProcessInfo and enhance unit tests for container ID extraction --- ProcessInfo.h | 7 +++++++ ProcessInfoTests.cpp | 27 +++++++++++++++++++-------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/ProcessInfo.h b/ProcessInfo.h index 77ab951..3d72c41 100644 --- a/ProcessInfo.h +++ b/ProcessInfo.h @@ -56,6 +56,10 @@ class ProcessInfo { std::string starttime(); inline bool is_cmdline_truncated() { return _cmdline_truncated; } + +protected: + int ExtractCGroupContainerId(const std::string& content); + private: explicit ProcessInfo(void* dp, int cmdline_size_limit); @@ -92,6 +96,9 @@ class ProcessInfo { std::string _starttime_str; bool _cmdline_truncated; std::string _container_id; + + // Declare the test class as a friend + friend class ProcessInfoTests; }; #endif //AUOMS_PROCESS_INFO_H diff --git a/ProcessInfoTests.cpp b/ProcessInfoTests.cpp index 45ceb61..5019059 100644 --- a/ProcessInfoTests.cpp +++ b/ProcessInfoTests.cpp @@ -22,25 +22,36 @@ #include "StringUtils.h" #include +class ProcessInfoTests { +public: + static int ExtractCGroupContainerId(ProcessInfo& processInfo, const std::string& content) { + return processInfo.ExtractCGroupContainerId(content); + } +}; + BOOST_AUTO_TEST_CASE(container_id_extraction_test) { - ProcessInfo processInfo; + // Create an instance of ProcessInfo using the Open method + auto processInfo = ProcessInfo::Open(0); + + // Ensure the instance is valid + BOOST_REQUIRE(processInfo != nullptr); // Test containerd format std::string containerd_line = "some text /containerd-ebe83cd204c5 more text\n"; - BOOST_CHECK_EQUAL(processInfo.ExtractCGroupContainerId(containerd_line), 0); - BOOST_CHECK_EQUAL(processInfo.GetContainerId(), "ebe83cd204c5"); + BOOST_CHECK_EQUAL(ProcessInfoTests::ExtractCGroupContainerId(*processInfo, containerd_line), 0); + BOOST_CHECK_EQUAL(processInfo.container_id(), "ebe83cd204c5"); // Test Docker format std::string docker_line = "some text /docker/ebe83cd204c5 more text\n"; - BOOST_CHECK_EQUAL(processInfo.ExtractCGroupContainerId(docker_line), 0); - BOOST_CHECK_EQUAL(processInfo.GetContainerId(), "ebe83cd204c5"); + BOOST_CHECK_EQUAL(ProcessInfoTests::ExtractCGroupContainerId(*processInfo, docker_line), 0); + BOOST_CHECK_EQUAL(processInfo.container_id(), "ebe83cd204c5"); // Test system.slice Docker format std::string system_docker_line = "some text /system.slice/docker-ebe83cd204c5 more text\n"; - BOOST_CHECK_EQUAL(processInfo.ExtractCGroupContainerId(system_docker_line), 0); - BOOST_CHECK_EQUAL(processInfo.GetContainerId(), "ebe83cd204c5"); + BOOST_CHECK_EQUAL(ProcessInfoTests::ExtractCGroupContainerId(*processInfo, system_docker_line), 0); + BOOST_CHECK_EQUAL(processInfo.container_id(), "ebe83cd204c5"); // Test invalid format std::string invalid_line = "some text without container id\n"; - BOOST_CHECK_NE(processInfo.ExtractCGroupContainerId(invalid_line), 0); + BOOST_CHECK_NE(ProcessInfoTests::ExtractCGroupContainerId(*processInfo, invalid_line), 0); } \ No newline at end of file From 65789e4e7f4702a97d1214923a853f78f68634e9 Mon Sep 17 00:00:00 2001 From: iritb Date: Tue, 7 Jan 2025 15:49:44 +0200 Subject: [PATCH 14/18] Fix container ID extraction tests to use pointer dereference for ProcessInfo --- ProcessInfoTests.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ProcessInfoTests.cpp b/ProcessInfoTests.cpp index 5019059..2fdf33a 100644 --- a/ProcessInfoTests.cpp +++ b/ProcessInfoTests.cpp @@ -39,17 +39,17 @@ BOOST_AUTO_TEST_CASE(container_id_extraction_test) { // Test containerd format std::string containerd_line = "some text /containerd-ebe83cd204c5 more text\n"; BOOST_CHECK_EQUAL(ProcessInfoTests::ExtractCGroupContainerId(*processInfo, containerd_line), 0); - BOOST_CHECK_EQUAL(processInfo.container_id(), "ebe83cd204c5"); + BOOST_CHECK_EQUAL(processInfo->container_id(), "ebe83cd204c5"); // Test Docker format std::string docker_line = "some text /docker/ebe83cd204c5 more text\n"; BOOST_CHECK_EQUAL(ProcessInfoTests::ExtractCGroupContainerId(*processInfo, docker_line), 0); - BOOST_CHECK_EQUAL(processInfo.container_id(), "ebe83cd204c5"); + BOOST_CHECK_EQUAL(processInfo->container_id(), "ebe83cd204c5"); // Test system.slice Docker format std::string system_docker_line = "some text /system.slice/docker-ebe83cd204c5 more text\n"; BOOST_CHECK_EQUAL(ProcessInfoTests::ExtractCGroupContainerId(*processInfo, system_docker_line), 0); - BOOST_CHECK_EQUAL(processInfo.container_id(), "ebe83cd204c5"); + BOOST_CHECK_EQUAL(processInfo->container_id(), "ebe83cd204c5"); // Test invalid format std::string invalid_line = "some text without container id\n"; From f8af84b54b89602eb42bb7a2314032a7f8ecd006 Mon Sep 17 00:00:00 2001 From: iritb Date: Tue, 7 Jan 2025 16:29:04 +0200 Subject: [PATCH 15/18] Change pointer type to const for container ID extraction in ProcessInfo --- ProcessInfo.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ProcessInfo.cpp b/ProcessInfo.cpp index 30f3bb1..14cfe1f 100644 --- a/ProcessInfo.cpp +++ b/ProcessInfo.cpp @@ -382,7 +382,7 @@ int ProcessInfo::ExtractCGroupContainerId(const std::string& content) { while ((line_end = strchr(ptr, '\n')) != nullptr) { // Check for containerd format - char *containerd_pos = strstr(ptr, containerd_prefix); + const char *containerd_pos = strstr(ptr, containerd_prefix); if (containerd_pos != nullptr && containerd_pos < line_end) { if (containerd_pos + containerd_prefix_len + 12 <= line_end) { _container_id = std::string(containerd_pos + containerd_prefix_len, 12); // Extract the first 12 characters of the container ID @@ -391,7 +391,7 @@ int ProcessInfo::ExtractCGroupContainerId(const std::string& content) { } // Check for Docker format - char *docker_pos = strstr(ptr, docker_prefix); + const char *docker_pos = strstr(ptr, docker_prefix); if (docker_pos != nullptr && docker_pos < line_end) { if (docker_pos + docker_prefix_len + 12 <= line_end) { _container_id = std::string(docker_pos + docker_prefix_len, 12); // Extract the first 12 characters of the container ID @@ -400,7 +400,7 @@ int ProcessInfo::ExtractCGroupContainerId(const std::string& content) { } // Check for system.slice Docker format - char *system_docker_pos = strstr(ptr, system_docker_prefix); + const char *system_docker_pos = strstr(ptr, system_docker_prefix); if (system_docker_pos != nullptr && system_docker_pos < line_end) { if (system_docker_pos + system_docker_prefix_len + 12 <= line_end) { _container_id = std::string(system_docker_pos + system_docker_prefix_len, 12); // Extract the first 12 characters of the container ID From 034d9e2785d5a1607b7a05b570fba05fe7cd3996 Mon Sep 17 00:00:00 2001 From: iritb Date: Tue, 7 Jan 2025 18:04:12 +0200 Subject: [PATCH 16/18] Add ProcessInfoTests executable and update test module definition --- CMakeLists.txt | 25 ++++++++++++++++++++++++- ProcessInfoTests.cpp | 2 +- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dac6dae..558a7f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -462,10 +462,33 @@ target_link_libraries(EventProcessorTests ${Boost_LIBRARIES} add_test(EventProcessor ${CMAKE_BINARY_DIR}/EventProcessorTests --log_sink=EventProcessorTests.log --report_sink=EventProcessorTests.report) +add_executable(ProcessInfoTests + auoms_version.h + ProcessInfoTests.cpp + Event.cpp + Signals.cpp + Logger.cpp + Config.cpp + UserDB.cpp + RunBase.cpp + ProcessInfo.cpp + ProcFilter.cpp + ProcessTree.cpp + FiltersEngine.cpp + StringUtils.cpp + ExecveConverter.cpp +) +target_link_libraries(ProcessInfoTests Boost::unit_test_framework) + +if(NOT DO_STATIC_LINK) + target_compile_definitions(ProcessInfoTests PUBLIC BOOST_TEST_DYN_LINK=1) +endif() + +add_test(NAME ProcessInfoTests COMMAND ProcessInfoTests) + add_executable(ProcessTreeTests auoms_version.h ProcessTreeTests.cpp - ProcessInfoTests.cpp Event.cpp Signals.cpp Logger.cpp diff --git a/ProcessInfoTests.cpp b/ProcessInfoTests.cpp index 2fdf33a..018b56d 100644 --- a/ProcessInfoTests.cpp +++ b/ProcessInfoTests.cpp @@ -14,7 +14,7 @@ THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#define BOOST_TEST_MODULE ProcessInfoTests +#define BOOST_TEST_MODULE "ProcessInfoTests" #include #include "ProcessInfo.h" From 3a4e3cc07155a3bba675d88e22d48ec6d0924a48 Mon Sep 17 00:00:00 2001 From: iritb Date: Tue, 7 Jan 2025 22:39:04 +0200 Subject: [PATCH 17/18] Update CMakeLists.txt to link additional libraries for ProcessInfoTests --- CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 558a7f9..f232d5a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -478,7 +478,13 @@ add_executable(ProcessInfoTests StringUtils.cpp ExecveConverter.cpp ) -target_link_libraries(ProcessInfoTests Boost::unit_test_framework) + +target_link_libraries(ProcessInfoTests ${Boost_LIBRARIES} + libre2.a + dl + pthread + rt +) if(NOT DO_STATIC_LINK) target_compile_definitions(ProcessInfoTests PUBLIC BOOST_TEST_DYN_LINK=1) From fec47ada947bd60468b1ba1b20f4ec04182c3955 Mon Sep 17 00:00:00 2001 From: iritb Date: Wed, 8 Jan 2025 17:00:10 +0200 Subject: [PATCH 18/18] added a comment --- ProcessTree.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/ProcessTree.cpp b/ProcessTree.cpp index 7774b42..c2dc49e 100644 --- a/ProcessTree.cpp +++ b/ProcessTree.cpp @@ -427,8 +427,21 @@ std::shared_ptr ProcessTree::AddProcess(enum ProcessTreeSource ApplyFlags(process); _processes[pid] = process; } - - // Call ReadProcEntry to ensure container ID is set if it's still empty + + // The purpose of extracting the container ID from cgroup is to accurately identify + // the container in which a process is running. This is particularly important for + // monitoring and logging purposes in containerized environments, where applications + // are packaged and run in containers. By testing the extraction logic with various + // cgroup formats, we aim to ensure that the container ID is correctly identified in + // all scenarios. + // This method complements the existing logic that extracts the container ID from the + // command line arguments by providing an additional, more reliable source of information. + // This is especially relevant when the container ID is not found through the existing + // logic, which can happen when there is no parent process or when the parent process + // does not have the container ID set. This situation can occur in various scenarios, + // such as when a process is the root process of a container or when the process is + // started by a web service or another system service that does not pass the container + // ID through the command line arguments. if (process->_containerid.empty()) { auto p_temp = ReadProcEntry(pid); if (p_temp) {