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

Commit 6bf71e0c authored by Wei Wang's avatar Wei Wang Committed by Automerger Merge Worker
Browse files

Merge "Support process path for WriteFileAction" am: a323e023

Original change: https://android-review.googlesource.com/c/platform/system/core/+/1979310

Change-Id: I051ae3978453680b00fa9f16e5f54bd846ac476f
parents dbc6027f a323e023
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;
};