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

Commit 6aaae780 authored by David Anderson's avatar David Anderson
Browse files

Remove the libsnapshot fuzzer.

The only bugs in the corpus here were bugs in the fuzzer itself. Part
of the reason is its speed - it's limited by the dm layer so can't fuzz
optimally. That also makes it difficult to maintain, since it's
effectively a functional OTA fuzzer, and is very sensitive to the
implementation of libsnapshot.

After discussing this through with the team, we think the best course is
to sunset this and aim for improved unit and functional OTA testing.

Bug: 227656961
Test: builds
Change-Id: I2ecf838be336ee06459988ef282f0694cebfce51
parent 42908c45
Loading
Loading
Loading
Loading
+0 −74
Original line number Diff line number Diff line
@@ -366,80 +366,6 @@ cc_test {
    gtest: false,
}

cc_defaults {
    name: "libsnapshot_fuzzer_defaults",
    defaults: [
        "libsnapshot_cow_defaults",
    ],
    native_coverage : true,
    srcs: [
        // Compile the protobuf definition again with type full.
        "android/snapshot/snapshot_fuzz.proto",
        "update_engine/update_metadata.proto",
        "fuzz_utils.cpp",
        "snapshot_fuzz.cpp",
        "snapshot_fuzz_utils.cpp",

        // Compile libsnapshot sources directly to avoid dependency
        // to update_metadata-protos
        ":libsnapshot_sources",
    ],
    static_libs: [
        "libbase",
        "libbrotli",
        "libc++fs",
        "libchrome",
        "libcrypto_static",
        "libcutils",
        "libext2_uuid",
        "libext4_utils",
        "libfstab",
        "libfs_mgr",
        "libgtest", // from libsnapshot_test_helpers
        "libgmock", // from libsnapshot_test_helpers
        "liblog",
        "liblp",
        "libsnapshot_cow",
        "libsnapshot_test_helpers",
        "libprotobuf-mutator",
        "libz",
    ],
    header_libs: [
        "libfiemap_headers",
        "libstorage_literals_headers",
        "libupdate_engine_headers",
    ],
    proto: {
        type: "full",
        canonical_path_from_root: false,
        local_include_dirs: ["."],
    },
}

cc_fuzz {
    name: "libsnapshot_fuzzer",
    defaults: ["libsnapshot_fuzzer_defaults"],
    corpus: ["corpus/*"],
    fuzz_config: {
        cc: ["android-virtual-ab+bugs@google.com"],
        componentid: 30545,
        hotlists: ["1646452"],
        fuzz_on_haiku_host: false,
        fuzz_on_haiku_device: true,
    },
}

cc_test {
    name: "libsnapshot_fuzzer_test",
    defaults: ["libsnapshot_fuzzer_defaults"],
    data: ["corpus/*"],
    test_suites: [
        "device-tests",
    ],
    auto_gen_config: true,
    require_root: true,
}

cc_test {
    name: "cow_api_test",
    defaults: [
+0 −110
Original line number Diff line number Diff line
// Copyright (C) 2020 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";
package android.snapshot;

import "update_engine/update_metadata.proto";

// Controls the behavior of IDeviceInfo.
// Next: 6
message FuzzDeviceInfoData {
    bool slot_suffix_is_a = 1;
    bool is_overlayfs_setup = 2;
    bool allow_set_boot_control_merge_status = 3;
    bool allow_set_slot_as_unbootable = 4;
    bool is_recovery = 5;
}

// Controls the behavior of the test SnapshotManager.
// Next: 2
message FuzzSnapshotManagerData {
    bool is_local_image_manager = 1;
}

// A simplified version of CreateLogicalPartitionParams for fuzzing.
// Next: 9
message CreateLogicalPartitionParamsProto {
    bool use_correct_super = 1;
    string block_device = 2;
    bool has_metadata_slot = 3;
    uint32 metadata_slot = 4;
    string partition_name = 5;
    bool force_writable = 6;
    int64 timeout_millis = 7;
    string device_name = 8;
}

// Mimics the API of ISnapshotManager. Defines one action on the snapshot
// manager.
// Next: 18
message SnapshotManagerActionProto {
    message NoArgs {}
    message ProcessUpdateStateArgs {
        bool has_before_cancel = 1;
        bool fail_before_cancel = 2;
    }
    message CreateLogicalAndSnapshotPartitionsArgs {
        bool use_correct_super = 1;
        string super = 2;
        int64 timeout_millis = 3;
    }
    message RecoveryCreateSnapshotDevicesArgs {
        bool has_metadata_device_object = 1;
        bool metadata_mounted = 2;
    }
    reserved 18 to 9999;
    oneof value {
        NoArgs begin_update = 1;
        NoArgs cancel_update = 2;
        bool finished_snapshot_writes = 3;
        NoArgs initiate_merge = 4;
        ProcessUpdateStateArgs process_update_state = 5;
        bool get_update_state = 6;
        chromeos_update_engine.DeltaArchiveManifest create_update_snapshots = 7;
        CreateLogicalPartitionParamsProto map_update_snapshot = 8;
        string unmap_update_snapshot = 9;
        NoArgs need_snapshots_in_first_stage_mount = 10;
        CreateLogicalAndSnapshotPartitionsArgs create_logical_and_snapshot_partitions = 11;
        bool handle_imminent_data_wipe = 12;
        NoArgs recovery_create_snapshot_devices = 13;
        RecoveryCreateSnapshotDevicesArgs recovery_create_snapshot_devices_with_metadata = 14;
        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;
    }
}

// Includes all data that needs to be fuzzed.
message SnapshotFuzzData {
    FuzzDeviceInfoData device_info_data = 1;
    FuzzSnapshotManagerData manager_data = 2;

    // If true:
    // - if super_data is empty, create empty super partition metadata.
    // - otherwise, create super partition metadata accordingly.
    // If false, no valid super partition metadata (it is zeroed)
    bool is_super_metadata_valid = 3;
    chromeos_update_engine.DeltaArchiveManifest super_data = 4;

    // Whether the directory that mocks /metadata/ota/snapshot is created.
    bool has_metadata_snapshots_dir = 5;

    // More data used to prep the test before running actions.
    reserved 6 to 9999;
    repeated SnapshotManagerActionProto actions = 10000;
}
+0 −41
Original line number Diff line number Diff line
device_info_data {
  allow_set_slot_as_unbootable: true
  is_recovery: true
}
is_super_metadata_valid: true
super_data {
  partitions {
    partition_name: "sys_a"
    new_partition_info {
      size: 3145728
    }
  }
  partitions {
    partition_name: "vnnd_"
    new_partition_info {
      size: 3145728
    }
  }
  partitions {
    partition_name: "prd_a"
    new_partition_info {
    }
  }
  dynamic_partition_metadata {
    groups {
      name: "group_google_dp_a"
      size: 34375467008
      partition_names: "sys_a"
      partition_names: "vnd_a"
      partition_names: "prd_a"
    }
  }
}
has_metadata_snapshots_dir: true
actions {
  handle_imminent_data_wipe: true
}
actions {
  begin_update {
  }
}
+0 −161
Original line number Diff line number Diff line
device_info_data {
  slot_suffix_is_a: true
  is_overlayfs_setup: false
  allow_set_boot_control_merge_status: true
  allow_set_slot_as_unbootable: true
  is_recovery: false
}
manager_data {
  is_local_image_manager: false
}
is_super_metadata_valid: true
super_data {
  partitions {
    partition_name: "sys_a"
    new_partition_info {
      size: 3145728
    }
  }
  partitions {
    partition_name: "vnd_a"
    new_partition_info {
      size: 3145728
    }
  }
  partitions {
    partition_name: "prd_a"
    new_partition_info {
      size: 3145728
    }
  }
  dynamic_partition_metadata {
    groups {
      name: "group_google_dp_a"
      size: 15728640
      partition_names: "sys_a"
      partition_names: "vnd_a"
      partition_names: "prd_a"
    }
  }
}
has_metadata_snapshots_dir: true
actions {
  begin_update {
  }
}
actions {
  create_update_snapshots {
    partitions {
      partition_name: "sys"
      new_partition_info {
        size: 3878912
      }
      operations {
        type: ZERO,
        dst_extents {
          start_block: 0
          num_blocks: 947
        }
      }
    }
    partitions {
      partition_name: "vnd"
      new_partition_info {
        size: 3878912
      }
      operations {
        type: ZERO,
        dst_extents {
          start_block: 0
          num_blocks: 947
        }
      }
    }
    partitions {
      partition_name: "prd"
      new_partition_info {
        size: 3878912
      }
      operations {
        type: ZERO,
        dst_extents {
          start_block: 0
          num_blocks: 947
        }
      }
    }
    dynamic_partition_metadata {
      groups {
        name: "group_google_dp"
        size: 15728640
        partition_names: "sys"
        partition_names: "vnd"
        partition_names: "prd"
      }
    }
  }
}
actions {
  map_update_snapshot {
    use_correct_super: true
    has_metadata_slot: true
    metadata_slot: 1
    partition_name: "sys_b"
    force_writable: true
    timeout_millis: 3000
  }
}
actions {
  map_update_snapshot {
    use_correct_super: true
    has_metadata_slot: true
    metadata_slot: 1
    partition_name: "vnd_b"
    force_writable: true
    timeout_millis: 3000
  }
}
actions {
  map_update_snapshot {
    use_correct_super: true
    has_metadata_slot: true
    metadata_slot: 1
    partition_name: "prd_b"
    force_writable: true
    timeout_millis: 3000
  }
}
actions {
  finished_snapshot_writes: false
}
actions {
  unmap_update_snapshot: "sys_b"
}
actions {
  unmap_update_snapshot: "vnd_b"
}
actions {
  unmap_update_snapshot: "prd_b"
}
actions {
  switch_slot {
  }
}
actions {
  need_snapshots_in_first_stage_mount {
  }
}
actions {
  create_logical_and_snapshot_partitions {
    use_correct_super: true
    timeout_millis: 5000
  }
}
actions {
  initiate_merge {
  }
}
actions {
  process_update_state {
  }
}

fs_mgr/libsnapshot/fuzz.sh

deleted100755 → 0
+0 −90
Original line number Diff line number Diff line
#!/bin/bash
PROJECT_PATH=system/core/fs_mgr/libsnapshot
FUZZ_TARGET=libsnapshot_fuzzer
TARGET_ARCH=$(get_build_var TARGET_ARCH)
FUZZ_BINARY=/data/fuzz/${TARGET_ARCH}/${FUZZ_TARGET}/${FUZZ_TARGET}
DEVICE_INIT_CORPUS_DIR=/data/fuzz/${TARGET_ARCH}/${FUZZ_TARGET}/corpus
DEVICE_GENERATED_CORPUS_DIR=/data/local/tmp/${FUZZ_TARGET}/corpus
DEVICE_GCOV_DIR=/data/local/tmp/${FUZZ_TARGET}/gcov
HOST_SCRATCH_DIR=/tmp/${FUZZ_TARGET}
GCOV_TOOL=${HOST_SCRATCH_DIR}/llvm-gcov

build_normal() (
    pushd $(gettop)
    NATIVE_COVERAGE="" NATIVE_LINE_COVERAGE="" NATIVE_COVERAGE_PATHS="" m ${FUZZ_TARGET}
    ret=$?
    popd
    return ${ret}
)

build_cov() {
    pushd $(gettop)
    NATIVE_COVERAGE="true" NATIVE_LINE_COVERAGE="true" NATIVE_COVERAGE_PATHS="${PROJECT_PATH}" m ${FUZZ_TARGET}
    ret=$?
    popd
    return ${ret}
}

prepare_device() {
    adb root && adb remount &&
    adb shell mkdir -p ${DEVICE_GENERATED_CORPUS_DIR} &&
    adb shell rm -rf ${DEVICE_GCOV_DIR} &&
    adb shell mkdir -p ${DEVICE_GCOV_DIR}
}

push_binary() {
    adb push ${ANDROID_PRODUCT_OUT}/${FUZZ_BINARY} ${FUZZ_BINARY} &&
    adb push ${ANDROID_PRODUCT_OUT}/${DEVICE_INIT_CORPUS_DIR} $(dirname ${FUZZ_BINARY})
}

prepare_host() {
    which lcov || {
        echo "please run:";
        echo "   sudo apt-get install lcov ";
        return 1;
    }
    rm -rf ${HOST_SCRATCH_DIR} &&
    mkdir -p ${HOST_SCRATCH_DIR}
}

# run_snapshot_fuzz -runs=10000
generate_corpus() {
    [[ "$@" ]] || { echo "run with -runs=X"; return 1; }

    prepare_device &&
    build_normal &&
    push_binary &&
    adb shell ${FUZZ_BINARY} "$@" ${DEVICE_INIT_CORPUS_DIR} ${DEVICE_GENERATED_CORPUS_DIR}
}

run_snapshot_fuzz() {
    prepare_device &&
    build_cov &&
    push_binary &&
    adb shell GCOV_PREFIX=${DEVICE_GCOV_DIR} GCOV_PREFIX_STRIP=3 \
        ${FUZZ_BINARY} \
        -runs=0 \
        ${DEVICE_INIT_CORPUS_DIR} ${DEVICE_GENERATED_CORPUS_DIR}
}

show_fuzz_result() {
    prepare_host &&
    unzip -o -j -d ${HOST_SCRATCH_DIR} ${ANDROID_PRODUCT_OUT}/coverage/data/fuzz/${TARGET_ARCH}/${FUZZ_TARGET}/${FUZZ_TARGET}.zip &&
    adb shell find ${DEVICE_GCOV_DIR} -type f | xargs -I {} adb pull {} ${HOST_SCRATCH_DIR} &&
    ls ${HOST_SCRATCH_DIR} &&
    cat > ${GCOV_TOOL} <<< '
#!/bin/bash
exec llvm-cov gcov "$@"
' &&
    chmod +x ${GCOV_TOOL} &&
    lcov --directory ${HOST_SCRATCH_DIR} --base-directory $(gettop) --gcov-tool ${GCOV_TOOL} --capture -o ${HOST_SCRATCH_DIR}/report.cov &&
    genhtml ${HOST_SCRATCH_DIR}/report.cov -o ${HOST_SCRATCH_DIR}/html &&
    echo file://$(realpath ${HOST_SCRATCH_DIR}/html/index.html)
}

# run_snapshot_fuzz -runs=10000
run_snapshot_fuzz_all() {
    generate_corpus "$@" &&
    run_snapshot_fuzz &&
    show_fuzz_result
}
Loading