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

Commit e6c1a842 authored by Yifan Hong's avatar Yifan Hong
Browse files

libsnapshot: fix incorrect assumption of cow images

libsnapshot used to assume CoW images are always mapped
with device mapper, and call GetDeviceString directly.
However, in tests, it is possible that it is mapped as loop
devices. Fix the incorrect assumption and calls
IImageManager::GetMappedImageDevice instead.

Test: libsnapshot_fuzzer with corpus
Bug: 154633114
Change-Id: I1ec39744480e514ae7a7902643ed863e0ca0a340
parent 2e660433
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -580,6 +580,10 @@ class SnapshotManager final : public ISnapshotManager {
    bool ProcessUpdateStateOnDataWipe(bool allow_forward_merge,
                                      const std::function<bool()>& callback);

    // Return device string of a mapped image, or if it is not available, the mapped image path.
    bool GetMappedImageDeviceStringOrPath(const std::string& device_name,
                                          std::string* device_string_or_mapped_path);

    std::string gsid_dir_;
    std::string metadata_dir_;
    std::unique_ptr<IDeviceInfo> device_;
+22 −4
Original line number Diff line number Diff line
@@ -1691,7 +1691,7 @@ bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock,
        return false;
    }
    std::string cow_device;
    if (!dm.GetDeviceString(cow_name, &cow_device)) {
    if (!GetMappedImageDeviceStringOrPath(cow_name, &cow_device)) {
        LOG(ERROR) << "Could not determine major/minor for: " << cow_name;
        return false;
    }
@@ -1788,7 +1788,7 @@ bool SnapshotManager::MapCowDevices(LockedFile* lock, const CreateLogicalPartiti
    // If the COW image exists, append it as the last extent.
    if (snapshot_status.cow_file_size() > 0) {
        std::string cow_image_device;
        if (!dm.GetDeviceString(cow_image_name, &cow_image_device)) {
        if (!GetMappedImageDeviceStringOrPath(cow_image_name, &cow_image_device)) {
            LOG(ERROR) << "Cannot determine major/minor for: " << cow_image_name;
            return false;
        }
@@ -2364,7 +2364,6 @@ Return SnapshotManager::InitializeUpdateSnapshots(
        const std::map<std::string, SnapshotStatus>& all_snapshot_status) {
    CHECK(lock);

    auto& dm = DeviceMapper::Instance();
    CreateLogicalPartitionParams cow_params{
            .block_device = LP_METADATA_DEFAULT_PARTITION_NAME,
            .metadata = exported_target_metadata,
@@ -2389,7 +2388,7 @@ Return SnapshotManager::InitializeUpdateSnapshots(
        }

        std::string cow_path;
        if (!dm.GetDmDevicePathByName(cow_name, &cow_path)) {
        if (!images_->GetMappedImageDevice(cow_name, &cow_path)) {
            LOG(ERROR) << "Cannot determine path for " << cow_name;
            return Return::Error();
        }
@@ -2742,5 +2741,24 @@ ISnapshotMergeStats* SnapshotManager::GetSnapshotMergeStatsInstance() {
    return SnapshotMergeStats::GetInstance(*this);
}

bool SnapshotManager::GetMappedImageDeviceStringOrPath(const std::string& device_name,
                                                       std::string* device_string_or_mapped_path) {
    auto& dm = DeviceMapper::Instance();
    // Try getting the device string if it is a device mapper device.
    if (dm.GetState(device_name) != DmDeviceState::INVALID) {
        return dm.GetDeviceString(device_name, device_string_or_mapped_path);
    }

    // Otherwise, get path from IImageManager.
    if (!images_->GetMappedImageDevice(device_name, device_string_or_mapped_path)) {
        return false;
    }

    LOG(WARNING) << "Calling GetMappedImageDevice with local image manager; device "
                 << (device_string_or_mapped_path ? *device_string_or_mapped_path : "(nullptr)")
                 << "may not be available in first stage init! ";
    return true;
}

}  // namespace snapshot
}  // namespace android