Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0a949a8b authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes Ib6f3d17a,I4f2b3037 into main

* changes:
  liblp: Fix lack of validation in file serialization.
  liblp: Remove unused slot-suffixing code.
parents 43674f52 29033a81
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -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",
    ],
}
@@ -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 {
+8 −2
Original line number Diff line number Diff line
@@ -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;

@@ -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.
+4 −1
Original line number Diff line number Diff line
@@ -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.
+3 −1
Original line number Diff line number Diff line
@@ -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();
+27 −28
Original line number Diff line number Diff line
@@ -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;

@@ -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);
@@ -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 "
@@ -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;
    }

@@ -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;
    }

@@ -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;
        }
@@ -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