Merge "Support process path for WriteFileAction"
diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp
index 73aa2af..dc7c368 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -350,14 +350,33 @@
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, "<uid>", std::to_string(uid), true);
+ value = StringReplace(value, "<pid>", 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 @@
ProfileAction::CacheUseResult WriteFileAction::UseCachedFd(ResourceCacheType cache_type,
const std::string& value) const {
std::lock_guard<std::mutex> 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 @@
}
bool WriteFileAction::ExecuteForProcess(uid_t uid, pid_t pid) const {
- std::string value(value_);
-
- value = StringReplace(value, "<uid>", std::to_string(uid), true);
- value = StringReplace(value, "<pid>", 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, "<uid>", std::to_string(uid), true);
- path = StringReplace(path, "<pid>", 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, "<uid>", std::to_string(uid), true);
- value = StringReplace(value, "<pid>", 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<std::mutex> lock(fd_mutex_);
+ if (fd_[cache_type] != FdCacheHelper::FDS_NOT_CACHED) {
+ return;
}
-
- return WriteValueToFile(value, path_, logfailures_);
+ 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;
+ }
}
-void WriteFileAction::EnableResourceCaching(ResourceCacheType) {
+void WriteFileAction::DropResourceCaching(ResourceCacheType cache_type) {
std::lock_guard<std::mutex> lock(fd_mutex_);
- FdCacheHelper::Cache(path_, fd_);
-}
-
-void WriteFileAction::DropResourceCaching(ResourceCacheType) {
- std::lock_guard<std::mutex> lock(fd_mutex_);
- FdCacheHelper::Drop(fd_);
+ FdCacheHelper::Drop(fd_[cache_type]);
}
bool ApplyProfileAction::ExecuteForProcess(uid_t uid, pid_t pid) const {
@@ -659,12 +702,14 @@
}
} 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<WriteFileAction>(attr_filepath, attr_value,
- logfailures));
+ profile->Add(std::make_unique<WriteFileAction>(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 e6e65fb..9ee3781 100644
--- a/libprocessgroup/task_profiles.h
+++ b/libprocessgroup/task_profiles.h
@@ -140,7 +140,8 @@
// 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);
const char* Name() const override { return "WriteFile"; }
bool ExecuteForProcess(uid_t uid, pid_t pid) const override;
@@ -149,13 +150,13 @@
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;
};