diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp index cff44b79e..9d710f90b 100644 --- a/fs_mgr/liblp/builder.cpp +++ b/fs_mgr/liblp/builder.cpp @@ -200,6 +200,11 @@ bool MetadataBuilder::Init(const BlockDeviceInfo& device_info, uint32_t metadata metadata_max_size = AlignTo(metadata_max_size, LP_SECTOR_SIZE); // Check that device properties are sane. + device_info_ = device_info; + if (device_info_.size % LP_SECTOR_SIZE != 0) { + LERROR << "Block device size must be a multiple of 512."; + return false; + } if (device_info_.alignment_offset % LP_SECTOR_SIZE != 0) { LERROR << "Alignment offset is not sector-aligned."; return false; @@ -212,7 +217,6 @@ bool MetadataBuilder::Init(const BlockDeviceInfo& device_info, uint32_t metadata LERROR << "Partition alignment offset is greater than its alignment."; return false; } - device_info_ = device_info; // We reserve a geometry block (4KB) plus space for each copy of the // maximum size of a metadata blob. Then, we double that space since diff --git a/fs_mgr/liblp/builder_test.cpp b/fs_mgr/liblp/builder_test.cpp index 08440a3d0..b610fd4c4 100644 --- a/fs_mgr/liblp/builder_test.cpp +++ b/fs_mgr/liblp/builder_test.cpp @@ -106,19 +106,9 @@ TEST(liblp, DiskAlignment) { static const uint32_t kMetadataSize = 1024; static const uint32_t kMetadataSlots = 2; - // If the disk size is not aligned to 512 bytes, make sure it still leaves - // space at the end for backup metadata, and that it doesn't overlap with - // the space for logical partitions. unique_ptr builder = MetadataBuilder::New(kDiskSize, kMetadataSize, kMetadataSlots); - unique_ptr exported = builder->Export(); - ASSERT_NE(exported, nullptr); - - static const size_t kMetadataSpace = - (kMetadataSize * kMetadataSlots) + LP_METADATA_GEOMETRY_SIZE; - uint64_t space_at_end = - kDiskSize - (exported->geometry.last_logical_sector + 1) * LP_SECTOR_SIZE; - EXPECT_GE(space_at_end, kMetadataSpace); + ASSERT_EQ(builder, nullptr); } TEST(liblp, MetadataAlignment) { @@ -148,15 +138,10 @@ TEST(liblp, InternalAlignment) { EXPECT_EQ(exported->geometry.first_logical_sector, 1472); EXPECT_EQ(exported->geometry.last_logical_sector, 2035); - // Test only an alignment offset (which should simply bump up the first - // logical sector). + // Alignment offset without alignment doesn't mean anything. device_info.alignment = 0; builder = MetadataBuilder::New(device_info, 1024, 2); - ASSERT_NE(builder, nullptr); - exported = builder->Export(); - ASSERT_NE(exported, nullptr); - EXPECT_EQ(exported->geometry.first_logical_sector, 1484); - EXPECT_EQ(exported->geometry.last_logical_sector, 2035); + ASSERT_EQ(builder, nullptr); // Test a small alignment with an alignment offset. device_info.alignment = 12 * 1024; diff --git a/fs_mgr/liblp/include/liblp/metadata_format.h b/fs_mgr/liblp/include/liblp/metadata_format.h index b69e13869..e1323e11e 100644 --- a/fs_mgr/liblp/include/liblp/metadata_format.h +++ b/fs_mgr/liblp/include/liblp/metadata_format.h @@ -86,7 +86,9 @@ typedef struct LpMetadataGeometry { /* 8: SHA256 checksum of this struct, with this field set to 0. */ uint8_t checksum[32]; - /* 40: Maximum amount of space a single copy of the metadata can use. */ + /* 40: Maximum amount of space a single copy of the metadata can use. This + * must be a multiple of LP_SECTOR_SIZE. + */ uint32_t metadata_max_size; /* 44: Number of copies of the metadata to keep. For A/B devices, this diff --git a/fs_mgr/liblp/reader.cpp b/fs_mgr/liblp/reader.cpp index 985cf0991..7fbf8e6c0 100644 --- a/fs_mgr/liblp/reader.cpp +++ b/fs_mgr/liblp/reader.cpp @@ -68,6 +68,10 @@ static bool ParseGeometry(const void* buffer, LpMetadataGeometry* geometry) { LERROR << "Logical partition metadata has invalid slot count."; return false; } + if (geometry->metadata_max_size % LP_SECTOR_SIZE != 0) { + LERROR << "Metadata max size is not sector-aligned."; + return false; + } // Check that the metadata area and logical partition areas don't overlap. int64_t end_of_metadata =