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
This commit is contained in:
Jooyung Han 2019-11-25 13:50:44 +09:00
parent 80a734f146
commit 5bb9d2133a

View file

@ -25,6 +25,7 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/result.h>
#include <android-base/unique_fd.h>
#include "util.h"
@ -79,30 +80,69 @@ static bool IsApexUpdatable() {
return updatable;
}
static Result<void> 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<void> ActivateFlattenedApexesFrom(const std::string& from_dir,
const std::string& to_dir) {
std::unique_ptr<DIR, decltype(&closedir)> 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<std::string> 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<std::string> 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) {