Merge tag 'android-15.0.0_r6' of https://android.googlesource.com/platform/system/update_engine into HEAD
Android 15.0.0 Release 6 (AP4A.241205.013)
Change-Id: I6ce1ae6653367fa828ff7b8f96ca2b10de33b902
# -----BEGIN PGP SIGNATURE-----
#
# iF0EABECAB0WIQRDQNE1cO+UXoOBCWTorT+BmrEOeAUCZ1IsswAKCRDorT+BmrEO
# eBrEAJ4ohnC9n/8C9+wX+0gPLNq6bZG2YQCdHksLzlUXR8dfY9gAbJhI/Czl46M=
# =lVER
# -----END PGP SIGNATURE-----
# gpg: Signature faite le jeu 05 déc 2024 17:44:03 EST
# gpg: avec la clef DSA 4340D13570EF945E83810964E8AD3F819AB10E78
# gpg: Impossible de vérifier la signature : Pas de clef publique
diff --git a/aosp/dynamic_partition_control_android.cc b/aosp/dynamic_partition_control_android.cc
index d8df520..af46b35 100644
--- a/aosp/dynamic_partition_control_android.cc
+++ b/aosp/dynamic_partition_control_android.cc
@@ -199,7 +199,7 @@
};
bool success = false;
if (GetVirtualAbFeatureFlag().IsEnabled() && target_supports_snapshot_ &&
- force_writable && ExpectMetadataMounted()) {
+ slot != source_slot_ && force_writable && ExpectMetadataMounted()) {
// Only target partitions are mapped with force_writable. On Virtual
// A/B devices, target partitions may overlap with source partitions, so
// they must be mapped with snapshot.
@@ -317,6 +317,7 @@
void DynamicPartitionControlAndroid::Cleanup() {
UnmapAllPartitions();
+ LOG(INFO) << "UnmapAllPartitions done";
metadata_device_.reset();
if (GetVirtualAbFeatureFlag().IsEnabled()) {
snapshot_ = SnapshotManager::New();
@@ -324,6 +325,7 @@
snapshot_ = SnapshotManagerStub::New();
}
CHECK(snapshot_ != nullptr) << "Cannot initialize SnapshotManager.";
+ LOG(INFO) << "SnapshotManager initialized.";
}
bool DynamicPartitionControlAndroid::DeviceExists(const std::string& path) {
@@ -1245,7 +1247,7 @@
}
}
- bool force_writable = (slot != current_slot) && !not_in_payload;
+ const bool force_writable = !not_in_payload;
if (MapPartitionOnDeviceMapper(
super_device, partition_name_suffix, slot, force_writable, device)) {
return DynamicPartitionDeviceStatus::SUCCESS;
diff --git a/aosp/ota_extractor.cc b/aosp/ota_extractor.cc
index 713cfc3..42270f4 100644
--- a/aosp/ota_extractor.cc
+++ b/aosp/ota_extractor.cc
@@ -17,6 +17,7 @@
#include <array>
#include <cstdint>
#include <cstdio>
+#include <future>
#include <iterator>
#include <memory>
@@ -53,6 +54,7 @@
"",
"Comma separated list of partitions to extract, leave empty for "
"extracting all partitions");
+DEFINE_bool(single_thread, false, "Limit extraction to a single thread");
using chromeos_update_engine::DeltaArchiveManifest;
using chromeos_update_engine::PayloadMetadata;
@@ -93,6 +95,103 @@
return;
}
+bool ExtractImageFromPartition(const DeltaArchiveManifest& manifest,
+ const PartitionUpdate& partition,
+ const size_t data_begin,
+ int payload_fd,
+ std::string_view input_dir,
+ std::string_view output_dir) {
+ InstallOperationExecutor executor(manifest.block_size());
+ const base::FilePath output_dir_path(
+ base::StringPiece(output_dir.data(), output_dir.size()));
+ const base::FilePath input_dir_path(
+ base::StringPiece(input_dir.data(), input_dir.size()));
+ std::vector<unsigned char> blob;
+
+ LOG(INFO) << "Extracting partition " << partition.partition_name()
+ << " size: " << partition.new_partition_info().size();
+ const auto output_path =
+ output_dir_path.Append(partition.partition_name() + ".img").value();
+ auto out_fd =
+ std::make_shared<chromeos_update_engine::EintrSafeFileDescriptor>();
+ TEST_AND_RETURN_FALSE_ERRNO(
+ out_fd->Open(output_path.c_str(), O_RDWR | O_CREAT, 0644));
+ auto in_fd =
+ std::make_shared<chromeos_update_engine::EintrSafeFileDescriptor>();
+ if (partition.has_old_partition_info()) {
+ const auto input_path =
+ input_dir_path.Append(partition.partition_name() + ".img").value();
+ LOG(INFO) << "Incremental OTA detected for partition "
+ << partition.partition_name() << " opening source image "
+ << input_path;
+ CHECK(in_fd->Open(input_path.c_str(), O_RDONLY))
+ << " failed to open " << input_path;
+ }
+
+ for (const auto& op : partition.operations()) {
+ if (op.has_src_sha256_hash()) {
+ brillo::Blob actual_hash;
+ TEST_AND_RETURN_FALSE(fd_utils::ReadAndHashExtents(
+ in_fd, op.src_extents(), manifest.block_size(), &actual_hash));
+ CHECK_EQ(HexEncode(ToStringView(actual_hash)),
+ HexEncode(op.src_sha256_hash()))
+ << ", failed partition: " << partition.partition_name();
+ }
+
+ blob.resize(op.data_length());
+ const auto op_data_offset = data_begin + op.data_offset();
+ ssize_t bytes_read = 0;
+ TEST_AND_RETURN_FALSE(utils::PReadAll(
+ payload_fd, blob.data(), blob.size(), op_data_offset, &bytes_read));
+ if (op.has_data_sha256_hash()) {
+ brillo::Blob actual_hash;
+ TEST_AND_RETURN_FALSE(HashCalculator::RawHashOfData(blob, &actual_hash));
+ CHECK_EQ(HexEncode(ToStringView(actual_hash)),
+ HexEncode(op.data_sha256_hash()))
+ << ", failed partition: " << partition.partition_name();
+ }
+ auto direct_writer = std::make_unique<DirectExtentWriter>(out_fd);
+ if (op.type() == InstallOperation::ZERO) {
+ TEST_AND_RETURN_FALSE(
+ executor.ExecuteZeroOrDiscardOperation(op, std::move(direct_writer)));
+ } else if (op.type() == InstallOperation::REPLACE ||
+ op.type() == InstallOperation::REPLACE_BZ ||
+ op.type() == InstallOperation::REPLACE_XZ) {
+ TEST_AND_RETURN_FALSE(executor.ExecuteReplaceOperation(
+ op, std::move(direct_writer), blob.data()));
+ } else if (op.type() == InstallOperation::SOURCE_COPY) {
+ CHECK(in_fd->IsOpen())
+ << ", failed partition: " << partition.partition_name();
+ TEST_AND_RETURN_FALSE(executor.ExecuteSourceCopyOperation(
+ op, std::move(direct_writer), in_fd));
+ } else {
+ CHECK(in_fd->IsOpen())
+ << ", failed partition: " << partition.partition_name();
+ TEST_AND_RETURN_FALSE(executor.ExecuteDiffOperation(
+ op, std::move(direct_writer), in_fd, blob.data(), blob.size()));
+ }
+ }
+ WriteVerity(partition, out_fd, manifest.block_size());
+ int err =
+ truncate64(output_path.c_str(), partition.new_partition_info().size());
+ if (err) {
+ PLOG(ERROR) << "Failed to truncate " << output_path << " to "
+ << partition.new_partition_info().size();
+ }
+ brillo::Blob actual_hash;
+ TEST_AND_RETURN_FALSE(
+ HashCalculator::RawHashOfFile(output_path, &actual_hash));
+ CHECK_EQ(HexEncode(ToStringView(actual_hash)),
+ HexEncode(partition.new_partition_info().hash()))
+ << " Partition " << partition.partition_name()
+ << " hash mismatches. Either the source image or OTA package is "
+ "corrupted.";
+
+ LOG(INFO) << "Extracted partition " << partition.partition_name();
+
+ return true;
+}
+
bool ExtractImagesFromOTA(const DeltaArchiveManifest& manifest,
const PayloadMetadata& metadata,
int payload_fd,
@@ -100,97 +199,46 @@
std::string_view input_dir,
std::string_view output_dir,
const std::set<std::string>& partitions) {
- InstallOperationExecutor executor(manifest.block_size());
const size_t data_begin = metadata.GetMetadataSize() +
metadata.GetMetadataSignatureSize() +
payload_offset;
- const base::FilePath output_dir_path(
- base::StringPiece(output_dir.data(), output_dir.size()));
- const base::FilePath input_dir_path(
- base::StringPiece(input_dir.data(), input_dir.size()));
- std::vector<unsigned char> blob;
- for (const auto& partition : manifest.partitions()) {
- if (!partitions.empty() &&
- partitions.count(partition.partition_name()) == 0) {
- continue;
- }
- LOG(INFO) << "Extracting partition " << partition.partition_name()
- << " size: " << partition.new_partition_info().size();
- const auto output_path =
- output_dir_path.Append(partition.partition_name() + ".img").value();
- auto out_fd =
- std::make_shared<chromeos_update_engine::EintrSafeFileDescriptor>();
- TEST_AND_RETURN_FALSE_ERRNO(
- out_fd->Open(output_path.c_str(), O_RDWR | O_CREAT, 0644));
- auto in_fd =
- std::make_shared<chromeos_update_engine::EintrSafeFileDescriptor>();
- if (partition.has_old_partition_info()) {
- const auto input_path =
- input_dir_path.Append(partition.partition_name() + ".img").value();
- LOG(INFO) << "Incremental OTA detected for partition "
- << partition.partition_name() << " opening source image "
- << input_path;
- CHECK(in_fd->Open(input_path.c_str(), O_RDONLY))
- << " failed to open " << input_path;
- }
+ bool ret = true;
- for (const auto& op : partition.operations()) {
- if (op.has_src_sha256_hash()) {
- brillo::Blob actual_hash;
- TEST_AND_RETURN_FALSE(fd_utils::ReadAndHashExtents(
- in_fd, op.src_extents(), manifest.block_size(), &actual_hash));
- CHECK_EQ(HexEncode(ToStringView(actual_hash)),
- HexEncode(op.src_sha256_hash()));
- }
-
- blob.resize(op.data_length());
- const auto op_data_offset = data_begin + op.data_offset();
- ssize_t bytes_read = 0;
- TEST_AND_RETURN_FALSE(utils::PReadAll(
- payload_fd, blob.data(), blob.size(), op_data_offset, &bytes_read));
- if (op.has_data_sha256_hash()) {
- brillo::Blob actual_hash;
- TEST_AND_RETURN_FALSE(
- HashCalculator::RawHashOfData(blob, &actual_hash));
- CHECK_EQ(HexEncode(ToStringView(actual_hash)),
- HexEncode(op.data_sha256_hash()));
- }
- auto direct_writer = std::make_unique<DirectExtentWriter>(out_fd);
- if (op.type() == InstallOperation::ZERO) {
- TEST_AND_RETURN_FALSE(executor.ExecuteZeroOrDiscardOperation(
- op, std::move(direct_writer)));
- } else if (op.type() == InstallOperation::REPLACE ||
- op.type() == InstallOperation::REPLACE_BZ ||
- op.type() == InstallOperation::REPLACE_XZ) {
- TEST_AND_RETURN_FALSE(executor.ExecuteReplaceOperation(
- op, std::move(direct_writer), blob.data()));
- } else if (op.type() == InstallOperation::SOURCE_COPY) {
- CHECK(in_fd->IsOpen());
- TEST_AND_RETURN_FALSE(executor.ExecuteSourceCopyOperation(
- op, std::move(direct_writer), in_fd));
- } else {
- CHECK(in_fd->IsOpen());
- TEST_AND_RETURN_FALSE(executor.ExecuteDiffOperation(
- op, std::move(direct_writer), in_fd, blob.data(), blob.size()));
+ if (FLAGS_single_thread) {
+ for (const auto& partition : manifest.partitions()) {
+ if (!ExtractImageFromPartition(manifest,
+ partition,
+ data_begin,
+ payload_fd,
+ input_dir,
+ output_dir)) {
+ ret = false;
+ LOG(ERROR) << "Extraction of partition " << partition.partition_name()
+ << " failed";
+ break;
}
}
- WriteVerity(partition, out_fd, manifest.block_size());
- int err =
- truncate64(output_path.c_str(), partition.new_partition_info().size());
- if (err) {
- PLOG(ERROR) << "Failed to truncate " << output_path << " to "
- << partition.new_partition_info().size();
+ } else {
+ std::vector<std::pair<std::future<bool>, std::string>> futures;
+ for (const auto& partition : manifest.partitions()) {
+ futures.push_back(std::make_pair(std::async(std::launch::async,
+ ExtractImageFromPartition,
+ manifest,
+ partition,
+ data_begin,
+ payload_fd,
+ input_dir,
+ output_dir),
+ partition.partition_name()));
}
- brillo::Blob actual_hash;
- TEST_AND_RETURN_FALSE(
- HashCalculator::RawHashOfFile(output_path, &actual_hash));
- CHECK_EQ(HexEncode(ToStringView(actual_hash)),
- HexEncode(partition.new_partition_info().hash()))
- << " Partition " << partition.partition_name()
- << " hash mismatches. Either the source image or OTA package is "
- "corrupted.";
+ for (auto& future : futures) {
+ if (!future.first.get()) {
+ ret = false;
+ LOG(ERROR) << "Extraction of partition " << future.second << " failed";
+ }
+ }
}
- return true;
+ return ret;
}
} // namespace chromeos_update_engine
diff --git a/aosp/update_attempter_android.cc b/aosp/update_attempter_android.cc
index 0f6fc5c..857685f 100644
--- a/aosp/update_attempter_android.cc
+++ b/aosp/update_attempter_android.cc
@@ -299,6 +299,8 @@
install_plan_.is_resume = !payload_id.empty() &&
DeltaPerformer::CanResumeUpdate(prefs_, payload_id);
if (!install_plan_.is_resume) {
+ LOG(INFO) << "Starting a new update " << payload_url
+ << " size: " << payload_size << " offset: " << payload_offset;
boot_control_->GetDynamicPartitionControl()->Cleanup();
boot_control_->GetDynamicPartitionControl()->ResetUpdate(prefs_);
@@ -379,11 +381,26 @@
#endif // _UE_SIDELOAD
}
// Setup extra headers.
- if (!headers[kPayloadPropertyAuthorization].empty())
+ if (!headers[kPayloadPropertyAuthorization].empty()) {
fetcher->SetHeader("Authorization", headers[kPayloadPropertyAuthorization]);
- if (!headers[kPayloadPropertyUserAgent].empty())
+ }
+ if (!headers[kPayloadPropertyUserAgent].empty()) {
fetcher->SetHeader("User-Agent", headers[kPayloadPropertyUserAgent]);
-
+ }
+ if (!headers[kPayloadPropertyHTTPExtras].empty()) {
+ auto entries =
+ android::base::Split(headers[kPayloadPropertyHTTPExtras], " ");
+ for (auto& entry : entries) {
+ auto parts = android::base::Split(entry, ";");
+ if (parts.size() != 2) {
+ LOG(ERROR)
+ << "HTTP headers are not in expected format. "
+ "headers[kPayloadPropertyHTTPExtras] = key1;val1 key2;val2";
+ continue;
+ }
+ fetcher->SetHeader(parts[0], parts[1]);
+ }
+ }
if (!headers[kPayloadPropertyNetworkProxy].empty()) {
LOG(INFO) << "Using proxy url from payload headers: "
<< headers[kPayloadPropertyNetworkProxy];
@@ -848,6 +865,9 @@
boot_control_->GetDynamicPartitionControl()->Cleanup();
+ for (auto observer : daemon_state_->service_observers())
+ observer->SendPayloadApplicationComplete(error_code);
+
download_progress_ = 0;
UpdateStatus new_status =
(error_code == ErrorCode::kSuccess ? UpdateStatus::UPDATED_NEED_REBOOT
@@ -861,9 +881,6 @@
LOG(WARNING) << "Unable to unbind network.";
}
- for (auto observer : daemon_state_->service_observers())
- observer->SendPayloadApplicationComplete(error_code);
-
CollectAndReportUpdateMetricsOnUpdateFinished(error_code);
ClearMetricsPrefs();
if (error_code == ErrorCode::kSuccess) {
diff --git a/common/constants.h b/common/constants.h
index 3fcf1f1..dcd181f 100644
--- a/common/constants.h
+++ b/common/constants.h
@@ -163,6 +163,8 @@
static constexpr const auto& kPayloadPropertyMetadataHash = "METADATA_HASH";
// The Authorization: HTTP header to be sent when downloading the payload.
static constexpr const auto& kPayloadPropertyAuthorization = "AUTHORIZATION";
+// HTTP headers extra entries in the format of key1;val1 key2;val2 key3;val3
+static constexpr const auto& kPayloadPropertyHTTPExtras = "HTTP_EXTRAS";
// The User-Agent HTTP header to be sent when downloading the payload.
static constexpr const auto& kPayloadPropertyUserAgent = "USER_AGENT";
// Set "POWERWASH=1" to powerwash (factory data reset) the device after
diff --git a/common/http_fetcher_unittest.cc b/common/http_fetcher_unittest.cc
index 06f3e15..b229660 100644
--- a/common/http_fetcher_unittest.cc
+++ b/common/http_fetcher_unittest.cc
@@ -548,6 +548,8 @@
fetcher->SetHeader("User-Agent", "MyTest");
fetcher->SetHeader("user-agent", "Override that header");
fetcher->SetHeader("Authorization", "Basic user:passwd");
+ fetcher->SetHeader("Cache-Control", "testControl");
+ fetcher->SetHeader("Connection", "testConnection");
// Invalid headers.
fetcher->SetHeader("X-Foo", "Invalid\nHeader\nIgnored");
@@ -571,6 +573,8 @@
delegate.data.find("user-agent: Override that header\r\n"));
EXPECT_NE(string::npos,
delegate.data.find("Authorization: Basic user:passwd\r\n"));
+ EXPECT_NE(string::npos, delegate.data.find("Cache-Control: testControl\r\n"));
+ EXPECT_NE(string::npos, delegate.data.find("Connection: testConnection\r\n"));
EXPECT_EQ(string::npos, delegate.data.find("\nAccept:"));
EXPECT_EQ(string::npos, delegate.data.find("X-Foo: Invalid"));
diff --git a/common/prefs.cc b/common/prefs.cc
index 79d622f..77078cf 100644
--- a/common/prefs.cc
+++ b/common/prefs.cc
@@ -200,7 +200,12 @@
return false;
}
// Copy the directory.
- std::filesystem::copy(source_directory, destination_directory);
+ std::error_code e;
+ std::filesystem::copy(source_directory, destination_directory, e);
+ if (e) {
+ LOG(ERROR) << "failed to copy prefs to prefs_tmp: " << e.message();
+ return false;
+ }
return true;
}
@@ -209,7 +214,12 @@
std::filesystem::path destination_directory(GetTemporaryDir());
if (std::filesystem::exists(destination_directory)) {
- return std::filesystem::remove_all(destination_directory);
+ std::error_code e;
+ std::filesystem::remove_all(destination_directory, e);
+ if (e) {
+ LOG(ERROR) << "failed to remove directory: " << e.message();
+ return false;
+ }
}
return true;
}
diff --git a/lz4diff/lz4diff_compress_unittest.cc b/lz4diff/lz4diff_compress_unittest.cc
index d05c6be..9caa9a3 100644
--- a/lz4diff/lz4diff_compress_unittest.cc
+++ b/lz4diff/lz4diff_compress_unittest.cc
@@ -14,10 +14,10 @@
// limitations under the License.
//
+#include <fcntl.h>
#include <unistd.h>
#include <algorithm>
-#include <mutex>
#include <string>
#include <vector>
@@ -48,10 +48,10 @@
const char* inode_path,
Blob* output) {
struct erofs_sb_info sbi {};
- auto err = dev_open_ro(&sbi, erofs_image);
+ auto err = erofs_dev_open(&sbi, erofs_image, O_RDONLY);
ASSERT_EQ(err, 0);
DEFER {
- dev_close(&sbi);
+ erofs_dev_close(&sbi);
};
err = erofs_read_superblock(&sbi);
diff --git a/payload_consumer/filesystem_verifier_action.cc b/payload_consumer/filesystem_verifier_action.cc
index 5345085..2e2f6b9 100644
--- a/payload_consumer/filesystem_verifier_action.cc
+++ b/payload_consumer/filesystem_verifier_action.cc
@@ -273,7 +273,7 @@
return;
}
const auto read_size =
- std::min<size_t>(buffer_size, end_offset - start_offset);
+ std::min<uint64_t>(buffer_size, end_offset - start_offset);
const auto bytes_read = fd->Read(buffer, read_size);
if (bytes_read < 0 || static_cast<size_t>(bytes_read) != read_size) {
PLOG(ERROR) << "Failed to read offset " << start_offset << " expected "
@@ -319,7 +319,7 @@
return;
}
const auto read_size =
- std::min<size_t>(buffer_size, end_offset - start_offset);
+ std::min<uint64_t>(buffer_size, end_offset - start_offset);
const auto bytes_read = fd->Read(buffer, read_size);
if (bytes_read < 0 || static_cast<size_t>(bytes_read) != read_size) {
PLOG(ERROR) << "Failed to read offset " << start_offset << " expected "
@@ -406,7 +406,6 @@
buffer_.resize(kReadFileBufferSize);
hasher_ = std::make_unique<HashCalculator>();
- offset_ = 0;
filesystem_data_end_ = partition_size_;
if (partition.fec_offset > 0) {
CHECK_LE(partition.hash_tree_offset, partition.fec_offset)
@@ -456,7 +455,7 @@
}
}
-size_t FilesystemVerifierAction::GetPartitionSize() const {
+uint64_t FilesystemVerifierAction::GetPartitionSize() const {
const InstallPlan::Partition& partition =
install_plan_.partitions[partition_index_];
switch (verifier_step_) {
diff --git a/payload_consumer/filesystem_verifier_action.h b/payload_consumer/filesystem_verifier_action.h
index 5bc44b1..d8cb902 100644
--- a/payload_consumer/filesystem_verifier_action.h
+++ b/payload_consumer/filesystem_verifier_action.h
@@ -109,7 +109,7 @@
bool IsVABC(const InstallPlan::Partition& partition) const;
- size_t GetPartitionSize() const;
+ uint64_t GetPartitionSize() const;
// When the read is done, finalize the hash checking of the current partition
// and continue checking the next one.
@@ -163,9 +163,6 @@
// partition in gpt.
uint64_t partition_size_{0};
- // The byte offset that we are reading in the current partition.
- uint64_t offset_{0};
-
// The end offset of filesystem data, first byte position of hashtree.
uint64_t filesystem_data_end_{0};
diff --git a/payload_consumer/install_plan.cc b/payload_consumer/install_plan.cc
index cea8e5a..9c3934d 100644
--- a/payload_consumer/install_plan.cc
+++ b/payload_consumer/install_plan.cc
@@ -99,7 +99,6 @@
{"powerwash_required", utils::ToString(powerwash_required)},
{"switch_slot_on_reboot", utils::ToString(switch_slot_on_reboot)},
{"run_post_install", utils::ToString(run_post_install)},
- {"is_rollback", utils::ToString(is_rollback)},
{"rollback_data_save_requested",
utils::ToString(rollback_data_save_requested)},
{"write_verity", utils::ToString(write_verity)},
diff --git a/payload_consumer/install_plan.h b/payload_consumer/install_plan.h
index dbbe4b2..097c6ce 100644
--- a/payload_consumer/install_plan.h
+++ b/payload_consumer/install_plan.h
@@ -182,9 +182,6 @@
// False otherwise.
bool run_post_install{true};
- // True if this update is a rollback.
- bool is_rollback{false};
-
// True if this rollback should preserve some system data.
bool rollback_data_save_requested{false};
diff --git a/payload_consumer/install_plan_unittest.cc b/payload_consumer/install_plan_unittest.cc
index 193d936..d2a3f5f 100644
--- a/payload_consumer/install_plan_unittest.cc
+++ b/payload_consumer/install_plan_unittest.cc
@@ -54,7 +54,6 @@
powerwash_required: false
switch_slot_on_reboot: true
run_post_install: true
-is_rollback: false
rollback_data_save_requested: false
write_verity: true
Partition: foo-partition_name
diff --git a/payload_consumer/postinstall_runner_action.cc b/payload_consumer/postinstall_runner_action.cc
index e7804ea..5635dce 100644
--- a/payload_consumer/postinstall_runner_action.cc
+++ b/payload_consumer/postinstall_runner_action.cc
@@ -114,9 +114,11 @@
// Mount snapshot partitions for Virtual AB Compression Compression.
if (dynamic_control->UpdateUsesSnapshotCompression()) {
- // Before calling MapAllPartitions to map snapshot devices, all CowWriters
- // must be closed, and MapAllPartitions() should be called.
- if (!install_plan_.partitions.empty()) {
+ // If we are switching slots, then we are required to MapAllPartitions,
+ // as FinishUpdate() requires all partitions to be mapped.
+ // And switching slots requires FinishUpdate() to be called first
+ if (!install_plan_.partitions.empty() ||
+ install_plan_.switch_slot_on_reboot) {
if (!dynamic_control->MapAllPartitions()) {
return CompletePostinstall(ErrorCode::kPostInstallMountError);
}
@@ -127,7 +129,7 @@
// if this is a full/normal powerwash, or a special rollback powerwash
// that retains a small amount of system state such as enrollment and
// network configuration. In both cases all user accounts are deleted.
- if (install_plan_.powerwash_required || install_plan_.is_rollback) {
+ if (install_plan_.powerwash_required) {
if (hardware_->SchedulePowerwash(
install_plan_.rollback_data_save_requested)) {
powerwash_scheduled_ = true;
@@ -526,14 +528,6 @@
};
if (error_code == ErrorCode::kSuccess) {
if (install_plan_.switch_slot_on_reboot) {
- if constexpr (!constants::kIsRecovery) {
- if (!boot_control_->GetDynamicPartitionControl()->MapAllPartitions()) {
- LOG(WARNING)
- << "Failed to map all partitions before marking snapshot as "
- "ready for slot switch. Subsequent FinishUpdate() call may or "
- "may not work";
- }
- }
if (!boot_control_->GetDynamicPartitionControl()->FinishUpdate(
install_plan_.powerwash_required) ||
!boot_control_->SetActiveBootSlot(install_plan_.target_slot)) {
diff --git a/payload_consumer/postinstall_runner_action_unittest.cc b/payload_consumer/postinstall_runner_action_unittest.cc
index 75d93dc..c899599 100644
--- a/payload_consumer/postinstall_runner_action_unittest.cc
+++ b/payload_consumer/postinstall_runner_action_unittest.cc
@@ -104,7 +104,6 @@
void RunPostinstallAction(const string& device_path,
const string& postinstall_program,
bool powerwash_required,
- bool is_rollback,
bool save_rollback_data);
void RunPostinstallActionWithInstallPlan(const InstallPlan& install_plan);
@@ -189,7 +188,6 @@
const string& device_path,
const string& postinstall_program,
bool powerwash_required,
- bool is_rollback,
bool save_rollback_data) {
InstallPlan::Partition part;
part.name = "part";
@@ -201,7 +199,6 @@
install_plan.partitions = {part};
install_plan.download_url = "http://127.0.0.1:8080/update";
install_plan.powerwash_required = powerwash_required;
- install_plan.is_rollback = is_rollback;
install_plan.rollback_data_save_requested = save_rollback_data;
RunPostinstallActionWithInstallPlan(install_plan);
}
@@ -279,8 +276,7 @@
TEST_F(PostinstallRunnerActionTest, RunAsRootSimpleTest) {
ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
- RunPostinstallAction(
- loop.dev(), kPostinstallDefaultScript, false, false, false);
+ RunPostinstallAction(loop.dev(), kPostinstallDefaultScript, false, false);
EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
EXPECT_TRUE(processor_delegate_.processing_done_called_);
@@ -291,7 +287,7 @@
TEST_F(PostinstallRunnerActionTest, RunAsRootRunSymlinkFileTest) {
ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
- RunPostinstallAction(loop.dev(), "bin/postinst_link", false, false, false);
+ RunPostinstallAction(loop.dev(), "bin/postinst_link", false, false);
EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
}
@@ -301,7 +297,6 @@
RunPostinstallAction(loop.dev(),
"bin/postinst_example",
/*powerwash_required=*/true,
- false,
false);
EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
@@ -310,43 +305,10 @@
EXPECT_FALSE(fake_hardware_.GetIsRollbackPowerwashScheduled());
}
-TEST_F(PostinstallRunnerActionTest, RunAsRootRollbackTestNoDataSave) {
- ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
-
- // Run a simple postinstall program, rollback happened.
- RunPostinstallAction(loop.dev(),
- "bin/postinst_example",
- false,
- /*is_rollback=*/true,
- /*save_rollback_data=*/false);
- EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
-
- // Check that powerwash was scheduled and that it's NOT a rollback powerwash.
- EXPECT_TRUE(fake_hardware_.IsPowerwashScheduled());
- EXPECT_FALSE(fake_hardware_.GetIsRollbackPowerwashScheduled());
-}
-
-TEST_F(PostinstallRunnerActionTest, RunAsRootRollbackTestWithDataSave) {
- ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
-
- // Run a simple postinstall program, rollback happened.
- RunPostinstallAction(loop.dev(),
- "bin/postinst_example",
- false,
- /*is_rollback=*/true,
- /*save_rollback_data=*/true);
- EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
-
- // Check that powerwash was scheduled and that it's a rollback powerwash.
- EXPECT_TRUE(fake_hardware_.IsPowerwashScheduled());
- EXPECT_TRUE(fake_hardware_.GetIsRollbackPowerwashScheduled());
-}
-
// Runs postinstall from a partition file that doesn't mount, so it should
// fail.
TEST_F(PostinstallRunnerActionTest, RunAsRootCantMountTest) {
- RunPostinstallAction(
- "/dev/null", kPostinstallDefaultScript, false, false, false);
+ RunPostinstallAction("/dev/null", kPostinstallDefaultScript, false, false);
EXPECT_EQ(ErrorCode::kPostInstallMountError, processor_delegate_.code_);
// In case of failure, Postinstall should not signal a powerwash even if it
@@ -382,7 +344,7 @@
// fail.
TEST_F(PostinstallRunnerActionTest, RunAsRootErrScriptTest) {
ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
- RunPostinstallAction(loop.dev(), "bin/postinst_fail1", false, false, false);
+ RunPostinstallAction(loop.dev(), "bin/postinst_fail1", false, false);
EXPECT_EQ(ErrorCode::kPostinstallRunnerError, processor_delegate_.code_);
}
@@ -390,7 +352,7 @@
// UMA with a different error code. Test those cases are properly detected.
TEST_F(PostinstallRunnerActionTest, RunAsRootFirmwareBErrScriptTest) {
ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
- RunPostinstallAction(loop.dev(), "bin/postinst_fail3", false, false, false);
+ RunPostinstallAction(loop.dev(), "bin/postinst_fail3", false, false);
EXPECT_EQ(ErrorCode::kPostinstallBootedFromFirmwareB,
processor_delegate_.code_);
}
@@ -398,7 +360,7 @@
// Check that you can't specify an absolute path.
TEST_F(PostinstallRunnerActionTest, RunAsRootAbsolutePathNotAllowedTest) {
ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
- RunPostinstallAction(loop.dev(), "/etc/../bin/sh", false, false, false);
+ RunPostinstallAction(loop.dev(), "/etc/../bin/sh", false, false);
EXPECT_EQ(ErrorCode::kPostinstallRunnerError, processor_delegate_.code_);
}
@@ -407,8 +369,7 @@
// SElinux labels are only set on Android.
TEST_F(PostinstallRunnerActionTest, RunAsRootCheckFileContextsTest) {
ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
- RunPostinstallAction(
- loop.dev(), "bin/self_check_context", false, false, false);
+ RunPostinstallAction(loop.dev(), "bin/self_check_context", false, false);
EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
}
@@ -417,7 +378,7 @@
TEST_F(PostinstallRunnerActionTest, RunAsRootCheckDefaultFileContextsTest) {
ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
RunPostinstallAction(
- loop.dev(), "bin/self_check_default_context", false, false, false);
+ loop.dev(), "bin/self_check_default_context", false, false);
EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
}
#endif // __ANDROID__
@@ -430,7 +391,7 @@
loop_.PostTask(FROM_HERE,
base::Bind(&PostinstallRunnerActionTest::SuspendRunningAction,
base::Unretained(this)));
- RunPostinstallAction(loop.dev(), "bin/postinst_suspend", false, false, false);
+ RunPostinstallAction(loop.dev(), "bin/postinst_suspend", false, false);
// postinst_suspend returns 0 only if it was suspended at some point.
EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
EXPECT_TRUE(processor_delegate_.processing_done_called_);
@@ -442,7 +403,7 @@
// Wait for the action to start and then cancel it.
CancelWhenStarted();
- RunPostinstallAction(loop.dev(), "bin/postinst_suspend", false, false, false);
+ RunPostinstallAction(loop.dev(), "bin/postinst_suspend", false, false);
// When canceling the action, the action never finished and therefore we had
// a ProcessingStopped call instead.
EXPECT_FALSE(processor_delegate_.code_set_);
@@ -465,8 +426,7 @@
ScopedLoopbackDeviceBinder loop(postinstall_image_, false, nullptr);
setup_action_delegate_ = &mock_delegate_;
- RunPostinstallAction(
- loop.dev(), "bin/postinst_progress", false, false, false);
+ RunPostinstallAction(loop.dev(), "bin/postinst_progress", false, false);
EXPECT_EQ(ErrorCode::kSuccess, processor_delegate_.code_);
}
diff --git a/payload_consumer/verified_source_fd.cc b/payload_consumer/verified_source_fd.cc
index 3f17ad7..d760d1f 100644
--- a/payload_consumer/verified_source_fd.cc
+++ b/payload_consumer/verified_source_fd.cc
@@ -109,9 +109,16 @@
brillo::Blob source_hash;
brillo::Blob expected_source_hash(operation.src_sha256_hash().begin(),
operation.src_sha256_hash().end());
- if (fd_utils::ReadAndHashExtents(
- source_fd_, operation.src_extents(), block_size_, &source_hash) &&
- source_hash == expected_source_hash) {
+ if (!fd_utils::ReadAndHashExtents(
+ source_fd_, operation.src_extents(), block_size_, &source_hash)) {
+ LOG(ERROR) << "Failed to compute hash for operation " << operation.type()
+ << " data offset: " << operation.data_offset();
+ if (error) {
+ *error = ErrorCode::kDownloadOperationHashVerificationError;
+ }
+ return nullptr;
+ }
+ if (source_hash == expected_source_hash) {
return source_fd_;
}
if (error) {
diff --git a/payload_consumer/verity_writer_android.cc b/payload_consumer/verity_writer_android.cc
index 4a476d2..d808dd5 100644
--- a/payload_consumer/verity_writer_android.cc
+++ b/payload_consumer/verity_writer_android.cc
@@ -78,7 +78,7 @@
// Encodes |block_size| number of rs blocks each round so that we can read
// one block each time instead of 1 byte to increase random read
// performance. This uses about 1 MiB memory for 4K block size.
- for (size_t j = 0; j < rs_n_; j++) {
+ for (uint64_t j = 0; j < rs_n_; j++) {
uint64_t offset = fec_ecc_interleave(
current_round_ * rs_n_ * block_size_ + j, rs_n_, num_rounds_);
// Don't read past |data_size|, treat them as 0.
@@ -95,11 +95,11 @@
TEST_AND_RETURN_FALSE(static_cast<size_t>(bytes_read) ==
buffer_.size());
}
- for (size_t k = 0; k < buffer_.size(); k++) {
+ for (uint64_t k = 0; k < buffer_.size(); k++) {
rs_blocks_[k * rs_n_ + j] = buffer_[k];
}
}
- for (size_t j = 0; j < block_size_; j++) {
+ for (uint64_t j = 0; j < block_size_; j++) {
// Encode [j * rs_n_ : (j + 1) * rs_n_) in |rs_blocks| and write
// |fec_roots| number of parity bytes to |j * fec_roots| in |fec|.
encode_rs_char(rs_char_.get(),
diff --git a/payload_consumer/verity_writer_android.h b/payload_consumer/verity_writer_android.h
index 1aaafd5..9926988 100644
--- a/payload_consumer/verity_writer_android.h
+++ b/payload_consumer/verity_writer_android.h
@@ -63,8 +63,8 @@
brillo::Blob fec_;
brillo::Blob fec_read_;
EncodeFECStep current_step_;
- size_t current_round_;
- size_t num_rounds_;
+ uint64_t current_round_;
+ uint64_t num_rounds_;
FileDescriptor* read_fd_;
FileDescriptor* write_fd_;
uint64_t data_offset_;
@@ -73,7 +73,7 @@
uint64_t fec_size_;
uint64_t fec_roots_;
uint64_t block_size_;
- size_t rs_n_;
+ uint64_t rs_n_;
bool verify_mode_;
std::unique_ptr<void, decltype(&free_rs_char)> rs_char_;
UnownedCachedFileDescriptor cache_fd_;
diff --git a/payload_generator/erofs_filesystem.cc b/payload_generator/erofs_filesystem.cc
index 32a5fc5..2835dea 100644
--- a/payload_generator/erofs_filesystem.cc
+++ b/payload_generator/erofs_filesystem.cc
@@ -175,12 +175,12 @@
}
struct erofs_sb_info sbi {};
- if (const auto err = dev_open_ro(&sbi, filename.c_str()); err) {
+ if (const auto err = erofs_dev_open(&sbi, filename.c_str(), O_RDONLY); err) {
PLOG(INFO) << "Failed to open " << filename;
return nullptr;
}
DEFER {
- dev_close(&sbi);
+ erofs_dev_close(&sbi);
};
if (const auto err = erofs_read_superblock(&sbi); err) {
@@ -189,7 +189,7 @@
}
const auto block_size = 1UL << sbi.blkszbits;
struct stat st {};
- if (const auto err = fstat(sbi.devfd, &st); err) {
+ if (const auto err = stat(filename.c_str(), &st); err) {
PLOG(ERROR) << "Failed to stat() " << filename;
return nullptr;
}