Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a323e023 authored by Wei Wang's avatar Wei Wang Committed by Gerrit Code Review
Browse files

Merge "Support process path for WriteFileAction"

parents 8e4b2bfd 9221b1ee
Loading
Loading
Loading
Loading
+85 −40
Original line number Diff line number Diff line
@@ -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_, 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_;
    }

bool WriteFileAction::WriteValueToFile(const std::string& value, const std::string& path,
                                       bool logfailures) {
    // 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_);
    if (!proc_path_.empty()) {
        return WriteValueToFile(value_, ProfileAction::RCT_PROCESS, uid, pid, logfailures_);
    }

    value = StringReplace(value, "<uid>", std::to_string(uid), true);
    value = StringReplace(value, "<pid>", std::to_string(pid), true);
    DIR* d;
    struct dirent* de;
    char proc_path[255];
    int t_pid;

    CacheUseResult result = UseCachedFd(ProfileAction::RCT_PROCESS, value);
    if (result != ProfileAction::UNUSED) {
        return result == ProfileAction::SUCCESS;
    sprintf(proc_path, "/proc/%d/task", pid);
    if (!(d = opendir(proc_path))) {
        return false;
    }

    std::string path(path_);
    path = StringReplace(path, "<uid>", std::to_string(uid), true);
    path = StringReplace(path, "<pid>", std::to_string(pid), true);
    while ((de = readdir(d))) {
        if (de->d_name[0] == '.') {
            continue;
        }

    return WriteValueToFile(value, path, logfailures_);
        t_pid = atoi(de->d_name);

        if (!t_pid) {
            continue;
        }

bool WriteFileAction::ExecuteForTask(int tid) const {
    std::string value(value_);
    int uid = getuid();
        WriteValueToFile(value_, ProfileAction::RCT_TASK, uid, t_pid, logfailures_);
    }

    value = StringReplace(value, "<uid>", std::to_string(uid), true);
    value = StringReplace(value, "<pid>", std::to_string(tid), true);
    closedir(d);

    CacheUseResult result = UseCachedFd(ProfileAction::RCT_TASK, value);
    if (result != ProfileAction::UNUSED) {
        return result == ProfileAction::SUCCESS;
    return true;
}

    return WriteValueToFile(value, path_, logfailures_);
bool WriteFileAction::ExecuteForTask(int tid) const {
    return WriteValueToFile(value_, ProfileAction::RCT_TASK, getuid(), tid, logfailures_);
}

void WriteFileAction::EnableResourceCaching(ResourceCacheType) {
void WriteFileAction::EnableResourceCaching(ResourceCacheType cache_type) {
    std::lock_guard<std::mutex> lock(fd_mutex_);
    FdCacheHelper::Cache(path_, fd_);
    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;
    }
}

void WriteFileAction::DropResourceCaching(ResourceCacheType) {
void WriteFileAction::DropResourceCaching(ResourceCacheType cache_type) {
    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 @@ 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";
+6 −5
Original line number Diff line number Diff line
@@ -140,7 +140,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);

    const char* Name() const override { return "WriteFile"; }
    bool ExecuteForProcess(uid_t uid, pid_t pid) const override;
@@ -149,13 +150,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;
};