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

Commit 4cbaf858 authored by Yifan Hong's avatar Yifan Hong
Browse files

libsnapshot_fuzzer: add new test directive to switch slot

Add a test directive to mimic the behavior of switching
slots after rebooting. This changes the behavior of
SnapshotFuzzDeviceInfo and has nothing to do with the
API surface of ISnapshotManager. It also relies on the
fact that SnapshotManager does not record the current
slot suffix and always reads from IDeviceInfo.

Test: run with corpus
Bug: 154633114
Change-Id: I6ebb68afb8519feaa05bd3e4817f0e06596fc920
parent 322ea7ae
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ message SnapshotManagerActionProto {
        bool has_metadata_device_object = 1;
        bool metadata_mounted = 2;
    }
    reserved 18 to 9999;
    oneof value {
        NoArgs begin_update = 1;
        NoArgs cancel_update = 2;
@@ -82,6 +83,9 @@ message SnapshotManagerActionProto {
        NoArgs dump = 15;
        NoArgs ensure_metadata_mounted = 16;
        NoArgs get_snapshot_merge_stats_instance = 17;

        // Test directives that has nothing to do with ISnapshotManager API surface.
        NoArgs switch_slot = 10000;
    }
}

+15 −3
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ std::string GetDsuSlot(const std::string& install_dir) {
namespace android::snapshot {

const SnapshotFuzzData* current_data = nullptr;
const SnapshotTestModule* current_module = nullptr;

SnapshotFuzzEnv* GetSnapshotFuzzEnv();

@@ -155,6 +156,13 @@ SNAPSHOT_FUZZ_FUNCTION(MapUpdateSnapshot, const CreateLogicalPartitionParamsProt
    (void)snapshot->MapUpdateSnapshot(params, &path);
}

SNAPSHOT_FUZZ_FUNCTION(SwitchSlot) {
    (void)snapshot;
    CHECK(current_module != nullptr);
    CHECK(current_module->device_info != nullptr);
    current_module->device_info->SwitchSlot();
}

// During global init, log all messages to stdio. This is only done once.
int AllowLoggingDuringGlobalInit() {
    SetLogger(&StdioLogger);
@@ -208,8 +216,12 @@ DEFINE_PROTO_FUZZER(const SnapshotFuzzData& snapshot_fuzz_data) {
    auto env = GetSnapshotFuzzEnv();
    env->CheckSoftReset();

    auto snapshot_manager = env->CheckCreateSnapshotManager(snapshot_fuzz_data);
    CHECK(snapshot_manager);
    auto test_module = env->CheckCreateSnapshotManager(snapshot_fuzz_data);
    current_module = &test_module;
    CHECK(test_module.snapshot);

    SnapshotManagerAction::ExecuteAll(test_module.snapshot.get(), snapshot_fuzz_data.actions());

    SnapshotManagerAction::ExecuteAll(snapshot_manager.get(), snapshot_fuzz_data.actions());
    current_module = nullptr;
    current_data = nullptr;
}
+8 −6
Original line number Diff line number Diff line
@@ -260,9 +260,10 @@ std::unique_ptr<AutoDevice> SnapshotFuzzEnv::CheckMapImage(const std::string& im
    return std::make_unique<AutoDetachLoopDevice>(control, *mapped_path);
}

std::unique_ptr<ISnapshotManager> SnapshotFuzzEnv::CheckCreateSnapshotManager(
        const SnapshotFuzzData& data) {
SnapshotTestModule SnapshotFuzzEnv::CheckCreateSnapshotManager(const SnapshotFuzzData& data) {
    SnapshotTestModule ret;
    auto partition_opener = std::make_unique<TestPartitionOpener>(super());
    ret.opener = partition_opener.get();
    CheckWriteSuperMetadata(data, *partition_opener);
    auto metadata_dir = fake_root_->tmp_path() + "/snapshot_metadata";
    PCHECK(Mkdir(metadata_dir));
@@ -270,15 +271,16 @@ std::unique_ptr<ISnapshotManager> SnapshotFuzzEnv::CheckCreateSnapshotManager(
        PCHECK(Mkdir(metadata_dir + "/snapshots"));
    }

    auto device_info = new SnapshotFuzzDeviceInfo(data.device_info_data(),
    ret.device_info = new SnapshotFuzzDeviceInfo(data.device_info_data(),
                                                 std::move(partition_opener), metadata_dir);
    auto snapshot = SnapshotManager::New(device_info /* takes ownership */);
    auto snapshot = SnapshotManager::New(ret.device_info /* takes ownership */);
    snapshot->images_ =
            CheckCreateFakeImageManager(fake_root_->tmp_path() + "/images_manager_metadata",
                                        fake_data_mount_point_ + "/image_manager_data");
    snapshot->has_local_image_manager_ = data.manager_data().is_local_image_manager();
    ret.snapshot = std::move(snapshot);

    return snapshot;
    return ret;
}

const std::string& SnapshotFuzzEnv::super() const {
+15 −5
Original line number Diff line number Diff line
@@ -31,12 +31,19 @@
namespace android::snapshot {

class AutoMemBasedDir;
class SnapshotFuzzDeviceInfo;

class DummyAutoDevice : public AutoDevice {
  public:
    DummyAutoDevice(bool mounted) : AutoDevice(mounted ? "dummy" : "") {}
};

struct SnapshotTestModule {
    std::unique_ptr<ISnapshotManager> snapshot;
    SnapshotFuzzDeviceInfo* device_info = nullptr;
    TestPartitionOpener* opener = nullptr;
};

// Prepare test environment. This has a heavy overhead and should be done once.
class SnapshotFuzzEnv {
  public:
@@ -54,7 +61,7 @@ class SnapshotFuzzEnv {
    // Create a snapshot manager for this test run.
    // Client is responsible for maintaining the lifetime of |data| over the life time of
    // ISnapshotManager.
    std::unique_ptr<ISnapshotManager> CheckCreateSnapshotManager(const SnapshotFuzzData& data);
    SnapshotTestModule CheckCreateSnapshotManager(const SnapshotFuzzData& data);

    // Return path to super partition.
    const std::string& super() const;
@@ -105,10 +112,8 @@ class SnapshotFuzzDeviceInfo : public ISnapshotManager::IDeviceInfo {
    }

    // Following APIs are fuzzed.
    std::string GetSlotSuffix() const override { return data_->slot_suffix_is_a() ? "_a" : "_b"; }
    std::string GetOtherSlotSuffix() const override {
        return data_->slot_suffix_is_a() ? "_b" : "_a";
    }
    std::string GetSlotSuffix() const override { return CurrentSlotIsA() ? "_a" : "_b"; }
    std::string GetOtherSlotSuffix() const override { return CurrentSlotIsA() ? "_b" : "_a"; }
    bool IsOverlayfsSetup() const override { return data_->is_overlayfs_setup(); }
    bool SetBootControlMergeStatus(android::hardware::boot::V1_1::MergeStatus) override {
        return data_->allow_set_boot_control_merge_status();
@@ -118,10 +123,15 @@ class SnapshotFuzzDeviceInfo : public ISnapshotManager::IDeviceInfo {
    }
    bool IsRecovery() const override { return data_->is_recovery(); }

    void SwitchSlot() { switched_slot_ = !switched_slot_; }

  private:
    const FuzzDeviceInfoData* data_;
    std::unique_ptr<TestPartitionOpener> partition_opener_;
    std::string metadata_dir_;
    bool switched_slot_ = false;

    bool CurrentSlotIsA() const { return data_->slot_suffix_is_a() != switched_slot_; }
};

}  // namespace android::snapshot