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();