libsnapshot_fuzzer: Properly unmap images

Instead of unsetting gsid.mapped_images.* directly, properly unmap
them through image manager. This also avoids interference between
different fuzzer runs because the gsid.mapped_images.* properties
are not destroyed in SoftReset.

Test: libsnapshot_fuzzer_test then reboot, device can come up
Fixes: 156689792
Bug: 156380383
Change-Id: I7a198312f63b4b17d8ea96c7df2dd112a910d004
This commit is contained in:
Yifan Hong 2020-05-15 14:32:07 -07:00
parent 8cef7c7d70
commit 3013e6efcc
2 changed files with 84 additions and 12 deletions

View File

@ -27,7 +27,6 @@
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <cutils/properties.h>
#include <fs_mgr.h>
#include <libsnapshot/auto_device.h>
#include <libsnapshot/snapshot.h>
@ -165,14 +164,6 @@ void InsertProperty(const char* key, const char* /*name*/, void* cookie) {
reinterpret_cast<PropertyList*>(cookie)->insert(key);
}
void CheckUnsetGsidProps() {
PropertyList list;
property_list(&InsertProperty, reinterpret_cast<void*>(&list));
for (const auto& key : list) {
SetProperty(key, "");
}
}
// Attempt to delete all devices that is based on dev_name, including itself.
void CheckDeleteDeviceMapperTree(const std::string& dev_name, bool known_allow_delete = false,
uint64_t depth = 100) {
@ -344,7 +335,6 @@ class AutoMemBasedDir : public AutoDevice {
};
SnapshotFuzzEnv::SnapshotFuzzEnv() {
CheckUnsetGsidProps();
CheckCleanupDeviceMapperDevices();
CheckDetachLoopDevices();
CheckUmountAll();
@ -368,7 +358,6 @@ SnapshotFuzzEnv::SnapshotFuzzEnv() {
}
SnapshotFuzzEnv::~SnapshotFuzzEnv() {
CheckUnsetGsidProps();
CheckCleanupDeviceMapperDevices();
mounted_data_ = nullptr;
auto_delete_data_mount_point_ = nullptr;
@ -396,7 +385,7 @@ std::unique_ptr<IImageManager> SnapshotFuzzEnv::CheckCreateFakeImageManager(
const std::string& metadata_dir, const std::string& data_dir) {
PCHECK(Mkdir(metadata_dir));
PCHECK(Mkdir(data_dir));
return ImageManager::Open(metadata_dir, data_dir);
return SnapshotFuzzImageManager::Open(metadata_dir, data_dir);
}
// Helper to create a loop device for a file.
@ -507,4 +496,21 @@ std::unique_ptr<AutoDevice> SnapshotFuzzEnv::CheckMountFormatData(const std::str
return std::make_unique<AutoUnmount>(mount_point);
}
SnapshotFuzzImageManager::~SnapshotFuzzImageManager() {
// Remove relevant gsid.mapped_images.* props.
for (const auto& name : mapped_) {
CHECK(UnmapImageIfExists(name)) << "Cannot unmap " << name;
}
}
bool SnapshotFuzzImageManager::MapImageDevice(const std::string& name,
const std::chrono::milliseconds& timeout_ms,
std::string* path) {
if (impl_->MapImageDevice(name, timeout_ms, path)) {
mapped_.insert(name);
return true;
}
return false;
}
} // namespace android::snapshot

View File

@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include <memory>
#include <set>
#include <string>
#include <android-base/file.h>
@ -134,4 +136,68 @@ class SnapshotFuzzDeviceInfo : public ISnapshotManager::IDeviceInfo {
bool CurrentSlotIsA() const { return data_->slot_suffix_is_a() != switched_slot_; }
};
// A spy class on ImageManager implementation. Upon destruction, unmaps all images
// map through this object.
class SnapshotFuzzImageManager : public android::fiemap::IImageManager {
public:
static std::unique_ptr<SnapshotFuzzImageManager> Open(const std::string& metadata_dir,
const std::string& data_dir) {
auto impl = android::fiemap::ImageManager::Open(metadata_dir, data_dir);
if (impl == nullptr) return nullptr;
return std::unique_ptr<SnapshotFuzzImageManager>(
new SnapshotFuzzImageManager(std::move(impl)));
}
~SnapshotFuzzImageManager();
// Spied APIs.
bool MapImageDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms,
std::string* path) override;
// Other functions call through.
android::fiemap::FiemapStatus CreateBackingImage(
const std::string& name, uint64_t size, int flags,
std::function<bool(uint64_t, uint64_t)>&& on_progress) override {
return impl_->CreateBackingImage(name, size, flags, std::move(on_progress));
}
bool DeleteBackingImage(const std::string& name) override {
return impl_->DeleteBackingImage(name);
}
bool UnmapImageDevice(const std::string& name) override {
return impl_->UnmapImageDevice(name);
}
bool BackingImageExists(const std::string& name) override {
return impl_->BackingImageExists(name);
}
bool IsImageMapped(const std::string& name) override { return impl_->IsImageMapped(name); }
bool MapImageWithDeviceMapper(const IPartitionOpener& opener, const std::string& name,
std::string* dev) override {
return impl_->MapImageWithDeviceMapper(opener, name, dev);
}
bool GetMappedImageDevice(const std::string& name, std::string* device) override {
return impl_->GetMappedImageDevice(name, device);
}
bool MapAllImages(const std::function<bool(std::set<std::string>)>& init) override {
return impl_->MapAllImages(init);
}
bool DisableImage(const std::string& name) override { return impl_->DisableImage(name); }
bool RemoveDisabledImages() override { return impl_->RemoveDisabledImages(); }
std::vector<std::string> GetAllBackingImages() override { return impl_->GetAllBackingImages(); }
android::fiemap::FiemapStatus ZeroFillNewImage(const std::string& name,
uint64_t bytes) override {
return impl_->ZeroFillNewImage(name, bytes);
}
bool RemoveAllImages() override { return impl_->RemoveAllImages(); }
bool UnmapImageIfExists(const std::string& name) override {
return impl_->UnmapImageIfExists(name);
}
private:
std::unique_ptr<android::fiemap::IImageManager> impl_;
std::set<std::string> mapped_;
SnapshotFuzzImageManager(std::unique_ptr<android::fiemap::IImageManager>&& impl)
: impl_(std::move(impl)) {}
};
} // namespace android::snapshot