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/Android.bp b/Android.bp
index 193928b..28e1bab 100644
--- a/Android.bp
+++ b/Android.bp
@@ -261,7 +261,6 @@
static_libs: [
"gkiprops",
- "libkver",
"libpayload_consumer",
"libupdate_engine_boot_control",
],
@@ -392,7 +391,6 @@
"libbrillo-stream",
"libbrillo",
"libchrome",
- "libkver",
],
target: {
recovery: {
@@ -686,7 +684,6 @@
"common/utils_unittest.cc",
"dynamic_partition_control_android_unittest.cc",
"libcurl_http_fetcher_unittest.cc",
- "hardware_android_unittest.cc",
"payload_consumer/bzip_extent_writer_unittest.cc",
"payload_consumer/cached_file_descriptor_unittest.cc",
"payload_consumer/certificate_parser_android_unittest.cc",
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
diff --git a/hardware_android.h b/hardware_android.h
index 552cb53..d8fbbbe 100644
--- a/hardware_android.h
+++ b/hardware_android.h
@@ -22,7 +22,6 @@
#include <base/macros.h>
#include <base/time/time.h>
-#include <gtest/gtest_prod.h>
#include "update_engine/common/error_code.h"
#include "update_engine/common/hardware.h"
@@ -68,18 +67,6 @@
const std::string& new_version) const override;
private:
- FRIEND_TEST(HardwareAndroidTest, IsKernelUpdateValid);
-
- // Helper for IsPartitionUpdateValid. Check an update from |old_release|
- // to |new_release| is valid or not.
- // - If |new_release| is invalid, return kDownloadManifestParseError
- // - If downgrade detected, kPayloadTimestampError if |prevent_downgrade| is
- // set to true, or kSuccess if |prevent_downgrade| is set to false
- // - If update is valid, kSuccess.
- static ErrorCode IsKernelUpdateValid(const std::string& old_release,
- const std::string& new_release,
- bool prevent_downgrade);
-
DISALLOW_COPY_AND_ASSIGN(HardwareAndroid);
};
diff --git a/hardware_android_unittest.cc b/hardware_android_unittest.cc
deleted file mode 100644
index 679356c..0000000
--- a/hardware_android_unittest.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-//
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "update_engine/common/error_code.h"
-#include "update_engine/hardware_android.h"
-
-using ::testing::NiceMock;
-using ::testing::Return;
-
-namespace chromeos_update_engine {
-
-TEST(HardwareAndroidTest, IsKernelUpdateValid) {
- EXPECT_EQ(ErrorCode::kSuccess,
- HardwareAndroid::IsKernelUpdateValid(
- "5.4.42-not-gki", "", true /*prevent_downgrade*/))
- << "Legacy update should be fine";
-
- EXPECT_EQ(
- ErrorCode::kSuccess,
- HardwareAndroid::IsKernelUpdateValid(
- "5.4.42-not-gki", "5.4.42-android12-0", true /*prevent_downgrade*/))
- << "Update to GKI should be fine";
-
- EXPECT_EQ(ErrorCode::kDownloadManifestParseError,
- HardwareAndroid::IsKernelUpdateValid(
- "5.4.42-not-gki", "5.4.42-not-gki", true /*prevent_downgrade*/))
- << "Should report parse error for invalid version field";
-
- EXPECT_EQ(ErrorCode::kSuccess,
- HardwareAndroid::IsKernelUpdateValid("5.4.42-android12-0-something",
- "5.4.42-android12-0-something",
- true /*prevent_downgrade*/))
- << "Self update should be fine";
-
- EXPECT_EQ(ErrorCode::kSuccess,
- HardwareAndroid::IsKernelUpdateValid("5.4.42-android12-0-something",
- "5.4.43-android12-0-something",
- true /*prevent_downgrade*/))
- << "Sub-level update should be fine";
-
- EXPECT_EQ(
- ErrorCode::kSuccess,
- HardwareAndroid::IsKernelUpdateValid("5.4.42-android12-0-something",
- "5.10.10-android12-0-something",
- true /*prevent_downgrade*/))
- << "KMI version update should be fine";
-
- EXPECT_EQ(ErrorCode::kPayloadTimestampError,
- HardwareAndroid::IsKernelUpdateValid("5.4.42-android12-0-something",
- "5.4.5-android12-0-something",
- true /*prevent_downgrade*/))
- << "Should detect sub-level downgrade";
-
- EXPECT_EQ(ErrorCode::kPayloadTimestampError,
- HardwareAndroid::IsKernelUpdateValid("5.4.42-android12-0-something",
- "5.1.5-android12-0-something",
- true /*prevent_downgrade*/))
- << "Should detect KMI version downgrade";
-
- EXPECT_EQ(ErrorCode::kSuccess,
- HardwareAndroid::IsKernelUpdateValid("5.4.42-android12-0-something",
- "5.4.5-android12-0-something",
- false /*prevent_downgrade*/))
- << "Should suppress sub-level downgrade";
-}
-
-} // namespace chromeos_update_engine