From 9221b1eeaeb80aa76b487bb5a5b19f3b915066f9 Mon Sep 17 00:00:00 2001 From: Rick Yiu Date: Thu, 10 Feb 2022 16:44:43 +0800 Subject: [PATCH] Support process path for WriteFileAction Currently, there is no distinguish between SetTaskProfiles and SetProcessProfiles in WriteFileAction because they use the same task path. Add ProcFilePath attribute so that WriteFileAction could use a separate path for process in SetProcessProfiles. Bug: 218684257 Test: function works Change-Id: I004b8c8799240c54f1ef1fed0566fa5057341cf4 --- libprocessgroup/task_profiles.cpp | 133 ++++++++++++++++++++---------- libprocessgroup/task_profiles.h | 11 +-- 2 files changed, 95 insertions(+), 49 deletions(-) diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp index ffcfeb8ad..c080582ac 100644 --- a/libprocessgroup/task_profiles.cpp +++ b/libprocessgroup/task_profiles.cpp @@ -350,14 +350,33 @@ void SetCgroupAction::DropResourceCaching(ResourceCacheType cache_type) { FdCacheHelper::Drop(fd_[cache_type]); } -WriteFileAction::WriteFileAction(const std::string& path, const std::string& value, - bool logfailures) - : path_(path), value_(value), logfailures_(logfailures) { - FdCacheHelper::Init(path_, fd_); +WriteFileAction::WriteFileAction(const std::string& task_path, const std::string& proc_path, + const std::string& value, bool logfailures) + : task_path_(task_path), proc_path_(proc_path), value_(value), logfailures_(logfailures) { + FdCacheHelper::Init(task_path_, fd_[ProfileAction::RCT_TASK]); + if (!proc_path_.empty()) FdCacheHelper::Init(proc_path_, fd_[ProfileAction::RCT_PROCESS]); } -bool WriteFileAction::WriteValueToFile(const std::string& value, const std::string& path, - bool logfailures) { +bool WriteFileAction::WriteValueToFile(const std::string& value_, ResourceCacheType cache_type, + int uid, int pid, bool logfailures) const { + std::string value(value_); + + value = StringReplace(value, "", std::to_string(uid), true); + value = StringReplace(value, "", std::to_string(pid), true); + + CacheUseResult result = UseCachedFd(cache_type, value); + + if (result != ProfileAction::UNUSED) { + return result == ProfileAction::SUCCESS; + } + + std::string path; + if (cache_type == ProfileAction::RCT_TASK || proc_path_.empty()) { + path = task_path_; + } else { + path = proc_path_; + } + // Use WriteStringToFd instead of WriteStringToFile because the latter will open file with // O_TRUNC which causes kernfs_mutex contention unique_fd tmp_fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_WRONLY | O_CLOEXEC))); @@ -378,21 +397,27 @@ bool WriteFileAction::WriteValueToFile(const std::string& value, const std::stri ProfileAction::CacheUseResult WriteFileAction::UseCachedFd(ResourceCacheType cache_type, const std::string& value) const { std::lock_guard lock(fd_mutex_); - if (FdCacheHelper::IsCached(fd_)) { + if (FdCacheHelper::IsCached(fd_[cache_type])) { // fd is cached, reuse it - if (!WriteStringToFd(value, fd_)) { - if (logfailures_) PLOG(ERROR) << "Failed to write '" << value << "' to " << path_; - return ProfileAction::FAIL; + bool ret = WriteStringToFd(value, fd_[cache_type]); + + if (!ret && logfailures_) { + if (cache_type == ProfileAction::RCT_TASK || proc_path_.empty()) { + PLOG(ERROR) << "Failed to write '" << value << "' to " << task_path_; + } else { + PLOG(ERROR) << "Failed to write '" << value << "' to " << proc_path_; + } } - return ProfileAction::SUCCESS; + return ret ? ProfileAction::SUCCESS : ProfileAction::FAIL; } - if (fd_ == FdCacheHelper::FDS_INACCESSIBLE) { + if (fd_[cache_type] == FdCacheHelper::FDS_INACCESSIBLE) { // no permissions to access the file, ignore return ProfileAction::SUCCESS; } - if (cache_type == ResourceCacheType::RCT_TASK && fd_ == FdCacheHelper::FDS_APP_DEPENDENT) { + if (cache_type == ResourceCacheType::RCT_TASK && + fd_[cache_type] == FdCacheHelper::FDS_APP_DEPENDENT) { // application-dependent path can't be used with tid PLOG(ERROR) << "Application profile can't be applied to a thread"; return ProfileAction::FAIL; @@ -401,46 +426,64 @@ ProfileAction::CacheUseResult WriteFileAction::UseCachedFd(ResourceCacheType cac } bool WriteFileAction::ExecuteForProcess(uid_t uid, pid_t pid) const { - std::string value(value_); - - value = StringReplace(value, "", std::to_string(uid), true); - value = StringReplace(value, "", std::to_string(pid), true); - - CacheUseResult result = UseCachedFd(ProfileAction::RCT_PROCESS, value); - if (result != ProfileAction::UNUSED) { - return result == ProfileAction::SUCCESS; + if (!proc_path_.empty()) { + return WriteValueToFile(value_, ProfileAction::RCT_PROCESS, uid, pid, logfailures_); } - std::string path(path_); - path = StringReplace(path, "", std::to_string(uid), true); - path = StringReplace(path, "", std::to_string(pid), true); + DIR* d; + struct dirent* de; + char proc_path[255]; + int t_pid; - return WriteValueToFile(value, path, logfailures_); + sprintf(proc_path, "/proc/%d/task", pid); + if (!(d = opendir(proc_path))) { + return false; + } + + while ((de = readdir(d))) { + if (de->d_name[0] == '.') { + continue; + } + + t_pid = atoi(de->d_name); + + if (!t_pid) { + continue; + } + + WriteValueToFile(value_, ProfileAction::RCT_TASK, uid, t_pid, logfailures_); + } + + closedir(d); + + return true; } bool WriteFileAction::ExecuteForTask(int tid) const { - std::string value(value_); - int uid = getuid(); + return WriteValueToFile(value_, ProfileAction::RCT_TASK, getuid(), tid, logfailures_); +} - value = StringReplace(value, "", std::to_string(uid), true); - value = StringReplace(value, "", std::to_string(tid), true); - - CacheUseResult result = UseCachedFd(ProfileAction::RCT_TASK, value); - if (result != ProfileAction::UNUSED) { - return result == ProfileAction::SUCCESS; +void WriteFileAction::EnableResourceCaching(ResourceCacheType cache_type) { + std::lock_guard lock(fd_mutex_); + if (fd_[cache_type] != FdCacheHelper::FDS_NOT_CACHED) { + return; + } + switch (cache_type) { + case (ProfileAction::RCT_TASK): + FdCacheHelper::Cache(task_path_, fd_[cache_type]); + break; + case (ProfileAction::RCT_PROCESS): + if (!proc_path_.empty()) FdCacheHelper::Cache(proc_path_, fd_[cache_type]); + break; + default: + LOG(ERROR) << "Invalid cache type is specified!"; + break; } - - return WriteValueToFile(value, path_, logfailures_); } -void WriteFileAction::EnableResourceCaching(ResourceCacheType) { +void WriteFileAction::DropResourceCaching(ResourceCacheType cache_type) { std::lock_guard lock(fd_mutex_); - FdCacheHelper::Cache(path_, fd_); -} - -void WriteFileAction::DropResourceCaching(ResourceCacheType) { - std::lock_guard lock(fd_mutex_); - FdCacheHelper::Drop(fd_); + FdCacheHelper::Drop(fd_[cache_type]); } bool ApplyProfileAction::ExecuteForProcess(uid_t uid, pid_t pid) const { @@ -657,12 +700,14 @@ bool TaskProfiles::Load(const CgroupMap& cg_map, const std::string& file_name) { } } else if (action_name == "WriteFile") { std::string attr_filepath = params_val["FilePath"].asString(); + std::string attr_procfilepath = params_val["ProcFilePath"].asString(); std::string attr_value = params_val["Value"].asString(); + // FilePath and Value are mandatory if (!attr_filepath.empty() && !attr_value.empty()) { std::string attr_logfailures = params_val["LogFailures"].asString(); bool logfailures = attr_logfailures.empty() || attr_logfailures == "true"; - profile->Add(std::make_unique(attr_filepath, attr_value, - logfailures)); + profile->Add(std::make_unique(attr_filepath, attr_procfilepath, + attr_value, logfailures)); } else if (attr_filepath.empty()) { LOG(WARNING) << "WriteFile: invalid parameter: " << "empty filepath"; diff --git a/libprocessgroup/task_profiles.h b/libprocessgroup/task_profiles.h index 2f486641e..ecc67a312 100644 --- a/libprocessgroup/task_profiles.h +++ b/libprocessgroup/task_profiles.h @@ -134,7 +134,8 @@ class SetCgroupAction : public ProfileAction { // Write to file action class WriteFileAction : public ProfileAction { public: - WriteFileAction(const std::string& path, const std::string& value, bool logfailures); + WriteFileAction(const std::string& task_path, const std::string& proc_path, + const std::string& value, bool logfailures); bool ExecuteForProcess(uid_t uid, pid_t pid) const override; bool ExecuteForTask(int tid) const override; @@ -142,13 +143,13 @@ class WriteFileAction : public ProfileAction { void DropResourceCaching(ResourceCacheType cache_type) override; private: - std::string path_, value_; + std::string task_path_, proc_path_, value_; bool logfailures_; - android::base::unique_fd fd_; + android::base::unique_fd fd_[ProfileAction::RCT_COUNT]; mutable std::mutex fd_mutex_; - static bool WriteValueToFile(const std::string& value, const std::string& path, - bool logfailures); + bool WriteValueToFile(const std::string& value, ResourceCacheType cache_type, int uid, int pid, + bool logfailures) const; CacheUseResult UseCachedFd(ResourceCacheType cache_type, const std::string& value) const; };