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
This commit is contained in:
Riddle Hsu 2019-06-18 15:53:53 -06:00
parent ad6f656be2
commit a6abd821d5
4 changed files with 40 additions and 0 deletions

View File

@ -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.

View File

@ -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<std::string>& profiles,
bool use_fd_cache) {
const TaskProfiles& tp = TaskProfiles::GetInstance();

View File

@ -173,6 +173,15 @@ void SetCgroupAction::EnableResourceCaching() {
fd_ = std::move(fd);
}
void SetCgroupAction::DropResourceCaching() {
std::lock_guard<std::mutex> 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.

View File

@ -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<std::string, std::unique_ptr<TaskProfile>> profiles_;