From 798e80571527d98292ba7f477c6353b6cdfc01b5 Mon Sep 17 00:00:00 2001 From: Suren Baghdasaryan Date: Thu, 21 Mar 2019 17:10:09 -0700 Subject: [PATCH] libprocessgroup: make sure SetupCgroups is called once and only by init SetupCgroups is called by init process during early-init stage and is not supposed to be called again by anyone else. Ensure that the caller is the init process, make sure cgroup.rc file is written only one time, keep the file descriptor to cgroup.rc file open by the init process to ensure all its further mappings stay valid even if the file is deleted. Bug: 124774415 Test: build, run, verify no errors or warning in the logcat Change-Id: I70ccec551fc07c380333566f618b969667dcf783 Signed-off-by: Suren Baghdasaryan --- libprocessgroup/cgroup_map.cpp | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/libprocessgroup/cgroup_map.cpp b/libprocessgroup/cgroup_map.cpp index b3b497f68..41a6e6ead 100644 --- a/libprocessgroup/cgroup_map.cpp +++ b/libprocessgroup/cgroup_map.cpp @@ -229,9 +229,11 @@ static bool SetupCgroup(const CgroupDescriptor&) { static bool WriteRcFile(const std::map& descriptors) { std::string cgroup_rc_path = StringPrintf("%s/%s", CGROUPS_RC_DIR, CgroupMap::CGROUPS_RC_FILE); - unique_fd fd(TEMP_FAILURE_RETRY(open(cgroup_rc_path.c_str(), - O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, - S_IRUSR | S_IRGRP | S_IROTH))); + // Let init keep the FD open to prevent file mappings from becoming invalid + // in case the file gets deleted somehow + static unique_fd fd(TEMP_FAILURE_RETRY(open(cgroup_rc_path.c_str(), + O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, + S_IRUSR | S_IRGRP | S_IROTH))); if (fd < 0) { PLOG(ERROR) << "open() failed for " << cgroup_rc_path; return false; @@ -412,6 +414,19 @@ void CgroupMap::Print() const { bool CgroupMap::SetupCgroups() { std::map descriptors; + if (getpid() != 1) { + LOG(ERROR) << "Cgroup setup can be done only by init process"; + return false; + } + + // Make sure we do this only one time. No need for std::call_once because + // init is a single-threaded process + static bool setup_done = false; + if (setup_done) { + LOG(WARNING) << "Attempt to call SetupCgroups more than once"; + return true; + } + // load cgroups.json file if (!ReadDescriptors(&descriptors)) { LOG(ERROR) << "Failed to load cgroup description file"; @@ -449,6 +464,7 @@ bool CgroupMap::SetupCgroups() { return false; } + setup_done = true; return true; }