Loading fs_mgr/liblp/Android.bp +5 −4 Original line number Diff line number Diff line Loading @@ -88,13 +88,14 @@ cc_defaults { static_libs: [ "libfs_mgr", ], } }, }, stl: "libc++_static", srcs: [ "builder_test.cpp", "super_layout_builder_test.cpp", "utility_test.cpp", "writer_test.cpp", ":TestPartitionOpener_group", ], } Loading @@ -105,7 +106,7 @@ cc_test { test_suites: ["device-tests"], auto_gen_config: true, require_root: true, host_supported: true host_supported: true, } cc_test { Loading fs_mgr/liblp/images.cpp +8 −2 Original line number Diff line number Diff line Loading @@ -112,7 +112,10 @@ std::unique_ptr<LpMetadata> ReadFromImageFile(const std::string& image_file) { bool WriteToImageFile(borrowed_fd fd, const LpMetadata& input) { std::string geometry = SerializeGeometry(input.geometry); std::string metadata = SerializeMetadata(input); std::string metadata = ValidateAndSerializeMetadata(input); if (metadata.empty()) { return false; } std::string everything = geometry + metadata; Loading Loading @@ -298,7 +301,10 @@ bool ImageBuilder::Build() { } std::string geometry_blob = SerializeGeometry(geometry_); std::string metadata_blob = SerializeMetadata(metadata_); std::string metadata_blob = ValidateAndSerializeMetadata(metadata_); if (metadata_blob.empty()) { return false; } metadata_blob.resize(geometry_.metadata_max_size); // Two copies of geometry, then two copies of each metadata slot. Loading fs_mgr/liblp/super_layout_builder.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -129,7 +129,10 @@ std::vector<SuperImageExtent> SuperLayoutBuilder::GetImageLayout() { // Write the primary and backup copies of each metadata slot. When flashing, // all metadata copies are the same, even for different slots. std::string metadata_bytes = SerializeMetadata(*metadata.get()); std::string metadata_bytes = ValidateAndSerializeMetadata(*metadata.get()); if (metadata_bytes.empty()) { return {}; } // Align metadata size to 4KB. This makes the layout easily compatible with // libsparse. Loading fs_mgr/liblp/super_layout_builder_test.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -46,7 +46,9 @@ TEST(SuperImageTool, Layout) { ASSERT_NE(metadata, nullptr); auto geometry_blob = std::make_shared<std::string>(SerializeGeometry(metadata->geometry)); auto metadata_blob = std::make_shared<std::string>(SerializeMetadata(*metadata.get())); auto metadata_blob = std::make_shared<std::string>(ValidateAndSerializeMetadata(*metadata.get())); ASSERT_FALSE(metadata_blob->empty()); metadata_blob->resize(4_KiB, '\0'); auto extents = tool.GetImageLayout(); Loading fs_mgr/liblp/writer.cpp +27 −28 Original line number Diff line number Diff line Loading @@ -47,7 +47,8 @@ static bool CompareGeometry(const LpMetadataGeometry& g1, const LpMetadataGeomet g1.logical_block_size == g2.logical_block_size; } std::string SerializeMetadata(const LpMetadata& input) { // Unvalidated serialization. static std::string SerializeMetadata(const LpMetadata& input) { LpMetadata metadata = input; LpMetadataHeader& header = metadata.header; Loading Loading @@ -81,26 +82,35 @@ std::string SerializeMetadata(const LpMetadata& input) { return header_blob + tables; } // Perform checks so we don't accidentally overwrite valid metadata with // potentially invalid metadata, or random partition data with metadata. static bool ValidateAndSerializeMetadata([[maybe_unused]] const IPartitionOpener& opener, const LpMetadata& metadata, const std::string& slot_suffix, std::string* blob) { // Validated serialization. std::string ValidateAndSerializeMetadata(const LpMetadata& metadata) { const LpMetadataGeometry& geometry = metadata.geometry; *blob = SerializeMetadata(metadata); std::string blob = SerializeMetadata(metadata); // Make sure we're writing within the space reserved. if (blob->size() > geometry.metadata_max_size) { LERROR << "Logical partition metadata is too large. " << blob->size() << " > " if (blob.size() > geometry.metadata_max_size) { LERROR << "Logical partition metadata is too large. " << blob.size() << " > " << geometry.metadata_max_size; return {}; } return blob; } // Perform checks so we don't accidentally overwrite valid metadata with // potentially invalid metadata, or random partition data with metadata. static bool ValidateAndSerializeMetadata([[maybe_unused]] const IPartitionOpener& opener, const LpMetadata& metadata, std::string* blob) { *blob = ValidateAndSerializeMetadata(metadata); if (blob->empty()) { return false; } // Make sure the device has enough space to store two backup copies of the // metadata. uint64_t reserved_size = LP_METADATA_GEOMETRY_SIZE + uint64_t(geometry.metadata_max_size) * geometry.metadata_slot_count; uint64_t reserved_size = LP_METADATA_GEOMETRY_SIZE + uint64_t(metadata.geometry.metadata_max_size) * metadata.geometry.metadata_slot_count; uint64_t total_reserved = LP_PARTITION_RESERVED_BYTES + reserved_size * 2; const LpMetadataBlockDevice* super_device = GetMetadataSuperBlockDevice(metadata); Loading @@ -116,13 +126,9 @@ static bool ValidateAndSerializeMetadata([[maybe_unused]] const IPartitionOpener for (const auto& block_device : metadata.block_devices) { std::string partition_name = GetBlockDevicePartitionName(block_device); if (block_device.flags & LP_BLOCK_DEVICE_SLOT_SUFFIXED) { if (slot_suffix.empty()) { LERROR << "Block device " << partition_name << " requires a slot suffix," << " which could not be derived from the super partition name."; LERROR << "Slot-suffixed super is no longer supported."; return false; } partition_name += slot_suffix; } if ((block_device.first_logical_sector + 1) * LP_SECTOR_SIZE > block_device.size) { LERROR << "Block device " << partition_name << " has invalid first sector " Loading Loading @@ -253,16 +259,11 @@ bool FlashPartitionTable(const IPartitionOpener& opener, const std::string& supe return false; } // This is only used in update_engine and fastbootd, where the super // partition should be specified as a name (or by-name link), and // therefore, we should be able to extract a slot suffix. std::string slot_suffix = GetPartitionSlotSuffix(super_partition); // Before writing geometry and/or logical partition tables, perform some // basic checks that the geometry and tables are coherent, and will fit // on the given block device. std::string metadata_blob; if (!ValidateAndSerializeMetadata(opener, metadata, slot_suffix, &metadata_blob)) { if (!ValidateAndSerializeMetadata(opener, metadata, &metadata_blob)) { return false; } Loading Loading @@ -328,13 +329,11 @@ bool UpdatePartitionTable(const IPartitionOpener& opener, const std::string& sup return false; } std::string slot_suffix = SlotSuffixForSlotNumber(slot_number); // Before writing geometry and/or logical partition tables, perform some // basic checks that the geometry and tables are coherent, and will fit // on the given block device. std::string blob; if (!ValidateAndSerializeMetadata(opener, metadata, slot_suffix, &blob)) { if (!ValidateAndSerializeMetadata(opener, metadata, &blob)) { return false; } Loading Loading @@ -366,7 +365,7 @@ bool UpdatePartitionTable(const IPartitionOpener& opener, const std::string& sup // synchronize the backup copy. This guarantees that a partial write // still leaves one copy intact. std::string old_blob; if (!ValidateAndSerializeMetadata(opener, *primary.get(), slot_suffix, &old_blob)) { if (!ValidateAndSerializeMetadata(opener, *primary.get(), &old_blob)) { LERROR << "Error serializing primary metadata to repair corrupted backup"; return false; } Loading @@ -378,7 +377,7 @@ bool UpdatePartitionTable(const IPartitionOpener& opener, const std::string& sup // The backup copy is coherent, and the primary is not. Sync it for // safety. std::string old_blob; if (!ValidateAndSerializeMetadata(opener, *backup.get(), slot_suffix, &old_blob)) { if (!ValidateAndSerializeMetadata(opener, *backup.get(), &old_blob)) { LERROR << "Error serializing backup metadata to repair corrupted primary"; return false; } Loading Loading
fs_mgr/liblp/Android.bp +5 −4 Original line number Diff line number Diff line Loading @@ -88,13 +88,14 @@ cc_defaults { static_libs: [ "libfs_mgr", ], } }, }, stl: "libc++_static", srcs: [ "builder_test.cpp", "super_layout_builder_test.cpp", "utility_test.cpp", "writer_test.cpp", ":TestPartitionOpener_group", ], } Loading @@ -105,7 +106,7 @@ cc_test { test_suites: ["device-tests"], auto_gen_config: true, require_root: true, host_supported: true host_supported: true, } cc_test { Loading
fs_mgr/liblp/images.cpp +8 −2 Original line number Diff line number Diff line Loading @@ -112,7 +112,10 @@ std::unique_ptr<LpMetadata> ReadFromImageFile(const std::string& image_file) { bool WriteToImageFile(borrowed_fd fd, const LpMetadata& input) { std::string geometry = SerializeGeometry(input.geometry); std::string metadata = SerializeMetadata(input); std::string metadata = ValidateAndSerializeMetadata(input); if (metadata.empty()) { return false; } std::string everything = geometry + metadata; Loading Loading @@ -298,7 +301,10 @@ bool ImageBuilder::Build() { } std::string geometry_blob = SerializeGeometry(geometry_); std::string metadata_blob = SerializeMetadata(metadata_); std::string metadata_blob = ValidateAndSerializeMetadata(metadata_); if (metadata_blob.empty()) { return false; } metadata_blob.resize(geometry_.metadata_max_size); // Two copies of geometry, then two copies of each metadata slot. Loading
fs_mgr/liblp/super_layout_builder.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -129,7 +129,10 @@ std::vector<SuperImageExtent> SuperLayoutBuilder::GetImageLayout() { // Write the primary and backup copies of each metadata slot. When flashing, // all metadata copies are the same, even for different slots. std::string metadata_bytes = SerializeMetadata(*metadata.get()); std::string metadata_bytes = ValidateAndSerializeMetadata(*metadata.get()); if (metadata_bytes.empty()) { return {}; } // Align metadata size to 4KB. This makes the layout easily compatible with // libsparse. Loading
fs_mgr/liblp/super_layout_builder_test.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -46,7 +46,9 @@ TEST(SuperImageTool, Layout) { ASSERT_NE(metadata, nullptr); auto geometry_blob = std::make_shared<std::string>(SerializeGeometry(metadata->geometry)); auto metadata_blob = std::make_shared<std::string>(SerializeMetadata(*metadata.get())); auto metadata_blob = std::make_shared<std::string>(ValidateAndSerializeMetadata(*metadata.get())); ASSERT_FALSE(metadata_blob->empty()); metadata_blob->resize(4_KiB, '\0'); auto extents = tool.GetImageLayout(); Loading
fs_mgr/liblp/writer.cpp +27 −28 Original line number Diff line number Diff line Loading @@ -47,7 +47,8 @@ static bool CompareGeometry(const LpMetadataGeometry& g1, const LpMetadataGeomet g1.logical_block_size == g2.logical_block_size; } std::string SerializeMetadata(const LpMetadata& input) { // Unvalidated serialization. static std::string SerializeMetadata(const LpMetadata& input) { LpMetadata metadata = input; LpMetadataHeader& header = metadata.header; Loading Loading @@ -81,26 +82,35 @@ std::string SerializeMetadata(const LpMetadata& input) { return header_blob + tables; } // Perform checks so we don't accidentally overwrite valid metadata with // potentially invalid metadata, or random partition data with metadata. static bool ValidateAndSerializeMetadata([[maybe_unused]] const IPartitionOpener& opener, const LpMetadata& metadata, const std::string& slot_suffix, std::string* blob) { // Validated serialization. std::string ValidateAndSerializeMetadata(const LpMetadata& metadata) { const LpMetadataGeometry& geometry = metadata.geometry; *blob = SerializeMetadata(metadata); std::string blob = SerializeMetadata(metadata); // Make sure we're writing within the space reserved. if (blob->size() > geometry.metadata_max_size) { LERROR << "Logical partition metadata is too large. " << blob->size() << " > " if (blob.size() > geometry.metadata_max_size) { LERROR << "Logical partition metadata is too large. " << blob.size() << " > " << geometry.metadata_max_size; return {}; } return blob; } // Perform checks so we don't accidentally overwrite valid metadata with // potentially invalid metadata, or random partition data with metadata. static bool ValidateAndSerializeMetadata([[maybe_unused]] const IPartitionOpener& opener, const LpMetadata& metadata, std::string* blob) { *blob = ValidateAndSerializeMetadata(metadata); if (blob->empty()) { return false; } // Make sure the device has enough space to store two backup copies of the // metadata. uint64_t reserved_size = LP_METADATA_GEOMETRY_SIZE + uint64_t(geometry.metadata_max_size) * geometry.metadata_slot_count; uint64_t reserved_size = LP_METADATA_GEOMETRY_SIZE + uint64_t(metadata.geometry.metadata_max_size) * metadata.geometry.metadata_slot_count; uint64_t total_reserved = LP_PARTITION_RESERVED_BYTES + reserved_size * 2; const LpMetadataBlockDevice* super_device = GetMetadataSuperBlockDevice(metadata); Loading @@ -116,13 +126,9 @@ static bool ValidateAndSerializeMetadata([[maybe_unused]] const IPartitionOpener for (const auto& block_device : metadata.block_devices) { std::string partition_name = GetBlockDevicePartitionName(block_device); if (block_device.flags & LP_BLOCK_DEVICE_SLOT_SUFFIXED) { if (slot_suffix.empty()) { LERROR << "Block device " << partition_name << " requires a slot suffix," << " which could not be derived from the super partition name."; LERROR << "Slot-suffixed super is no longer supported."; return false; } partition_name += slot_suffix; } if ((block_device.first_logical_sector + 1) * LP_SECTOR_SIZE > block_device.size) { LERROR << "Block device " << partition_name << " has invalid first sector " Loading Loading @@ -253,16 +259,11 @@ bool FlashPartitionTable(const IPartitionOpener& opener, const std::string& supe return false; } // This is only used in update_engine and fastbootd, where the super // partition should be specified as a name (or by-name link), and // therefore, we should be able to extract a slot suffix. std::string slot_suffix = GetPartitionSlotSuffix(super_partition); // Before writing geometry and/or logical partition tables, perform some // basic checks that the geometry and tables are coherent, and will fit // on the given block device. std::string metadata_blob; if (!ValidateAndSerializeMetadata(opener, metadata, slot_suffix, &metadata_blob)) { if (!ValidateAndSerializeMetadata(opener, metadata, &metadata_blob)) { return false; } Loading Loading @@ -328,13 +329,11 @@ bool UpdatePartitionTable(const IPartitionOpener& opener, const std::string& sup return false; } std::string slot_suffix = SlotSuffixForSlotNumber(slot_number); // Before writing geometry and/or logical partition tables, perform some // basic checks that the geometry and tables are coherent, and will fit // on the given block device. std::string blob; if (!ValidateAndSerializeMetadata(opener, metadata, slot_suffix, &blob)) { if (!ValidateAndSerializeMetadata(opener, metadata, &blob)) { return false; } Loading Loading @@ -366,7 +365,7 @@ bool UpdatePartitionTable(const IPartitionOpener& opener, const std::string& sup // synchronize the backup copy. This guarantees that a partial write // still leaves one copy intact. std::string old_blob; if (!ValidateAndSerializeMetadata(opener, *primary.get(), slot_suffix, &old_blob)) { if (!ValidateAndSerializeMetadata(opener, *primary.get(), &old_blob)) { LERROR << "Error serializing primary metadata to repair corrupted backup"; return false; } Loading @@ -378,7 +377,7 @@ bool UpdatePartitionTable(const IPartitionOpener& opener, const std::string& sup // The backup copy is coherent, and the primary is not. Sync it for // safety. std::string old_blob; if (!ValidateAndSerializeMetadata(opener, *backup.get(), slot_suffix, &old_blob)) { if (!ValidateAndSerializeMetadata(opener, *backup.get(), &old_blob)) { LERROR << "Error serializing backup metadata to repair corrupted primary"; return false; } Loading