From a6abd821d5dc50fbaaf921354d66fe5477a2f201 Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Tue, 18 Jun 2019 15:53:53 -0600 Subject: [PATCH] Allow to drop existing fd cache of cgroup path A process can give up the permission to set cgroup. If we still keep the fd that was cached before losing the permission, when the process sets scheduling group, it will write to the cached fd without checking if is accessible and lead to sepolicy denied. Bug: 123043091 Test: Build and boot. Test: A new process from zygote set cgroup and drop fd cache, and then specializes to app domain. There is no sepolicy denied when the process creates new thread. (android::thread_data_t::trampoline) Change-Id: I285ee91424ea965ea9c670fc0f6662948e3e2ce5 --- .../include/processgroup/processgroup.h | 5 ++++ libprocessgroup/processgroup.cpp | 4 +++ libprocessgroup/task_profiles.cpp | 27 +++++++++++++++++++ libprocessgroup/task_profiles.h | 4 +++ 4 files changed, 40 insertions(+) diff --git a/libprocessgroup/include/processgroup/processgroup.h b/libprocessgroup/include/processgroup/processgroup.h index 7e6bf45cf..f73ec2d41 100644 --- a/libprocessgroup/include/processgroup/processgroup.h +++ b/libprocessgroup/include/processgroup/processgroup.h @@ -39,6 +39,11 @@ static constexpr const char* CGROUPS_RC_PATH = "/dev/cgroup_info/cgroup.rc"; bool UsePerAppMemcg(); +// Drop the fd cache of cgroup path. It is used for when resource caching is enabled and a process +// loses the access to the path, the access checking (See SetCgroupAction::EnableResourceCaching) +// should be active again. E.g. Zygote specialization for child process. +void DropTaskProfilesResourceCaching(); + // Return 0 and removes the cgroup if there are no longer any processes in it. // Returns -1 in the case of an error occurring or if there are processes still running // even after retrying for up to 200ms. diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp index d3ac26bd1..7c191be1b 100644 --- a/libprocessgroup/processgroup.cpp +++ b/libprocessgroup/processgroup.cpp @@ -111,6 +111,10 @@ static bool isMemoryCgroupSupported() { return memcg_supported; } +void DropTaskProfilesResourceCaching() { + TaskProfiles::GetInstance().DropResourceCaching(); +} + bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector& profiles, bool use_fd_cache) { const TaskProfiles& tp = TaskProfiles::GetInstance(); diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp index edc316a8d..aee5f0cce 100644 --- a/libprocessgroup/task_profiles.cpp +++ b/libprocessgroup/task_profiles.cpp @@ -173,6 +173,15 @@ void SetCgroupAction::EnableResourceCaching() { fd_ = std::move(fd); } +void SetCgroupAction::DropResourceCaching() { + std::lock_guard lock(fd_mutex_); + if (fd_ == FDS_NOT_CACHED) { + return; + } + + fd_.reset(FDS_NOT_CACHED); +} + bool SetCgroupAction::AddTidToCgroup(int tid, int fd) { if (tid <= 0) { return true; @@ -292,6 +301,24 @@ void TaskProfile::EnableResourceCaching() { res_cached_ = true; } +void TaskProfile::DropResourceCaching() { + if (!res_cached_) { + return; + } + + for (auto& element : elements_) { + element->DropResourceCaching(); + } + + res_cached_ = false; +} + +void TaskProfiles::DropResourceCaching() const { + for (auto& iter : profiles_) { + iter.second->DropResourceCaching(); + } +} + TaskProfiles& TaskProfiles::GetInstance() { // Deliberately leak this object to avoid a race between destruction on // process exit and concurrent access from another thread. diff --git a/libprocessgroup/task_profiles.h b/libprocessgroup/task_profiles.h index 77bac2d94..891d5b56a 100644 --- a/libprocessgroup/task_profiles.h +++ b/libprocessgroup/task_profiles.h @@ -51,6 +51,7 @@ class ProfileAction { virtual bool ExecuteForTask(int) const { return false; }; virtual void EnableResourceCaching() {} + virtual void DropResourceCaching() {} }; // Profile actions @@ -114,6 +115,7 @@ class SetCgroupAction : public ProfileAction { virtual bool ExecuteForProcess(uid_t uid, pid_t pid) const; virtual bool ExecuteForTask(int tid) const; virtual void EnableResourceCaching(); + virtual void DropResourceCaching(); const CgroupController* controller() const { return &controller_; } std::string path() const { return path_; } @@ -145,6 +147,7 @@ class TaskProfile { bool ExecuteForProcess(uid_t uid, pid_t pid) const; bool ExecuteForTask(int tid) const; void EnableResourceCaching(); + void DropResourceCaching(); private: bool res_cached_; @@ -158,6 +161,7 @@ class TaskProfiles { TaskProfile* GetProfile(const std::string& name) const; const ProfileAttribute* GetAttribute(const std::string& name) const; + void DropResourceCaching() const; private: std::map> profiles_;