From 5bb9d2133a56289d8a80d84cd310bda934d256ee Mon Sep 17 00:00:00 2001 From: Jooyung Han Date: Mon, 25 Nov 2019 13:50:44 +0900 Subject: [PATCH] Bind-mount individual flattened APEXes There are a few directories for builtin APEXes: /system/apex, /system_ext/apex, /product/apex, /vendor/apex. For devices with ro.apex.updatable=false, init should bind-mount "flattened" apexes from all of above. Bug: 144732372 Test: OVERRIDE_TARGET_FLATTEN_APEX=true m && device boot Change-Id: If151145e6e3d966b202300ff3a0ddb5ec9fdaa87 --- init/mount_namespace.cpp | 62 +++++++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 11 deletions(-) diff --git a/init/mount_namespace.cpp b/init/mount_namespace.cpp index 0745148bd..940fb6b5d 100644 --- a/init/mount_namespace.cpp +++ b/init/mount_namespace.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "util.h" @@ -79,30 +80,69 @@ static bool IsApexUpdatable() { return updatable; } +static Result MountDir(const std::string& path, const std::string& mount_path) { + if (int ret = mkdir(mount_path.c_str(), 0755); ret != 0 && ret != EEXIST) { + return ErrnoError() << "Could not create mount point " << mount_path; + } + if (mount(path.c_str(), mount_path.c_str(), nullptr, MS_BIND, nullptr) != 0) { + return ErrnoError() << "Could not bind mount " << path << " to " << mount_path; + } + return {}; +} + +static Result ActivateFlattenedApexesFrom(const std::string& from_dir, + const std::string& to_dir) { + std::unique_ptr dir(opendir(from_dir.c_str()), closedir); + if (!dir) { + return {}; + } + dirent* entry; + while ((entry = readdir(dir.get())) != nullptr) { + if (entry->d_name[0] == '.') continue; + if (entry->d_type == DT_DIR) { + const std::string apex_path = from_dir + "/" + entry->d_name; + const std::string mount_path = to_dir + "/" + entry->d_name; + if (auto result = MountDir(apex_path, mount_path); !result) { + return result; + } + } + } + return {}; +} + static bool ActivateFlattenedApexesIfPossible() { if (IsRecoveryMode() || IsApexUpdatable()) { return true; } - constexpr const char kSystemApex[] = "/system/apex"; - constexpr const char kApexTop[] = "/apex"; - if (mount(kSystemApex, kApexTop, nullptr, MS_BIND, nullptr) != 0) { - PLOG(ERROR) << "Could not bind mount " << kSystemApex << " to " << kApexTop; - return false; - } + const std::string kApexTop = "/apex"; + const std::vector kBuiltinDirsForApexes = { + "/system/apex", + "/system_ext/apex", + "/product/apex", + "/vendor/apex", + }; + for (const auto& dir : kBuiltinDirsForApexes) { + if (auto result = ActivateFlattenedApexesFrom(dir, kApexTop); !result) { + LOG(ERROR) << result.error(); + return false; + } + } // Special casing for the ART APEX - constexpr const char kArtApexMountPath[] = "/system/apex/com.android.art"; + constexpr const char kArtApexMountPath[] = "/apex/com.android.art"; static const std::vector kArtApexDirNames = {"com.android.art.release", "com.android.art.debug"}; bool success = false; for (const auto& name : kArtApexDirNames) { - std::string path = std::string(kSystemApex) + "/" + name; + std::string path = kApexTop + "/" + name; if (access(path.c_str(), F_OK) == 0) { - if (mount(path.c_str(), kArtApexMountPath, nullptr, MS_BIND, nullptr) == 0) { - success = true; - break; + if (auto result = MountDir(path, kArtApexMountPath); !result) { + LOG(ERROR) << result.error(); + return false; } + success = true; + break; } } if (!success) {