Loading install/include/install/install.h +1 −1 Original line number Diff line number Diff line Loading @@ -65,7 +65,7 @@ bool ReadMetadataFromPackage(ZipArchiveHandle zip, std::map<std::string, std::st // pre-device and serial number (if presents). A/B OTA specific checks: pre-build version, // fingerprint, timestamp. bool CheckPackageMetadata(const std::map<std::string, std::string>& metadata, OtaType ota_type, RecoveryUI* ui); RecoveryUI* ui, bool spl_downgrade_approved = false); // Ensures the path to the update package is mounted. Also set the |should_use_fuse| to true if the // package stays on a removable media. Loading install/install.cpp +20 −9 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ using namespace std::chrono_literals; bool ask_to_continue_unverified(Device* device); bool ask_to_continue_downgrade(Device* device); bool ask_to_continue_spl_downgrade(Device* device); static constexpr int kRecoveryApiVersion = 3; // We define RECOVERY_API_VERSION in Android.mk, which will be picked up by build system and packed Loading Loading @@ -154,7 +155,7 @@ static void ReadSourceTargetBuild(const std::map<std::string, std::string>& meta // Downgrading is not allowed unless explicitly enabled in the package and only for // incremental packages. static bool CheckAbSpecificMetadata(const std::map<std::string, std::string>& metadata, RecoveryUI* ui) { RecoveryUI* ui, bool spl_downgrade_approved) { // 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"); Loading Loading @@ -185,10 +186,10 @@ static bool CheckAbSpecificMetadata(const std::map<std::string, std::string>& me !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 " LOG(WARNING) << "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."; << " this is considered a downgrade"; undeclared_downgrade = true; } else if (pkg_pre_build_fingerprint.empty()) { LOG(ERROR) << "Downgrade package must have a pre-build version set, not allowed."; Loading @@ -207,7 +208,7 @@ static bool CheckAbSpecificMetadata(const std::map<std::string, std::string>& me } } if (undeclared_downgrade && if (!spl_downgrade_approved && undeclared_downgrade && !(ui->IsTextVisible() && ask_to_continue_downgrade(ui->GetDevice()))) { return false; } Loading @@ -216,7 +217,7 @@ static bool CheckAbSpecificMetadata(const std::map<std::string, std::string>& me } bool CheckPackageMetadata(const std::map<std::string, std::string>& metadata, OtaType ota_type, RecoveryUI* ui) { RecoveryUI* ui, bool spl_downgrade_approved) { auto package_ota_type = get_value(metadata, "ota-type"); auto expected_ota_type = OtaTypeToString(ota_type); if (ota_type != OtaType::AB && ota_type != OtaType::BRICK) { Loading Loading @@ -273,7 +274,7 @@ bool CheckPackageMetadata(const std::map<std::string, std::string>& metadata, Ot } if (ota_type == OtaType::AB) { return CheckAbSpecificMetadata(metadata, ui); return CheckAbSpecificMetadata(metadata, ui, spl_downgrade_approved); } return true; Loading Loading @@ -423,11 +424,21 @@ static InstallResult TryUpdateBinary(Package* package, bool* wipe_cache, bool device_only_supports_ab = device_supports_ab && !ab_device_supports_nonab; bool device_supports_virtual_ab = android::base::GetBoolProperty("ro.virtual_ab.enabled", false); bool spl_downgrade_approved = false; const auto allow_spl_downgrade = android::base::GetBoolProperty("persist.vendor.recovery_allow_spl_downgrade", false); const auto current_spl = android::base::GetProperty("ro.build.version.security_patch", ""); if (ViolatesSPLDowngrade(zip, current_spl)) { if (!allow_spl_downgrade || !ui->IsTextVisible()) { LOG(ERROR) << "Denying OTA because it's SPL downgrade"; return INSTALL_ERROR; } if (!ask_to_continue_spl_downgrade(device)) { LOG(ERROR) << "User denied SPL downgrade"; return INSTALL_ERROR; } spl_downgrade_approved = true; } if (package_is_ab) { CHECK(package->GetType() == PackageType::kFile); Loading @@ -438,7 +449,7 @@ static InstallResult TryUpdateBinary(Package* package, bool* wipe_cache, // Package does not declare itself as an A/B package, but device only supports A/B; // still calls CheckPackageMetadata to get a meaningful error message. if (package_is_ab || device_only_supports_ab) { if (!CheckPackageMetadata(metadata, OtaType::AB, ui)) { if (!CheckPackageMetadata(metadata, OtaType::AB, ui, spl_downgrade_approved)) { log_buffer->push_back(android::base::StringPrintf("error: %d", kUpdateBinaryCommandFailure)); return INSTALL_ERROR; } Loading install/spl_check.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -30,7 +30,7 @@ bool ViolatesSPLDowngrade(const build::tools::releasetools::OtaMetadata& metadat // example, 05 for May). Otherwise this comparison doesn't work. We don't expect SPL date formats // to change, leave this as is. if (post_spl < current_spl) { LOG(ERROR) << "Current SPL: " << current_spl << " Target SPL: " << post_spl LOG(WARNING) << "Current SPL: " << current_spl << " Target SPL: " << post_spl << " this is considered a downgrade"; if (metadata.spl_downgrade() || metadata.downgrade()) { LOG(WARNING) Loading install/wipe_device.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -169,7 +169,7 @@ static bool CheckWipePackage(Package* wipe_package, RecoveryUI* ui) { return false; } return CheckPackageMetadata(metadata, OtaType::BRICK, ui); return CheckPackageMetadata(metadata, OtaType::BRICK, ui, false); } bool WipeAbDevice(Device* device, size_t wipe_package_size) { Loading recovery.cpp +13 −0 Original line number Diff line number Diff line Loading @@ -190,6 +190,19 @@ bool ask_to_continue_downgrade(Device* device) { } } bool ask_to_continue_spl_downgrade(Device* device) { if (get_build_type() == "user") { return false; } else { device->GetUI()->SetProgressType(RecoveryUI::EMPTY); return yes_no(device, "WARNING: Security patch level downgrade detected. " "This may require formatting data. " "Device may brick if hardware rollback protection is enabled. ", "Install anyway?"); } } static bool ask_to_wipe_data(Device* device) { std::vector<std::string> headers{ "Format user data?", "This includes internal storage.", "THIS CANNOT BE UNDONE!" }; std::vector<std::string> items{ " Cancel", " Format data" }; Loading Loading
install/include/install/install.h +1 −1 Original line number Diff line number Diff line Loading @@ -65,7 +65,7 @@ bool ReadMetadataFromPackage(ZipArchiveHandle zip, std::map<std::string, std::st // pre-device and serial number (if presents). A/B OTA specific checks: pre-build version, // fingerprint, timestamp. bool CheckPackageMetadata(const std::map<std::string, std::string>& metadata, OtaType ota_type, RecoveryUI* ui); RecoveryUI* ui, bool spl_downgrade_approved = false); // Ensures the path to the update package is mounted. Also set the |should_use_fuse| to true if the // package stays on a removable media. Loading
install/install.cpp +20 −9 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ using namespace std::chrono_literals; bool ask_to_continue_unverified(Device* device); bool ask_to_continue_downgrade(Device* device); bool ask_to_continue_spl_downgrade(Device* device); static constexpr int kRecoveryApiVersion = 3; // We define RECOVERY_API_VERSION in Android.mk, which will be picked up by build system and packed Loading Loading @@ -154,7 +155,7 @@ static void ReadSourceTargetBuild(const std::map<std::string, std::string>& meta // Downgrading is not allowed unless explicitly enabled in the package and only for // incremental packages. static bool CheckAbSpecificMetadata(const std::map<std::string, std::string>& metadata, RecoveryUI* ui) { RecoveryUI* ui, bool spl_downgrade_approved) { // 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"); Loading Loading @@ -185,10 +186,10 @@ static bool CheckAbSpecificMetadata(const std::map<std::string, std::string>& me !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 " LOG(WARNING) << "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."; << " this is considered a downgrade"; undeclared_downgrade = true; } else if (pkg_pre_build_fingerprint.empty()) { LOG(ERROR) << "Downgrade package must have a pre-build version set, not allowed."; Loading @@ -207,7 +208,7 @@ static bool CheckAbSpecificMetadata(const std::map<std::string, std::string>& me } } if (undeclared_downgrade && if (!spl_downgrade_approved && undeclared_downgrade && !(ui->IsTextVisible() && ask_to_continue_downgrade(ui->GetDevice()))) { return false; } Loading @@ -216,7 +217,7 @@ static bool CheckAbSpecificMetadata(const std::map<std::string, std::string>& me } bool CheckPackageMetadata(const std::map<std::string, std::string>& metadata, OtaType ota_type, RecoveryUI* ui) { RecoveryUI* ui, bool spl_downgrade_approved) { auto package_ota_type = get_value(metadata, "ota-type"); auto expected_ota_type = OtaTypeToString(ota_type); if (ota_type != OtaType::AB && ota_type != OtaType::BRICK) { Loading Loading @@ -273,7 +274,7 @@ bool CheckPackageMetadata(const std::map<std::string, std::string>& metadata, Ot } if (ota_type == OtaType::AB) { return CheckAbSpecificMetadata(metadata, ui); return CheckAbSpecificMetadata(metadata, ui, spl_downgrade_approved); } return true; Loading Loading @@ -423,11 +424,21 @@ static InstallResult TryUpdateBinary(Package* package, bool* wipe_cache, bool device_only_supports_ab = device_supports_ab && !ab_device_supports_nonab; bool device_supports_virtual_ab = android::base::GetBoolProperty("ro.virtual_ab.enabled", false); bool spl_downgrade_approved = false; const auto allow_spl_downgrade = android::base::GetBoolProperty("persist.vendor.recovery_allow_spl_downgrade", false); const auto current_spl = android::base::GetProperty("ro.build.version.security_patch", ""); if (ViolatesSPLDowngrade(zip, current_spl)) { if (!allow_spl_downgrade || !ui->IsTextVisible()) { LOG(ERROR) << "Denying OTA because it's SPL downgrade"; return INSTALL_ERROR; } if (!ask_to_continue_spl_downgrade(device)) { LOG(ERROR) << "User denied SPL downgrade"; return INSTALL_ERROR; } spl_downgrade_approved = true; } if (package_is_ab) { CHECK(package->GetType() == PackageType::kFile); Loading @@ -438,7 +449,7 @@ static InstallResult TryUpdateBinary(Package* package, bool* wipe_cache, // Package does not declare itself as an A/B package, but device only supports A/B; // still calls CheckPackageMetadata to get a meaningful error message. if (package_is_ab || device_only_supports_ab) { if (!CheckPackageMetadata(metadata, OtaType::AB, ui)) { if (!CheckPackageMetadata(metadata, OtaType::AB, ui, spl_downgrade_approved)) { log_buffer->push_back(android::base::StringPrintf("error: %d", kUpdateBinaryCommandFailure)); return INSTALL_ERROR; } Loading
install/spl_check.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -30,7 +30,7 @@ bool ViolatesSPLDowngrade(const build::tools::releasetools::OtaMetadata& metadat // example, 05 for May). Otherwise this comparison doesn't work. We don't expect SPL date formats // to change, leave this as is. if (post_spl < current_spl) { LOG(ERROR) << "Current SPL: " << current_spl << " Target SPL: " << post_spl LOG(WARNING) << "Current SPL: " << current_spl << " Target SPL: " << post_spl << " this is considered a downgrade"; if (metadata.spl_downgrade() || metadata.downgrade()) { LOG(WARNING) Loading
install/wipe_device.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -169,7 +169,7 @@ static bool CheckWipePackage(Package* wipe_package, RecoveryUI* ui) { return false; } return CheckPackageMetadata(metadata, OtaType::BRICK, ui); return CheckPackageMetadata(metadata, OtaType::BRICK, ui, false); } bool WipeAbDevice(Device* device, size_t wipe_package_size) { Loading
recovery.cpp +13 −0 Original line number Diff line number Diff line Loading @@ -190,6 +190,19 @@ bool ask_to_continue_downgrade(Device* device) { } } bool ask_to_continue_spl_downgrade(Device* device) { if (get_build_type() == "user") { return false; } else { device->GetUI()->SetProgressType(RecoveryUI::EMPTY); return yes_no(device, "WARNING: Security patch level downgrade detected. " "This may require formatting data. " "Device may brick if hardware rollback protection is enabled. ", "Install anyway?"); } } static bool ask_to_wipe_data(Device* device) { std::vector<std::string> headers{ "Format user data?", "This includes internal storage.", "THIS CANNOT BE UNDONE!" }; std::vector<std::string> items{ " Cancel", " Format data" }; Loading