diff options
-rw-r--r-- | daemon.cpp | 3 | ||||
-rw-r--r-- | gsi_service.cpp | 80 | ||||
-rw-r--r-- | gsi_service.h | 7 |
3 files changed, 65 insertions, 25 deletions
@@ -59,6 +59,9 @@ int main(int argc, char** argv) { } else if (argv[1] == "dump-device-mapper"s) { int rc = DumpDeviceMapper(); exit(rc); + } else if (argv[1] == "verify-image-maps"s) { + android::gsi::GsiService::VerifyImageMaps(); + exit(0); } } diff --git a/gsi_service.cpp b/gsi_service.cpp index 6f7ff01..122bbf6 100644 --- a/gsi_service.cpp +++ b/gsi_service.cpp @@ -36,6 +36,7 @@ #include <android/os/IVold.h> #include <binder/IServiceManager.h> #include <binder/LazyServiceRegistrar.h> +#include <cutils/android_reboot.h> #include <ext4_utils/ext4_utils.h> #include <fs_mgr.h> #include <libavb/libavb.h> @@ -154,13 +155,34 @@ binder::Status GsiService::openInstall(const std::string& install_dir, int* _aid binder::Status GsiService::closeInstall(int* _aidl_return) { ENFORCE_SYSTEM; std::lock_guard<std::mutex> guard(lock_); + + installer_ = {}; + auto dsu_slot = GetDsuSlot(install_dir_); std::string file = GetCompleteIndication(dsu_slot); if (!WriteStringToFile("OK", file)) { PLOG(ERROR) << "write failed: " << file; - *_aidl_return = INSTALL_ERROR_GENERIC; + *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC; + return binder::Status::ok(); } - *_aidl_return = INSTALL_OK; + + // Create installation complete marker files, but set disabled immediately. + if (!WriteStringToFile(dsu_slot, kDsuActiveFile)) { + PLOG(ERROR) << "cannot write active DSU slot (" << dsu_slot << "): " << kDsuActiveFile; + *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC; + return binder::Status::ok(); + } + RestoreconMetadataFiles(); + + // DisableGsi() creates the DSU install status file and mark it as "disabled". + if (!DisableGsi()) { + PLOG(ERROR) << "cannot write DSU status file: " << kDsuInstallStatusFile; + *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC; + return binder::Status::ok(); + } + + SetProperty(kGsiInstalledProp, "1"); + *_aidl_return = IGsiService::INSTALL_OK; return binder::Status::ok(); } @@ -216,7 +238,8 @@ binder::Status GsiService::closePartition(int32_t* _aidl_return) { return binder::Status::ok(); } // It is important to not reset |installer_| here because other methods such - // as enableGsi() relies on the state of |installer_|. + // as isGsiInstallInProgress() relies on the state of |installer_|. + // TODO: Maybe don't do this, use a dedicated |in_progress_| flag? *_aidl_return = installer_->FinishInstall(); return binder::Status::ok(); } @@ -302,6 +325,7 @@ binder::Status GsiService::enableGsiAsync(bool one_shot, const std::string& dsuS } binder::Status GsiService::enableGsi(bool one_shot, const std::string& dsuSlot, int* _aidl_return) { + ENFORCE_SYSTEM_OR_SHELL; std::lock_guard<std::mutex> guard(lock_); if (!WriteStringToFile(dsuSlot, kDsuActiveFile)) { @@ -310,22 +334,14 @@ binder::Status GsiService::enableGsi(bool one_shot, const std::string& dsuSlot, return binder::Status::ok(); } RestoreconMetadataFiles(); + if (installer_) { - ENFORCE_SYSTEM; - installer_ = {}; - // Note: create the install status file last, since this is the actual boot - // indicator. - if (!SetBootMode(one_shot) || !CreateInstallStatusFile()) { - *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC; - } else { - *_aidl_return = INSTALL_OK; - } - } else { - ENFORCE_SYSTEM_OR_SHELL; - *_aidl_return = ReenableGsi(one_shot); + LOG(ERROR) << "cannot enable an ongoing installation, was closeInstall() called?"; + *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC; + return binder::Status::ok(); } - installer_ = nullptr; + *_aidl_return = ReenableGsi(one_shot); return binder::Status::ok(); } @@ -529,7 +545,7 @@ binder::Status GsiService::suggestScratchSize(int64_t* _aidl_return) { return binder::Status::ok(); } -bool GsiService::CreateInstallStatusFile() { +bool GsiService::ResetBootAttemptCounter() { if (!android::base::WriteStringToFile("0", kDsuInstallStatusFile)) { PLOG(ERROR) << "write " << kDsuInstallStatusFile; return false; @@ -944,13 +960,7 @@ int GsiService::ReenableGsi(bool one_shot) { LOG(ERROR) << "GSI is not currently disabled"; return INSTALL_ERROR_GENERIC; } - if (IsGsiRunning()) { - if (!SetBootMode(one_shot) || !CreateInstallStatusFile()) { - return IGsiService::INSTALL_ERROR_GENERIC; - } - return IGsiService::INSTALL_OK; - } - if (!SetBootMode(one_shot) || !CreateInstallStatusFile()) { + if (!SetBootMode(one_shot) || !ResetBootAttemptCounter()) { return IGsiService::INSTALL_ERROR_GENERIC; } return IGsiService::INSTALL_OK; @@ -1109,6 +1119,28 @@ void GsiService::RunStartupTasks() { } } +void GsiService::VerifyImageMaps() { + std::vector<std::pair<std::string, std::string>> paths = { + {"/metadata/gsi/remount", "/data/gsi/remount"}, + {"/metadata/gsi/ota", "/data/gsi/ota"}, + }; + + for (const auto& [metadata_dir, data_dir] : paths) { + auto impl = ImageManager::Open(metadata_dir, data_dir); + if (!impl) { + LOG(ERROR) << "Could not open ImageManager for " << metadata_dir << " and " << data_dir; + continue; + } + if (!impl->ValidateImageMaps()) { + LOG(ERROR) << "ImageManager for " << metadata_dir + << " failed validation, device data is at risk. Rebooting."; + android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,fastboot"); + continue; + } + LOG(INFO) << "ImageManager verification passed for " << metadata_dir; + } +} + static bool GetAvbPublicKeyFromFd(int fd, AvbPublicKey* dst) { // Read the AVB footer from EOF. int64_t total_size = get_block_device_size(fd); diff --git a/gsi_service.h b/gsi_service.h index c9e4e05..0ec7620 100644 --- a/gsi_service.h +++ b/gsi_service.h @@ -80,6 +80,7 @@ class GsiService : public BinderService<GsiService>, public BnGsiService { bool should_abort() const { return should_abort_; } static void RunStartupTasks(); + static void VerifyImageMaps(); static std::string GetInstalledImageDir(); std::string GetActiveDsuSlot(); std::string GetActiveInstalledImageDir(); @@ -100,7 +101,11 @@ class GsiService : public BinderService<GsiService>, public BnGsiService { enum class AccessLevel { System, SystemOrShell }; binder::Status CheckUid(AccessLevel level = AccessLevel::System); - bool CreateInstallStatusFile(); + + // Mark install completion, and reset boot attempt counter. + // Next boot will try to boot into DSU. + bool ResetBootAttemptCounter(); + bool SetBootMode(bool one_shot); static android::wp<GsiService> sInstance; |