diff --git a/libprocessgroup/Android.bp b/libprocessgroup/Android.bp index f529ad76d..bb855d58c 100644 --- a/libprocessgroup/Android.bp +++ b/libprocessgroup/Android.bp @@ -8,6 +8,7 @@ soong_config_module_type { config_namespace: "ANDROID", bool_variables: [ "memcg_v2_force_enabled", + "cgroup_v2_sys_app_isolation", ], properties: [ "cflags", @@ -23,6 +24,11 @@ libprocessgroup_flag_aware_cc_defaults { "-DMEMCG_V2_FORCE_ENABLED=true", ], }, + cgroup_v2_sys_app_isolation: { + cflags: [ + "-DCGROUP_V2_SYS_APP_ISOLATION=true", + ], + }, }, } diff --git a/libprocessgroup/build_flags.h b/libprocessgroup/build_flags.h index 69fa76e1b..bc3e7dff1 100644 --- a/libprocessgroup/build_flags.h +++ b/libprocessgroup/build_flags.h @@ -20,10 +20,18 @@ #define MEMCG_V2_FORCE_ENABLED false #endif +#ifndef CGROUP_V2_SYS_APP_ISOLATION +#define CGROUP_V2_SYS_APP_ISOLATION false +#endif + namespace android::libprocessgroup_flags { inline consteval bool force_memcg_v2() { return MEMCG_V2_FORCE_ENABLED; } +inline consteval bool cgroup_v2_sys_app_isolation() { + return CGROUP_V2_SYS_APP_ISOLATION; +} + } // namespace android::libprocessgroup_flags diff --git a/libprocessgroup/setup/cgroup_map_write.cpp b/libprocessgroup/setup/cgroup_map_write.cpp index a9fd0e58b..1b26fbcc6 100644 --- a/libprocessgroup/setup/cgroup_map_write.cpp +++ b/libprocessgroup/setup/cgroup_map_write.cpp @@ -483,6 +483,42 @@ static std::optional MEMCGDisabled( return content.find("memory") == std::string::npos; } +static bool CreateV2SubHierarchy( + const std::string& path, + const std::map& descriptors) { + using namespace android::cgrouprc; + + const auto cgv2_iter = descriptors.find(CGROUPV2_HIERARCHY_NAME); + if (cgv2_iter == descriptors.end()) return false; + const android::cgrouprc::CgroupDescriptor cgv2_descriptor = cgv2_iter->second; + + if (!Mkdir(path, cgv2_descriptor.mode(), cgv2_descriptor.uid(), cgv2_descriptor.gid())) { + PLOG(ERROR) << "Failed to create directory for " << path; + return false; + } + + // Activate all v2 controllers in path so they can be activated in + // children as they are created. + for (const auto& [name, descriptor] : descriptors) { + const format::CgroupController* controller = descriptor.controller(); + std::uint32_t flags = controller->flags(); + if (controller->version() == 2 && name != CGROUPV2_HIERARCHY_NAME && + flags & CGROUPRC_CONTROLLER_FLAG_NEEDS_ACTIVATION) { + std::string str("+"); + str += controller->name(); + if (!android::base::WriteStringToFile(str, path + "/cgroup.subtree_control")) { + if (flags & CGROUPRC_CONTROLLER_FLAG_OPTIONAL) { + PLOG(WARNING) << "Activation of cgroup controller " << str << " failed in path " + << path; + } else { + return false; + } + } + } + } + return true; +} + bool CgroupSetup() { using namespace android::cgrouprc; @@ -527,6 +563,21 @@ bool CgroupSetup() { } } + // System / app isolation. + // This really belongs in early-init in init.rc, but we cannot use the flag there. + if (android::libprocessgroup_flags::cgroup_v2_sys_app_isolation()) { + const auto it = descriptors.find(CGROUPV2_HIERARCHY_NAME); + const std::string cgroup_v2_root = (it == descriptors.end()) + ? CGROUP_V2_ROOT_DEFAULT + : it->second.controller()->path(); + + LOG(INFO) << "Using system/app isolation under: " << cgroup_v2_root; + if (!CreateV2SubHierarchy(cgroup_v2_root + "/apps", descriptors) || + !CreateV2SubHierarchy(cgroup_v2_root + "/system", descriptors)) { + return false; + } + } + // mkdir 0711 system system if (!Mkdir(android::base::Dirname(CGROUPS_RC_PATH), 0711, "system", "system")) { LOG(ERROR) << "Failed to create directory for " << CGROUPS_RC_PATH << " file"; diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp index c376a0fe6..0c2252b17 100644 --- a/libprocessgroup/task_profiles.cpp +++ b/libprocessgroup/task_profiles.cpp @@ -33,6 +33,8 @@ #include #include +#include + // To avoid issues in sdk_mac build #if defined(__ANDROID__) #include @@ -126,7 +128,17 @@ void ProfileAttribute::Reset(const CgroupController& controller, const std::stri file_v2_name_ = file_v2_name; } +static bool isSystemApp(uid_t uid) { + return uid < AID_APP_START; +} + std::string ConvertUidToPath(const char* root_cgroup_path, uid_t uid) { + if (android::libprocessgroup_flags::cgroup_v2_sys_app_isolation()) { + if (isSystemApp(uid)) + return StringPrintf("%s/system/uid_%u", root_cgroup_path, uid); + else + return StringPrintf("%s/apps/uid_%u", root_cgroup_path, uid); + } return StringPrintf("%s/uid_%u", root_cgroup_path, uid); }