Merge "Fix preload partition failure behavior" am: 6259714f90 am: 65f006b17e
Change-Id: Id6615a9cd60aeab9cf7871f0f3e8906320d35424
diff --git a/libavb/avb_slot_verify.c b/libavb/avb_slot_verify.c
index f107cf0..fc4c564 100644
--- a/libavb/avb_slot_verify.c
+++ b/libavb/avb_slot_verify.c
@@ -105,11 +105,11 @@
}
if (*out_image_buf != NULL) {
+ *out_image_preloaded = true;
if (part_num_read != image_size) {
avb_errorv(part_name, ": Read incorrect number of bytes.\n", NULL);
return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
}
- *out_image_preloaded = true;
}
}
diff --git a/test/avb_slot_verify_unittest.cc b/test/avb_slot_verify_unittest.cc
index c516d24..680ea27 100644
--- a/test/avb_slot_verify_unittest.cc
+++ b/test/avb_slot_verify_unittest.cc
@@ -831,6 +831,64 @@
avb_slot_verify_data_free(slot_data);
}
+TEST_F(AvbSlotVerifyTest, SmallPreallocatedPreloadedPartitionFailGracefully) {
+ const size_t boot_partition_size = 16 * 1024 * 1024;
+ const size_t boot_image_size = 5 * 1024 * 1024;
+ // Generate vbmeta based on this boot image.
+ base::FilePath boot_path = GenerateImage("boot_a.img", boot_image_size);
+
+ // Preload smaller image than expected on the stack
+ // libavb should not attempt to free this buffer.
+ const size_t fake_preload_image_size = 1024;
+ uint8_t fake_preload_buf[fake_preload_image_size];
+
+ EXPECT_COMMAND(
+ 0,
+ "./avbtool add_hash_footer"
+ " --image %s"
+ " --rollback_index 0"
+ " --partition_name boot"
+ " --partition_size %zd"
+ " --kernel_cmdline 'cmdline in hash footer $(ANDROID_SYSTEM_PARTUUID)'"
+ " --salt deadbeef"
+ " --internal_release_string \"\"",
+ boot_path.value().c_str(),
+ boot_partition_size);
+
+ GenerateVBMetaImage(
+ "vbmeta_a.img",
+ "SHA256_RSA2048",
+ 4,
+ base::FilePath("test/data/testkey_rsa2048.pem"),
+ base::StringPrintf(
+ "--include_descriptors_from_image %s"
+ " --kernel_cmdline 'cmdline in vbmeta $(ANDROID_BOOT_PARTUUID)'"
+ " --internal_release_string \"\"",
+ boot_path.value().c_str()));
+
+ EXPECT_COMMAND(0,
+ "./avbtool erase_footer"
+ " --image %s",
+ boot_path.value().c_str());
+
+ ops_.set_expected_public_key(
+ PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
+ ops_.enable_get_preloaded_partition();
+ EXPECT_TRUE(ops_.preload_preallocated_partition(
+ "boot_a", fake_preload_buf, fake_preload_image_size));
+
+ AvbSlotVerifyData* slot_data = NULL;
+ const char* requested_partitions[] = {"boot", NULL};
+ EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_IO,
+ avb_slot_verify(ops_.avb_ops(),
+ requested_partitions,
+ "_a",
+ AVB_SLOT_VERIFY_FLAGS_NONE,
+ AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
+ &slot_data));
+ EXPECT_EQ(nullptr, slot_data);
+}
+
TEST_F(AvbSlotVerifyTest, HashDescriptorInVBMetaCorruptBoot) {
size_t boot_partition_size = 16 * 1024 * 1024;
base::FilePath boot_path = GenerateImage("boot_a.img", 5 * 1024 * 1024);
diff --git a/test/fake_avb_ops.cc b/test/fake_avb_ops.cc
index 6e8ab8c..0f4db5a 100644
--- a/test/fake_avb_ops.cc
+++ b/test/fake_avb_ops.cc
@@ -87,6 +87,18 @@
return true;
}
+bool FakeAvbOps::preload_preallocated_partition(const std::string& partition,
+ uint8_t* buffer,
+ size_t size) {
+ if (preallocated_preloaded_partitions_.count(partition) > 0) {
+ fprintf(stderr, "Partition '%s' already preloaded\n", partition.c_str());
+ return false;
+ }
+
+ preallocated_preloaded_partitions_[partition] = std::make_pair(buffer, size);
+ return true;
+}
+
AvbIOResult FakeAvbOps::read_from_partition(const char* partition,
int64_t offset,
size_t num_bytes,
@@ -160,6 +172,15 @@
if (hidden_partitions_.find(partition) != hidden_partitions_.end()) {
return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
}
+
+ std::map<std::string, std::pair<uint8_t*, size_t>>::iterator prealloc_it =
+ preallocated_preloaded_partitions_.find(std::string(partition));
+ if (prealloc_it != preallocated_preloaded_partitions_.end()) {
+ *out_pointer = prealloc_it->second.first;
+ *out_num_bytes_preloaded = std::min(prealloc_it->second.second, num_bytes);
+ return AVB_IO_RESULT_OK;
+ }
+
std::map<std::string, uint8_t*>::iterator it =
preloaded_partitions_.find(std::string(partition));
if (it == preloaded_partitions_.end()) {
@@ -173,11 +194,8 @@
if (result != AVB_IO_RESULT_OK) {
return result;
}
- if (size != num_bytes) {
- return AVB_IO_RESULT_ERROR_IO;
- }
- *out_num_bytes_preloaded = num_bytes;
+ *out_num_bytes_preloaded = std::min(static_cast<size_t>(size), num_bytes);
*out_pointer = it->second;
return AVB_IO_RESULT_OK;
}
diff --git a/test/fake_avb_ops.h b/test/fake_avb_ops.h
index 2cc12d8..5dea5bd 100644
--- a/test/fake_avb_ops.h
+++ b/test/fake_avb_ops.h
@@ -211,6 +211,10 @@
bool preload_partition(const std::string& partition,
const base::FilePath& path);
+ bool preload_preallocated_partition(const std::string& partition,
+ uint8_t* buffer,
+ size_t size);
+
// Gets the partition names that were passed to the
// read_from_partition() operation.
std::set<std::string> get_partition_names_read_from();
@@ -315,6 +319,8 @@
std::set<std::string> partition_names_read_from_;
std::map<std::string, uint8_t*> preloaded_partitions_;
+ std::map<std::string, std::pair<uint8_t*, size_t>>
+ preallocated_preloaded_partitions_;
std::set<std::string> hidden_partitions_;
std::map<std::string, std::string> stored_values_;