Read boot image version from ro.bootimage.build.date.utc
This change re-defines boot image downgrade check logic. The
sysprop ro.bootimage.build.date.utc is checked instead. If the
sysprop ro.build.ab_update.gki.prevent_downgrade_version is not set,
any detected downgrades are suppressed.
Bug: 162554855
Bug: 162623577
Bug: 169169031
Test: pass
Change-Id: Ib86cb40576a852e0654a4c22d81c876d0315d0d2
diff --git a/hardware_android.cc b/hardware_android.cc
index fc6e1dc..a659bf6 100644
--- a/hardware_android.cc
+++ b/hardware_android.cc
@@ -17,7 +17,6 @@
#include "update_engine/hardware_android.h"
#include <sys/types.h>
-#include <sys/utsname.h>
#include <memory>
#include <string>
@@ -28,8 +27,6 @@
#include <android-base/properties.h>
#include <base/files/file_util.h>
#include <bootloader_message/bootloader_message.h>
-#include <kver/kernel_release.h>
-#include <kver/utils.h>
#include "update_engine/common/error_code_utils.h"
#include "update_engine/common/hardware.h"
@@ -39,8 +36,6 @@
using android::base::GetBoolProperty;
using android::base::GetIntProperty;
using android::base::GetProperty;
-using android::kver::IsKernelUpdateValid;
-using android::kver::KernelRelease;
using std::string;
namespace chromeos_update_engine {
@@ -62,6 +57,19 @@
"");
}
+ErrorCode IsTimestampNewerLogged(const std::string& partition_name,
+ const std::string& old_version,
+ const std::string& new_version) {
+ auto error_code = utils::IsTimestampNewer(old_version, new_version);
+ if (error_code != ErrorCode::kSuccess) {
+ LOG(WARNING) << "Timestamp check failed with "
+ << utils::ErrorCodeToString(error_code) << ": "
+ << partition_name << " Partition timestamp: " << old_version
+ << " Update timestamp: " << new_version;
+ }
+ return error_code;
+}
+
} // namespace
namespace hardware {
@@ -242,14 +250,8 @@
string HardwareAndroid::GetVersionForLogging(
const string& partition_name) const {
if (partition_name == "boot") {
- struct utsname buf;
- if (uname(&buf) != 0) {
- PLOG(ERROR) << "Unable to call uname()";
- return "";
- }
- auto kernel_release =
- KernelRelease::Parse(buf.release, true /* allow_suffix */);
- return kernel_release.has_value() ? kernel_release->string() : "";
+ // ro.bootimage.build.date.utc
+ return GetPartitionBuildDate("bootimage");
}
return GetPartitionBuildDate(partition_name);
}
@@ -257,61 +259,33 @@
ErrorCode HardwareAndroid::IsPartitionUpdateValid(
const string& partition_name, const string& new_version) const {
if (partition_name == "boot") {
- struct utsname buf;
- if (uname(&buf) != 0) {
- PLOG(ERROR) << "Unable to call uname()";
- return ErrorCode::kError;
+ const auto old_version = GetPartitionBuildDate("bootimage");
+ auto error_code =
+ IsTimestampNewerLogged(partition_name, old_version, new_version);
+ if (error_code == ErrorCode::kPayloadTimestampError) {
+ bool prevent_downgrade =
+ android::sysprop::GkiProperties::prevent_downgrade_version().value_or(
+ false);
+ if (!prevent_downgrade) {
+ LOG(WARNING) << "Downgrade of boot image is detected, but permitting "
+ "update because device does not prevent boot image "
+ "downgrade";
+ // If prevent_downgrade_version sysprop is not explicitly set, permit
+ // downgrade in boot image version.
+ // Even though error_code is overridden here, always call
+ // IsTimestampNewerLogged to produce log messages.
+ error_code = ErrorCode::kSuccess;
+ }
}
- bool prevent_downgrade =
- android::sysprop::GkiProperties::prevent_downgrade_version().value_or(
- false);
- return IsKernelUpdateValid(buf.release, new_version, prevent_downgrade);
+ return error_code;
}
const auto old_version = GetPartitionBuildDate(partition_name);
// TODO(zhangkelvin) for some partitions, missing a current timestamp should
// be an error, e.g. system, vendor, product etc.
- auto error_code = utils::IsTimestampNewer(old_version, new_version);
- if (error_code != ErrorCode::kSuccess) {
- LOG(ERROR) << "Timestamp check failed with "
- << utils::ErrorCodeToString(error_code)
- << " Partition timestamp: " << old_version
- << " Update timestamp: " << new_version;
- }
+ auto error_code =
+ IsTimestampNewerLogged(partition_name, old_version, new_version);
return error_code;
}
-ErrorCode HardwareAndroid::IsKernelUpdateValid(const string& old_release,
- const string& new_release,
- bool prevent_downgrade) {
- // Check that the package either contain an empty version (indicating that the
- // new build does not use GKI), or a valid GKI kernel release.
- std::optional<KernelRelease> new_kernel_release;
- if (new_release.empty()) {
- LOG(INFO) << "New build does not contain GKI.";
- } else {
- new_kernel_release =
- KernelRelease::Parse(new_release, true /* allow_suffix */);
- if (!new_kernel_release.has_value()) {
- LOG(ERROR) << "New kernel release is not valid GKI kernel release: "
- << new_release;
- return ErrorCode::kDownloadManifestParseError;
- }
- }
-
- auto old_kernel_release =
- KernelRelease::Parse(old_release, true /* allow_suffix */);
- bool is_update_valid = android::kver::IsKernelUpdateValid(old_kernel_release,
- new_kernel_release);
-
- if (!is_update_valid) {
- if (prevent_downgrade) {
- return ErrorCode::kPayloadTimestampError;
- }
- LOG(WARNING) << "Boot version downgrade detected, allowing update because "
- << "prevent_downgrade_version sysprop is not set.";
- }
- return ErrorCode::kSuccess;
-}
-
} // namespace chromeos_update_engine