From ac9022445a10af06aad4f23a214172d4231b566b Mon Sep 17 00:00:00 2001 From: Varun Singhal Date: Tue, 29 Sep 2026 15:41:20 +0530 Subject: [PATCH] classifier: skip Docker container processes to fix docker exec failure URM was moving Docker container init processes out of their docker-.scope cgroup, causing systemd to remove the empty scope and breaking docker exec with "can't open cgroup" error. Add isContainerProcess() to detect container init processes by reading /proc//cgroup and skip them in shouldProcBeIgnored(). CRs-Fixed: 4689720 Signed-off-by: Varun Singhal --- .../ContextualClassifier.cpp | 32 +++++++++++++++++++ .../Include/ContextualClassifier.h | 4 +++ 2 files changed, 36 insertions(+) diff --git a/contextual-classifier/ContextualClassifier.cpp b/contextual-classifier/ContextualClassifier.cpp index cfd98f150..db95b9d12 100644 --- a/contextual-classifier/ContextualClassifier.cpp +++ b/contextual-classifier/ContextualClassifier.cpp @@ -471,11 +471,43 @@ void ContextualClassifier::loadStaticProcData() { LOGI(CLASSIFIER_TAG, "Successfully loaded static proc data"); } +int8_t ContextualClassifier::isContainerProcess(pid_t pid) { + // Check if the process lives inside a container cgroup scope by reading + // /proc//cgroup. A Docker container init process has a path like: + // 0::/system.slice/docker-.scope + // Moving it out of this scope causes systemd to remove the now-empty scope, + // which breaks subsequent docker exec calls with: + // "can't open cgroup: .../docker-.scope: No such file or directory" + + // TODO: extend to Kubernetes container runtimes when needed: + // - containerd (k8s default runtime): cgroup path contains "containerd-.scope" + // - CRI-O (OpenShift / k8s alternative): cgroup path contains "crio-.scope" + + std::ifstream cgroupFile("/proc/" + std::to_string(pid) + "/cgroup"); + if(cgroupFile.is_open()) { + std::string line; + while(std::getline(cgroupFile, line)) { + if(line.find("docker-") != std::string::npos && + line.find(".scope") != std::string::npos) { + return true; + } + } + } + return false; +} + int8_t ContextualClassifier::shouldProcBeIgnored(int32_t evType, pid_t pid) { if(evType == CC_APP_CLOSE) { return false; } + // Skip Docker container init processes to avoid breaking docker exec. + if(this->isContainerProcess(pid)) { + LOGI(CLASSIFIER_TAG, + "Ignoring Docker container process PID: " + std::to_string(pid)); + return true; + } + std::string procName = ""; if(AuxRoutines::fetchComm(pid, procName) != 0) { return true; diff --git a/contextual-classifier/Include/ContextualClassifier.h b/contextual-classifier/Include/ContextualClassifier.h index 175825335..aa75c644b 100644 --- a/contextual-classifier/Include/ContextualClassifier.h +++ b/contextual-classifier/Include/ContextualClassifier.h @@ -87,6 +87,10 @@ class ContextualClassifier { int8_t checkClientPriority(const std::string& procName); int8_t shouldProcBeIgnored(int32_t evType, pid_t pid); + // Returns true if the process lives inside a container cgroup scope + // (e.g. docker-.scope), indicating it should not be moved by URM. + int8_t isContainerProcess(pid_t pid); + // Transparently get the classification object, without expecting the client // to be aware of the underlying model / implementation. Inference* GetInferenceObject();