From 82035d6b82ef71d6970abd4992ea6ecf8282debb Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Mon, 4 May 2020 16:59:27 -0700 Subject: [PATCH] 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 (cherry picked from commit e6c1a8427643a066d4f272a9ef9f9f1bd8b7449e) Merged-In: I1ec39744480e514ae7a7902643ed863e0ca0a340 --- .../include/libsnapshot/snapshot.h | 4 +++ fs_mgr/libsnapshot/snapshot.cpp | 26 ++++++++++++++++--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h index 1daa83b8a..72fc7b2b3 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h @@ -536,6 +536,10 @@ class SnapshotManager final { bool ProcessUpdateStateOnDataWipe(bool allow_forward_merge, const std::function& 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 device_; diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp index c9fa28e9f..ec33aa6e5 100644 --- a/fs_mgr/libsnapshot/snapshot.cpp +++ b/fs_mgr/libsnapshot/snapshot.cpp @@ -1674,7 +1674,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; } @@ -1771,7 +1771,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; } @@ -2347,7 +2347,6 @@ Return SnapshotManager::InitializeUpdateSnapshots( const std::map& all_snapshot_status) { CHECK(lock); - auto& dm = DeviceMapper::Instance(); CreateLogicalPartitionParams cow_params{ .block_device = LP_METADATA_DEFAULT_PARTITION_NAME, .metadata = exported_target_metadata, @@ -2372,7 +2371,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(); } @@ -2685,5 +2684,24 @@ bool SnapshotManager::UpdateForwardMergeIndicator(bool wipe) { return true; } +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