Allow creation of a logical partition
- InstallPlan: allow source partition to be missing if size == 0
- DeltaPerformer: don't open source partition if size == 0
Also:
- DeltaPerformer: test for source_fd_ before using it
(to avoid segfault)
- Fix DeltaPerformerTest to generate payloads with correct
source sizes and paths. Previously, this works because source_path
is always set even when source_size = 0.
Bug: 124958572
Test: python system/update_engine/scripts/update_device.py <ota-img>
Test: update_engine_unittests
Change-Id: I53bda1d12accdf91e7fa616be5da562e189038d5
diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
index 489c821..ae73d03 100644
--- a/payload_consumer/delta_performer.cc
+++ b/payload_consumer/delta_performer.cc
@@ -358,7 +358,10 @@
install_plan_->partitions[num_previous_partitions + current_partition_];
// Open source fds if we have a delta payload with minor version >= 2.
if (payload_->type == InstallPayloadType::kDelta &&
- GetMinorVersion() != kInPlaceMinorPayloadVersion) {
+ GetMinorVersion() != kInPlaceMinorPayloadVersion &&
+ // With dynamic partitions we could create a new partition in a
+ // delta payload, and we shouldn't open source partition in that case.
+ install_part.source_size > 0) {
source_path_ = install_part.source_path;
int err;
source_fd_ = OpenFile(source_path_.c_str(), O_RDONLY, false, &err);
@@ -1167,6 +1170,8 @@
if (operation.has_dst_length())
TEST_AND_RETURN_FALSE(operation.dst_length() % block_size_ == 0);
+ TEST_AND_RETURN_FALSE(source_fd_ != nullptr);
+
if (operation.has_src_sha256_hash()) {
brillo::Blob source_hash;
brillo::Blob expected_source_hash(operation.src_sha256_hash().begin(),
@@ -1236,6 +1241,11 @@
FileDescriptorPtr DeltaPerformer::ChooseSourceFD(
const InstallOperation& operation, ErrorCode* error) {
+ if (source_fd_ == nullptr) {
+ LOG(ERROR) << "ChooseSourceFD fail: source_fd_ == nullptr";
+ return nullptr;
+ }
+
if (!operation.has_src_sha256_hash()) {
// When the operation doesn't include a source hash, we attempt the error
// corrected device first since we can't verify the block in the raw device
diff --git a/payload_consumer/delta_performer_unittest.cc b/payload_consumer/delta_performer_unittest.cc
index 61b58ed..b7a38cc 100644
--- a/payload_consumer/delta_performer_unittest.cc
+++ b/payload_consumer/delta_performer_unittest.cc
@@ -177,19 +177,22 @@
brillo::Blob GeneratePayload(const brillo::Blob& blob_data,
const vector<AnnotatedOperation>& aops,
- bool sign_payload) {
+ bool sign_payload,
+ PartitionConfig* old_part = nullptr) {
return GeneratePayload(blob_data,
aops,
sign_payload,
kMaxSupportedMajorPayloadVersion,
- kMaxSupportedMinorPayloadVersion);
+ kMaxSupportedMinorPayloadVersion,
+ old_part);
}
brillo::Blob GeneratePayload(const brillo::Blob& blob_data,
const vector<AnnotatedOperation>& aops,
bool sign_payload,
uint64_t major_version,
- uint32_t minor_version) {
+ uint32_t minor_version,
+ PartitionConfig* old_part = nullptr) {
test_utils::ScopedTempFile blob_file("Blob-XXXXXX");
EXPECT_TRUE(test_utils::WriteFileVector(blob_file.path(), blob_data));
@@ -200,24 +203,29 @@
PayloadFile payload;
EXPECT_TRUE(payload.Init(config));
- PartitionConfig old_part(kPartitionNameRoot);
+ std::unique_ptr<PartitionConfig> old_part_uptr;
+ if (!old_part) {
+ old_part_uptr = std::make_unique<PartitionConfig>(kPartitionNameRoot);
+ old_part = old_part_uptr.get();
+ }
if (minor_version != kFullPayloadMinorVersion) {
// When generating a delta payload we need to include the old partition
// information to mark it as a delta payload.
- old_part.path = "/dev/null";
- old_part.size = 0;
+ if (old_part->path.empty()) {
+ old_part->path = "/dev/null";
+ }
}
PartitionConfig new_part(kPartitionNameRoot);
new_part.path = "/dev/zero";
new_part.size = 1234;
- payload.AddPartition(old_part, new_part, aops);
+ payload.AddPartition(*old_part, new_part, aops);
// We include a kernel partition without operations.
- old_part.name = kPartitionNameKernel;
+ old_part->name = kPartitionNameKernel;
new_part.name = kPartitionNameKernel;
new_part.size = 0;
- payload.AddPartition(old_part, new_part, {});
+ payload.AddPartition(*old_part, new_part, {});
test_utils::ScopedTempFile payload_file("Payload-XXXXXX");
string private_key =
@@ -233,7 +241,8 @@
}
brillo::Blob GenerateSourceCopyPayload(const brillo::Blob& copied_data,
- bool add_hash) {
+ bool add_hash,
+ PartitionConfig* old_part = nullptr) {
PayloadGenerationConfig config;
const uint64_t kDefaultBlockSize = config.block_size;
EXPECT_EQ(0U, copied_data.size() % kDefaultBlockSize);
@@ -247,7 +256,7 @@
if (add_hash)
aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
- return GeneratePayload(brillo::Blob(), {aop}, false);
+ return GeneratePayload(brillo::Blob(), {aop}, false, old_part);
}
// Apply |payload_data| on partition specified in |source_path|.
@@ -571,11 +580,16 @@
EXPECT_TRUE(HashCalculator::RawHashOfData(expected_data, &src_hash));
aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
- brillo::Blob payload_data = GeneratePayload(brillo::Blob(), {aop}, false);
-
test_utils::ScopedTempFile source("Source-XXXXXX");
EXPECT_TRUE(test_utils::WriteFileVector(source.path(), expected_data));
+ PartitionConfig old_part(kPartitionNameRoot);
+ old_part.path = source.path();
+ old_part.size = expected_data.size();
+
+ brillo::Blob payload_data =
+ GeneratePayload(brillo::Blob(), {aop}, false, &old_part);
+
EXPECT_EQ(expected_data, ApplyPayload(payload_data, source.path(), true));
}
@@ -594,11 +608,16 @@
EXPECT_TRUE(HashCalculator::RawHashOfData(src, &src_hash));
aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
- brillo::Blob payload_data = GeneratePayload(puffdiff_payload, {aop}, false);
-
test_utils::ScopedTempFile source("Source-XXXXXX");
EXPECT_TRUE(test_utils::WriteFileVector(source.path(), src));
+ PartitionConfig old_part(kPartitionNameRoot);
+ old_part.path = source.path();
+ old_part.size = src.size();
+
+ brillo::Blob payload_data =
+ GeneratePayload(puffdiff_payload, {aop}, false, &old_part);
+
brillo::Blob dst(std::begin(dst_deflates), std::end(dst_deflates));
EXPECT_EQ(dst, ApplyPayload(payload_data, source.path(), true));
}
@@ -617,11 +636,16 @@
EXPECT_TRUE(HashCalculator::RawHashOfData(expected_data, &src_hash));
aop.op.set_src_sha256_hash(src_hash.data(), src_hash.size());
- brillo::Blob payload_data = GeneratePayload(brillo::Blob(), {aop}, false);
-
test_utils::ScopedTempFile source("Source-XXXXXX");
EXPECT_TRUE(test_utils::WriteFileVector(source.path(), actual_data));
+ PartitionConfig old_part(kPartitionNameRoot);
+ old_part.path = source.path();
+ old_part.size = actual_data.size();
+
+ brillo::Blob payload_data =
+ GeneratePayload(brillo::Blob(), {aop}, false, &old_part);
+
EXPECT_EQ(actual_data, ApplyPayload(payload_data, source.path(), false));
}
@@ -640,7 +664,12 @@
FakeFileDescriptor* fake_fec = SetFakeECCFile(kCopyOperationSize);
brillo::Blob expected_data = FakeFileDescriptorData(kCopyOperationSize);
- brillo::Blob payload_data = GenerateSourceCopyPayload(expected_data, true);
+ PartitionConfig old_part(kPartitionNameRoot);
+ old_part.path = source.path();
+ old_part.size = invalid_data.size();
+
+ brillo::Blob payload_data =
+ GenerateSourceCopyPayload(expected_data, true, &old_part);
EXPECT_EQ(expected_data, ApplyPayload(payload_data, source.path(), true));
// Verify that the fake_fec was actually used.
EXPECT_EQ(1U, fake_fec->GetReadOps().size());
@@ -661,8 +690,13 @@
// the expected.
FakeFileDescriptor* fake_fec = SetFakeECCFile(kCopyOperationSize / 2);
+ PartitionConfig old_part(kPartitionNameRoot);
+ old_part.path = source.path();
+ old_part.size = expected_data.size();
+
// The payload operation doesn't include an operation hash.
- brillo::Blob payload_data = GenerateSourceCopyPayload(expected_data, false);
+ brillo::Blob payload_data =
+ GenerateSourceCopyPayload(expected_data, false, &old_part);
EXPECT_EQ(expected_data, ApplyPayload(payload_data, source.path(), true));
// Verify that the fake_fec was attempted to be used. Since the file
// descriptor is shorter it can actually do more than one read to realize it
diff --git a/payload_consumer/install_plan.cc b/payload_consumer/install_plan.cc
index f52cd2d..2e7b6d4 100644
--- a/payload_consumer/install_plan.cc
+++ b/payload_consumer/install_plan.cc
@@ -98,7 +98,8 @@
bool InstallPlan::LoadPartitionsFromSlots(BootControlInterface* boot_control) {
bool result = true;
for (Partition& partition : partitions) {
- if (source_slot != BootControlInterface::kInvalidSlot) {
+ if (source_slot != BootControlInterface::kInvalidSlot &&
+ partition.source_size > 0) {
result = boot_control->GetPartitionDevice(
partition.name, source_slot, &partition.source_path) &&
result;