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; }