diff options
| author | Alessandro Astone <ales.astone@gmail.com> | 2020-03-17 23:06:52 +0100 |
|---|---|---|
| committer | doc HD <doc.divxm@gmail.com> | 2020-03-31 23:20:17 +0300 |
| commit | df601c3a2adf9a02a8b00783a0aab59e1d08475b (patch) | |
| tree | 37de02dd1a417074a8994e0be3efc4ee46bf94be | |
| parent | 0a93002775a7ae69a53e9a32997a1b42b6ef9837 (diff) | |
recovery: allow A/B updater to downgradeq10.0-backup
Change-Id: Iaa1fb7838fb958e69fb3104fef7743aafad12b1b
| -rw-r--r-- | install/adb_install.cpp | 12 | ||||
| -rw-r--r-- | install/fuse_sdcard_install.cpp | 9 | ||||
| -rw-r--r-- | install/include/install/install.h | 7 | ||||
| -rw-r--r-- | install/install.cpp | 62 | ||||
| -rw-r--r-- | recovery.cpp | 11 |
5 files changed, 64 insertions, 37 deletions
diff --git a/install/adb_install.cpp b/install/adb_install.cpp index fd1ca1a2..d82238ec 100644 --- a/install/adb_install.cpp +++ b/install/adb_install.cpp @@ -114,11 +114,17 @@ static auto AdbInstallPackageHandler(Device* device, int* result) { } ui->CancelWaitKey(); - *result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, false, false, 0, true /* verify */, ui); + *result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, false, false, 0, true /* verify */, + false /* allow_ab_downgrade */, ui); if (*result == INSTALL_UNVERIFIED && ui->IsTextVisible() && ask_to_continue_unverified(device)) { - *result = - install_package(FUSE_SIDELOAD_HOST_PATHNAME, false, false, 0, false /* verify */, ui); + *result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, false, false, 0, false /* verify */, + false /* allow_ab_downgrade */, ui); + } + if (*result == INSTALL_DOWNGRADE && + ui->IsTextVisible() && ask_to_continue_downgrade(device)) { + *result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, false, false, 0, false /* verify */, + true /* allow_ab_downgrade */, ui); } break; } diff --git a/install/fuse_sdcard_install.cpp b/install/fuse_sdcard_install.cpp index e7f4c0d3..cc0a3e77 100644 --- a/install/fuse_sdcard_install.cpp +++ b/install/fuse_sdcard_install.cpp @@ -191,11 +191,16 @@ int ApplyFromSdcard(Device* device, RecoveryUI* ui) { } result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, false, false, 0 /*retry_count*/, - true /* verify */, ui); + true /* verify */, false /* allow_ab_downgrade */, ui); if (result == INSTALL_UNVERIFIED && ask_to_continue_unverified(device)) { result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, false, false, 0 /*retry_count*/, - false /* verify */, ui); + false /* verify */, false /* allow_ab_downgrade */, ui); } + if (result == INSTALL_DOWNGRADE && ask_to_continue_downgrade(device)) { + result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, false, false, 0 /*retry_count*/, + false /* verify */, true /* allow_ab_downgrade */, ui); + } + break; } diff --git a/install/include/install/install.h b/install/include/install/install.h index a0763af2..85c197de 100644 --- a/install/include/install/install.h +++ b/install/include/install/install.h @@ -38,6 +38,7 @@ enum InstallResult { INSTALL_KEY_INTERRUPTED, INSTALL_REBOOT, INSTALL_UNVERIFIED, + INSTALL_DOWNGRADE, }; enum class OtaType { @@ -50,7 +51,7 @@ enum class OtaType { // successful installation if |should_wipe_cache| is true or an updater command asks to wipe the // cache. int install_package(const std::string& package, bool should_wipe_cache, bool needs_mount, - int retry_count, bool verify, RecoveryUI* ui); + int retry_count, bool verify, bool allow_ab_downgrade, RecoveryUI* ui); // Verifies the package by ota keys. Returns true if the package is verified successfully, // otherwise returns false. @@ -70,7 +71,9 @@ bool verify_package_compatibility(ZipArchiveHandle package_zip); // Checks if the the metadata in the OTA package has expected values. Returns 0 on success. // Mandatory checks: ota-type, pre-device and serial number(if presents) // AB OTA specific checks: pre-build version, fingerprint, timestamp. -int CheckPackageMetadata(const std::map<std::string, std::string>& metadata, OtaType ota_type); +int CheckPackageMetadata(const std::map<std::string, std::string>& metadata, OtaType ota_type, + bool allow_ab_downgrade = false); // Defined in recovery.cpp, just declare it and it will eventually link fine. bool ask_to_continue_unverified(Device* device); +bool ask_to_continue_downgrade(Device* device);
\ No newline at end of file diff --git a/install/install.cpp b/install/install.cpp index d376433b..80e5f1bb 100644 --- a/install/install.cpp +++ b/install/install.cpp @@ -138,7 +138,8 @@ static void ReadSourceTargetBuild(const std::map<std::string, std::string>& meta // Checks the build version, fingerprint and timestamp in the metadata of the A/B package. // Downgrading is not allowed unless explicitly enabled in the package and only for // incremental packages. -static int CheckAbSpecificMetadata(const std::map<std::string, std::string>& metadata) { +static int CheckAbSpecificMetadata(const std::map<std::string, std::string>& metadata, + bool allow_ab_downgrade) { // Incremental updates should match the current build. auto device_pre_build = android::base::GetProperty("ro.build.version.incremental", ""); auto pkg_pre_build = get_value(metadata, "pre-build-incremental"); @@ -157,32 +158,35 @@ static int CheckAbSpecificMetadata(const std::map<std::string, std::string>& met } // Check for downgrade version. - int64_t build_timestamp = - android::base::GetIntProperty("ro.build.date.utc", std::numeric_limits<int64_t>::max()); - int64_t pkg_post_timestamp = 0; - // We allow to full update to the same version we are running, in case there - // is a problem with the current copy of that version. - auto pkg_post_timestamp_string = get_value(metadata, "post-timestamp"); - if (pkg_post_timestamp_string.empty() || - !android::base::ParseInt(pkg_post_timestamp_string, &pkg_post_timestamp) || - pkg_post_timestamp < build_timestamp) { - if (get_value(metadata, "ota-downgrade") != "yes") { - LOG(ERROR) << "Update package is older than the current build, expected a build " - "newer than timestamp " - << build_timestamp << " but package has timestamp " << pkg_post_timestamp - << " and downgrade not allowed."; - return INSTALL_ERROR; - } - if (pkg_pre_build_fingerprint.empty()) { - LOG(ERROR) << "Downgrade package must have a pre-build version set, not allowed."; - return INSTALL_ERROR; + if (!allow_ab_downgrade) { + int64_t build_timestamp = + android::base::GetIntProperty("ro.build.date.utc", std::numeric_limits<int64_t>::max()); + int64_t pkg_post_timestamp = 0; + // We allow to full update to the same version we are running, in case there + // is a problem with the current copy of that version. + auto pkg_post_timestamp_string = get_value(metadata, "post-timestamp"); + if (pkg_post_timestamp_string.empty() || + !android::base::ParseInt(pkg_post_timestamp_string, &pkg_post_timestamp) || + pkg_post_timestamp < build_timestamp) { + if (get_value(metadata, "ota-downgrade") != "yes") { + LOG(ERROR) << "Update package is older than the current build, expected a build " + "newer than timestamp " + << build_timestamp << " but package has timestamp " << pkg_post_timestamp + << " and downgrade not allowed."; + return INSTALL_DOWNGRADE; + } + if (pkg_pre_build_fingerprint.empty()) { + LOG(ERROR) << "Downgrade package must have a pre-build version set, not allowed."; + return INSTALL_DOWNGRADE; + } } } return 0; } -int CheckPackageMetadata(const std::map<std::string, std::string>& metadata, OtaType ota_type) { +int CheckPackageMetadata(const std::map<std::string, std::string>& metadata, OtaType ota_type, + bool allow_ab_downgrade) { auto device = android::base::GetProperty("ro.product.device", ""); auto pkg_device = get_value(metadata, "pre-device"); if (pkg_device != device || pkg_device.empty()) { @@ -209,7 +213,7 @@ int CheckPackageMetadata(const std::map<std::string, std::string>& metadata, Ota } if (ota_type == OtaType::AB) { - return CheckAbSpecificMetadata(metadata); + return CheckAbSpecificMetadata(metadata, allow_ab_downgrade); } return 0; @@ -313,14 +317,14 @@ static void log_max_temperature(int* max_temperature, const std::atomic<bool>& l // If the package contains an update binary, extract it and run it. static int try_update_binary(const std::string& package, ZipArchiveHandle zip, bool* wipe_cache, std::vector<std::string>* log_buffer, int retry_count, - int* max_temperature, RecoveryUI* ui) { + bool allow_ab_downgrade, int* max_temperature, RecoveryUI* ui) { std::map<std::string, std::string> metadata; bool is_ab_ota = false; if (ReadMetadataFromPackage(zip, &metadata)) { ReadSourceTargetBuild(metadata, log_buffer); if (get_value(metadata, "ota-type") == OtaTypeToString(OtaType::AB)) { is_ab_ota = true; - int check_status = CheckPackageMetadata(metadata, OtaType::AB); + int check_status = CheckPackageMetadata(metadata, OtaType::AB, allow_ab_downgrade); if (check_status != 0) { return check_status; } @@ -556,7 +560,7 @@ bool verify_package_compatibility(ZipArchiveHandle package_zip) { static int really_install_package(const std::string& path, bool* wipe_cache, bool needs_mount, std::vector<std::string>* log_buffer, int retry_count, - bool verify, int* max_temperature, RecoveryUI* ui) { + bool verify, bool allow_ab_downgrade, int* max_temperature, RecoveryUI* ui) { ui->SetBackground(RecoveryUI::INSTALLING_UPDATE); ui->Print("Finding update package...\n"); // Give verification half the progress bar... @@ -607,8 +611,8 @@ static int really_install_package(const std::string& path, bool* wipe_cache, boo ui->Print("Retry attempt: %d\n", retry_count); } ui->SetEnableReboot(false); - int result = - try_update_binary(path, zip, wipe_cache, log_buffer, retry_count, max_temperature, ui); + int result = try_update_binary(path, zip, wipe_cache, log_buffer, retry_count, allow_ab_downgrade, + max_temperature, ui); ui->SetEnableReboot(true); ui->Print("\n"); @@ -616,7 +620,7 @@ static int really_install_package(const std::string& path, bool* wipe_cache, boo } int install_package(const std::string& path, bool should_wipe_cache, bool needs_mount, - int retry_count, bool verify, RecoveryUI* ui) { + int retry_count, bool verify, bool allow_ab_downgrade, RecoveryUI* ui) { CHECK(!path.empty()); auto start = std::chrono::system_clock::now(); @@ -632,7 +636,7 @@ int install_package(const std::string& path, bool should_wipe_cache, bool needs_ } else { bool updater_wipe_cache = false; result = really_install_package(path, &updater_wipe_cache, needs_mount, &log_buffer, - retry_count, verify, &max_temperature, ui); + retry_count, verify, allow_ab_downgrade, &max_temperature, ui); should_wipe_cache = should_wipe_cache || updater_wipe_cache; } diff --git a/recovery.cpp b/recovery.cpp index f3a78cc1..ff04b49d 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -186,6 +186,15 @@ bool ask_to_continue_unverified(Device* device) { } } +bool ask_to_continue_downgrade(Device* device) { + if (get_build_type() == "user") { + return false; + } else { + ui->SetProgressType(RecoveryUI::EMPTY); + return yes_no(device, "This package will downgrade your system", "Install anyway?"); + } +} + static bool ask_to_wipe_data(Device* device) { std::vector<std::string> headers{ "Wipe all user data?", " THIS CAN NOT BE UNDONE!" }; std::vector<std::string> items{ " Cancel", " Factory data reset" }; @@ -918,7 +927,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri } status = install_package(update_package, should_wipe_cache, true, retry_count, - true /* verify */, ui); + true /* verify */, false /* allow_ab_downgrade */, ui); if (status != INSTALL_SUCCESS) { ui->Print("Installation aborted.\n"); |
