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
This commit is contained in:
parent
86b6db0b0f
commit
9221b1eeae
|
@ -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, "<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 @@ 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<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 @@ ProfileAction::CacheUseResult WriteFileAction::UseCachedFd(ResourceCacheType cac
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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<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 {
|
||||
|
@ -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<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";
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue