summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--daemon.cpp3
-rw-r--r--gsi_service.cpp80
-rw-r--r--gsi_service.h7
3 files changed, 65 insertions, 25 deletions
diff --git a/daemon.cpp b/daemon.cpp
index a1ee809..2123599 100644
--- a/daemon.cpp
+++ b/daemon.cpp
@@ -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;