From fef6c8d1b15fdcc1804d661c795e7963c685e683 Mon Sep 17 00:00:00 2001 From: Romain Malmain Date: Mon, 22 Apr 2024 18:17:22 +0200 Subject: [PATCH] Run qemu_systemmode tests with self-hosted runners (#2018) * run qemu fuzzers (qemu_systemmode only for now) in self-hosted runners * Remove qemu-related fuzzers to general fuzzers * fix * Install dependencies before anything else * Do not use sudo * Install sudo * Revert "Install dependencies before anything else" This reverts commit 107addad5d9f68dec5a9af50831112cd72c28f4d. * added qemu specific prerequisites * add -y flag * Format with nightly * Do not use nightly only. Install fmt and clippy for stable as well. * Install qemu-img for qemu * fix qemu-img install * apt update * Changed timeout. * Fix qemu_systemmode test * fmt * clippy + decorrelate build and run for qemu_systemmode. * fix fuzzer * clippy * add sqlite3-dev to package prerequisites. * add arm-none-eabi-gcc * fix profile dir * fix condition. * Run less QEMU stuff faster --------- Co-authored-by: Toka --- .github/workflows/build_and_test.yml | 37 ++++++++++-- .../fuzzer-tester-prepare/action.yml | 7 ++- .../qemu-fuzzer-tester-prepare/action.yml | 8 +++ Dockerfile | 2 +- fuzzers/frida_gdiplus/src/fuzzer.rs | 2 +- fuzzers/qemu_cmin/Makefile.toml | 27 +++++++++ fuzzers/qemu_coverage/Makefile.toml | 27 +++++++++ fuzzers/qemu_coverage/src/fuzzer.rs | 4 +- fuzzers/qemu_launcher/README.md | 3 +- fuzzers/qemu_systemmode/Makefile.toml | 43 ++++++++++---- fuzzers/qemu_systemmode/README.md | 18 +++++- fuzzers/qemu_systemmode/example/main.c | 4 +- .../concolic/serialization_format.rs | 2 - libafl_bolts/src/os/unix_signals.rs | 2 +- libafl_cc/src/lib.rs | 1 - libafl_derive/src/lib.rs | 1 - libafl_frida/src/lib.rs | 1 - libafl_qemu/libafl_qemu_build/src/build.rs | 57 ++++++++++++------- libafl_qemu/src/hooks.rs | 4 +- libafl_sugar/src/lib.rs | 1 - libafl_targets/src/lib.rs | 1 - libafl_tinyinst/src/lib.rs | 1 - .../{test_all_fuzzers.sh => test_fuzzer.sh} | 4 +- 23 files changed, 198 insertions(+), 59 deletions(-) create mode 100644 .github/workflows/qemu-fuzzer-tester-prepare/action.yml rename scripts/{test_all_fuzzers.sh => test_fuzzer.sh} (93%) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index b75a5ae0e0..9f3d9da46e 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -309,7 +309,7 @@ jobs: - ./fuzzers/backtrace_baby_fuzzers - ./fuzzers/fuzzbench_qemu - ./fuzzers/nyx_libxml2_parallel - - ./fuzzers/qemu_launcher + # - ./fuzzers/qemu_launcher - ./fuzzers/frida_gdiplus - ./fuzzers/libfuzzer_stb_image_concolic - ./fuzzers/nautilus_sync @@ -359,7 +359,32 @@ jobs: - name: Build and run example fuzzers (Linux) if: runner.os == 'Linux' shell: bash - run: RUN_ON_CI=1 LLVM_CONFIG=llvm-config ./scripts/test_all_fuzzers.sh ${{ matrix.fuzzer }} + run: RUN_ON_CI=1 LLVM_CONFIG=llvm-config ./scripts/test_fuzzer.sh ${{ matrix.fuzzer }} + + fuzzers-qemu: + strategy: + matrix: + os: [ubuntu-latest] + fuzzer: + - ./fuzzers/qemu_cmin + - ./fuzzers/qemu_systemmode + - ./fuzzers/qemu_coverage + - ./fuzzers/qemu_launcher + + runs-on: [ self-hosted, qemu ] + container: registry.gitlab.com/qemu-project/qemu/qemu/ubuntu2204:latest + steps: + - uses: actions/checkout@v3 + - uses: ./.github/workflows/qemu-fuzzer-tester-prepare + - uses: ./.github/workflows/fuzzer-tester-prepare + - name: Symlink Headers + if: runner.os == 'Linux' + shell: bash + run: sudo ln -s /usr/include/asm-generic /usr/include/asm + - name: Build and run example QEMU fuzzers (Linux) + if: runner.os == 'Linux' + shell: bash + run: RUN_ON_CI=1 LLVM_CONFIG=llvm-config ./scripts/test_fuzzer.sh ${{ matrix.fuzzer }} nostd-build: runs-on: ubuntu-latest @@ -409,8 +434,8 @@ jobs: windows-frida-libpng: runs-on: windows-latest needs: - - common - steps: + - common + steps: - uses: actions/checkout@v3 - uses: ./.github/workflows/windows-tester-prepare - name: Build fuzzers/frida_libpng @@ -439,7 +464,7 @@ jobs: windows-tinyinst-simple: runs-on: windows-latest needs: - - common + - common steps: - uses: actions/checkout@v3 - uses: ./.github/workflows/windows-tester-prepare @@ -451,7 +476,7 @@ jobs: windows-clippy: runs-on: windows-latest needs: - - common + - common steps: - uses: actions-rs/toolchain@v1 with: diff --git a/.github/workflows/fuzzer-tester-prepare/action.yml b/.github/workflows/fuzzer-tester-prepare/action.yml index 8f504e5956..c161a74607 100644 --- a/.github/workflows/fuzzer-tester-prepare/action.yml +++ b/.github/workflows/fuzzer-tester-prepare/action.yml @@ -13,6 +13,9 @@ runs: with: profile: minimal toolchain: stable + - name: Add stable rustfmt and clippy + shell: bash + run: rustup toolchain install stable --component rustfmt --component clippy --allow-downgrade - name: Add nightly rustfmt and clippy shell: bash run: rustup toolchain install nightly --component rustfmt --component clippy --allow-downgrade @@ -25,7 +28,7 @@ runs: - name: Remove obsolete llvm (Linux) if: runner.os == 'Linux' shell: bash - run: sudo apt purge llvm* clang* + run: sudo apt purge -y llvm* clang* - name: Install LLVM and Clang uses: KyleMayes/install-llvm-action@v1 with: @@ -33,7 +36,7 @@ runs: version: 17 - name: Install deps shell: bash - run: sudo apt update && sudo apt install nasm ninja-build gcc-arm-linux-gnueabi g++-arm-linux-gnueabi gcc-aarch64-linux-gnu g++-aarch64-linux-gnu gcc-mipsel-linux-gnu g++-mipsel-linux-gnu gcc-powerpc-linux-gnu g++-powerpc-linux-gnu libc6-dev-i386-cross libc6-dev libc6-dev-i386 lib32gcc-11-dev lib32stdc++-11-dev libgtk-3-dev pax-utils libz3-dev + run: sudo apt update && sudo apt install -y nasm ninja-build gcc-arm-linux-gnueabi g++-arm-linux-gnueabi gcc-aarch64-linux-gnu g++-aarch64-linux-gnu gcc-mipsel-linux-gnu g++-mipsel-linux-gnu gcc-powerpc-linux-gnu g++-powerpc-linux-gnu libc6-dev-i386-cross libc6-dev libc6-dev-i386 lib32gcc-11-dev lib32stdc++-11-dev libgtk-3-dev pax-utils libz3-dev - name: pip install shell: bash run: python3 -m pip install msgpack jinja2 find_libpython diff --git a/.github/workflows/qemu-fuzzer-tester-prepare/action.yml b/.github/workflows/qemu-fuzzer-tester-prepare/action.yml new file mode 100644 index 0000000000..337c68d1ac --- /dev/null +++ b/.github/workflows/qemu-fuzzer-tester-prepare/action.yml @@ -0,0 +1,8 @@ +name: Setup QEMU Fuzzers environment +description: Sets up the QEMU fuzzers environment +runs: + using: composite + steps: + - name: Install sudo + shell: bash + run: apt update && apt install -y sudo wget qemu-utils libsqlite3-dev gcc-arm-none-eabi \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index c1839d6735..128b722afa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -140,7 +140,7 @@ RUN cargo build && cargo build --release # Copy fuzzers over COPY fuzzers fuzzers -# RUN ./scripts/test_all_fuzzers.sh --no-fmt +# RUN ./scripts/test_fuzzer.sh --no-fmt ENTRYPOINT [ "/bin/bash", "-c" ] CMD ["/bin/bash"] diff --git a/fuzzers/frida_gdiplus/src/fuzzer.rs b/fuzzers/frida_gdiplus/src/fuzzer.rs index 4ec52e3887..7bff6cd18e 100644 --- a/fuzzers/frida_gdiplus/src/fuzzer.rs +++ b/fuzzers/frida_gdiplus/src/fuzzer.rs @@ -4,7 +4,7 @@ //! is platform independent. Hence, this file contains code for other platforms //! but it's only meaningful for Windows because of the `gdiplus` target. If you //! going to make it compilable only for Windows, don't forget to modify the -//! `scripts/test_all_fuzzers.sh` to opt-out this fuzzer from that test. +//! `scripts/test_fuzzer.sh` to opt-out this fuzzer from that test. use mimalloc::MiMalloc; #[global_allocator] diff --git a/fuzzers/qemu_cmin/Makefile.toml b/fuzzers/qemu_cmin/Makefile.toml index a28fafea8a..c43f51af6b 100644 --- a/fuzzers/qemu_cmin/Makefile.toml +++ b/fuzzers/qemu_cmin/Makefile.toml @@ -8,6 +8,7 @@ TARGET_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/x86_64" LIBPNG_ARCH = "x86_64" LIBPNG_OPTIMIZATIONS = "yes" FEATURE = "x86_64" +LIBAFL_QEMU_CLONE_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/qemu-libafl-bridge" #LIBAFL_DEBUG_OUTPUT = "1" #CUSTOM_QEMU_DIR= "~/qemu-libafl-bridge" @@ -19,6 +20,7 @@ TARGET_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/arm" LIBPNG_ARCH = "arm" LIBPNG_OPTIMIZATIONS = "yes" FEATURE = "arm" +LIBAFL_QEMU_CLONE_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/qemu-libafl-bridge" [env.aarch64] CROSS_CC = "aarch64-linux-gnu-gcc" @@ -28,6 +30,7 @@ TARGET_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/aarch64" LIBPNG_ARCH = "aarch64" LIBPNG_OPTIMIZATIONS = "yes" FEATURE = "aarch64" +LIBAFL_QEMU_CLONE_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/qemu-libafl-bridge" [env.x86_64] CROSS_CC = "x86_64-linux-gnu-gcc" @@ -37,6 +40,7 @@ TARGET_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/x86_64" LIBPNG_ARCH = "x86_64" LIBPNG_OPTIMIZATIONS = "yes" FEATURE = "x86_64" +LIBAFL_QEMU_CLONE_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/qemu-libafl-bridge" [env.i386] CROSS_CC = "x86_64-linux-gnu-gcc" @@ -46,6 +50,7 @@ TARGET_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/i386" LIBPNG_ARCH = "i386" LIBPNG_OPTIMIZATIONS = "yes" FEATURE = "i386" +LIBAFL_QEMU_CLONE_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/qemu-libafl-bridge" [env.mips] CROSS_CC = "mipsel-linux-gnu-gcc" @@ -55,6 +60,7 @@ TARGET_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/mips" LIBPNG_ARCH = "mips" LIBPNG_OPTIMIZATIONS = "yes" FEATURE = "mips" +LIBAFL_QEMU_CLONE_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/qemu-libafl-bridge" [env.ppc] CROSS_CC = "powerpc-linux-gnu-gcc" @@ -64,6 +70,7 @@ TARGET_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/ppc" LIBPNG_ARCH = "ppc" LIBPNG_OPTIMIZATIONS = "no" FEATURE = "ppc" +LIBAFL_QEMU_CLONE_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/qemu-libafl-bridge" [tasks.unsupported] script_runner="@shell" @@ -242,6 +249,20 @@ mac_alias = "unsupported" windows_alias = "unsupported" [tasks.test_unix] +dependencies = [ "lightweight" ] +# Tidy up after we've run our tests so we don't hog all the disk space +command = "cargo" +args = [ + "make", + "clean", +] + +[tasks.test_full] +linux_alias = "test_unix_full" +mac_alias = "unsupported" +windows_alias = "unsupported" + +[tasks.test_unix_full] dependencies = [ "all" ] # Tidy up after we've run our tests so we don't hog all the disk space command = "cargo" @@ -321,3 +342,9 @@ dependencies = [ "mips", "ppc" ] + +[tasks.lightweight] +dependencies = [ + "arm", + "x86_64", +] diff --git a/fuzzers/qemu_coverage/Makefile.toml b/fuzzers/qemu_coverage/Makefile.toml index d8972bc283..3ec4818066 100644 --- a/fuzzers/qemu_coverage/Makefile.toml +++ b/fuzzers/qemu_coverage/Makefile.toml @@ -8,6 +8,7 @@ TARGET_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/x86_64" LIBPNG_ARCH = "x86_64" LIBPNG_OPTIMIZATIONS = "yes" FEATURE = "x86_64" +LIBAFL_QEMU_CLONE_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/qemu-libafl-bridge" #LIBAFL_DEBUG_OUTPUT = "1" #CUSTOM_QEMU_DIR= "~/qemu-libafl-bridge" @@ -19,6 +20,7 @@ TARGET_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/arm" LIBPNG_ARCH = "arm" LIBPNG_OPTIMIZATIONS = "yes" FEATURE = "arm" +LIBAFL_QEMU_CLONE_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/qemu-libafl-bridge" [env.aarch64] CROSS_CC = "aarch64-linux-gnu-gcc" @@ -28,6 +30,7 @@ TARGET_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/aarch64" LIBPNG_ARCH = "aarch64" LIBPNG_OPTIMIZATIONS = "yes" FEATURE = "aarch64" +LIBAFL_QEMU_CLONE_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/qemu-libafl-bridge" [env.x86_64] CROSS_CC = "x86_64-linux-gnu-gcc" @@ -37,6 +40,7 @@ TARGET_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/x86_64" LIBPNG_ARCH = "x86_64" LIBPNG_OPTIMIZATIONS = "yes" FEATURE = "x86_64" +LIBAFL_QEMU_CLONE_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/qemu-libafl-bridge" [env.i386] CROSS_CC = "x86_64-linux-gnu-gcc" @@ -46,6 +50,7 @@ TARGET_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/i386" LIBPNG_ARCH = "i386" LIBPNG_OPTIMIZATIONS = "yes" FEATURE = "i386" +LIBAFL_QEMU_CLONE_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/qemu-libafl-bridge" [env.mips] CROSS_CC = "mipsel-linux-gnu-gcc" @@ -55,6 +60,7 @@ TARGET_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/mips" LIBPNG_ARCH = "mips" LIBPNG_OPTIMIZATIONS = "yes" FEATURE = "mips" +LIBAFL_QEMU_CLONE_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/qemu-libafl-bridge" [env.ppc] CROSS_CC = "powerpc-linux-gnu-gcc" @@ -64,6 +70,7 @@ TARGET_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/ppc" LIBPNG_ARCH = "ppc" LIBPNG_OPTIMIZATIONS = "no" FEATURE = "ppc" +LIBAFL_QEMU_CLONE_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/qemu-libafl-bridge" [tasks.unsupported] script_runner="@shell" @@ -241,6 +248,20 @@ mac_alias = "unsupported" windows_alias = "unsupported" [tasks.test_unix] +dependencies = [ "lightweight" ] +# Tidy up after we've run our tests so we don't hog all the disk space +command = "cargo" +args = [ + "make", + "clean", +] + +[tasks.test_full] +linux_alias = "test_unix_full" +mac_alias = "unsupported" +windows_alias = "unsupported" + +[tasks.test_unix_full] dependencies = [ "all" ] # Tidy up after we've run our tests so we don't hog all the disk space command = "cargo" @@ -320,3 +341,9 @@ dependencies = [ "mips", "ppc" ] + +[tasks.lightweight] +dependencies = [ + "arm", + "x86_64", +] diff --git a/fuzzers/qemu_coverage/src/fuzzer.rs b/fuzzers/qemu_coverage/src/fuzzer.rs index 698fc59883..7379ff14a7 100644 --- a/fuzzers/qemu_coverage/src/fuzzer.rs +++ b/fuzzers/qemu_coverage/src/fuzzer.rs @@ -137,7 +137,7 @@ pub fn fuzz() { "Mapping: 0x{:016x}-0x{:016x}, {}", m.start(), m.end(), - m.path().unwrap_or("") + m.path().unwrap_or(&"".to_string()) ); } @@ -255,7 +255,7 @@ pub fn fuzz() { tuple_list!(QemuDrCovHelper::new( QemuInstrumentationAddressRangeFilter::None, rangemap, - PathBuf::from(coverage), + coverage, false, )), ); diff --git a/fuzzers/qemu_launcher/README.md b/fuzzers/qemu_launcher/README.md index 10111d6471..bc9c9b767d 100644 --- a/fuzzers/qemu_launcher/README.md +++ b/fuzzers/qemu_launcher/README.md @@ -26,7 +26,8 @@ sudo apt install \ gcc-mipsel-linux-gnu \ g++-mipsel-linux-gnu \ gcc-powerpc-linux-gnu \ - g++-powerpc-linux-gnu + g++-powerpc-linux-gnu \ + libsqlite3-dev ``` ## Run diff --git a/fuzzers/qemu_systemmode/Makefile.toml b/fuzzers/qemu_systemmode/Makefile.toml index fe261e1507..2afe843b23 100644 --- a/fuzzers/qemu_systemmode/Makefile.toml +++ b/fuzzers/qemu_systemmode/Makefile.toml @@ -1,6 +1,31 @@ +env_scripts = [ +''' +#!@duckscript +profile = get_env PROFILE + +if eq ${profile} "dev" + set_env PROFILE_DIR debug +else + set_env PROFILE_DIR ${profile} +end +''', +''' +#!@duckscript +runs_on_ci = get_env RUN_ON_CI + +if ${runs_on_ci} + cargo_target_dir = get_env CARGO_MAKE_CRATE_TARGET_DIRECTORY + set_env TARGET_DIR ${cargo_target_dir} + set_env KERNEL ${cargo_target_dir}/example.elf +end +''' +] + [env] -PROFILE = { value = "release", condition = {env_not_set = ["PROFILE"]} } +PROFILE = { value = "release", condition = { env_not_set = ["PROFILE"] } } TARGET_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/${FEATURE}" +LIBAFL_QEMU_CLONE_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/qemu-libafl-bridge" +KERNEL = "${TARGET_DIR}/example.elf" [tasks.target_dir] condition = { files_not_exist = [ "${TARGET_DIR}" ] } @@ -18,7 +43,7 @@ qemu-img create -f qcow2 ${TARGET_DIR}/dummy.qcow2 32M ''' [tasks.target] -dependencies = ["target_dir", "build_fuzzer"] +dependencies = ["target_dir"] condition = { env_set = [ "TARGET_DEFINE" ] } command = "arm-none-eabi-gcc" args = [ @@ -31,7 +56,7 @@ args = [ "${CARGO_MAKE_WORKING_DIRECTORY}/example/main.c", "${CARGO_MAKE_WORKING_DIRECTORY}/example/startup.c", "-D", "${TARGET_DEFINE}", - "-I", "${TARGET_DIR}/${PROFILE}/include", + "-I", "${TARGET_DIR}/${PROFILE_DIR}/include", "-o", "${TARGET_DIR}/example.elf", ] @@ -49,8 +74,7 @@ args = [ dependencies = ["image"] [tasks.run_fuzzer] -env = { "KERNEL" = "${TARGET_DIR}/example.elf" } -command = "${TARGET_DIR}/${PROFILE}/qemu_systemmode" +command = "${TARGET_DIR}/${PROFILE_DIR}/qemu_systemmode" args = [ "-icount", "shift=auto,align=off,sleep=off", "-machine", "mps2-an385", @@ -62,7 +86,7 @@ args = [ "-drive", "if=none,format=qcow2,file=${TARGET_DIR}/dummy.qcow2", "-S", ] -dependencies = ["build_fuzzer", "target"] +dependencies = ["target"] [tasks.test_fuzzer] condition = { env_set = [ "FEATURE" ] } @@ -74,10 +98,10 @@ cargo make build_$FEATURE timeout 15s cargo make ${FEATURE} | tee $TMP_DIR/fuzz.log 2>&1 || true if [ -z "$(grep 'Objective' $TMP_DIR/fuzz.log)" ]; then - echo "Fuzzer did not find the objective in $TMP_DIR/fuzz.log" + echo "qemu_systemmode ${FEATURE}: Fuzzer did not find the objective in $TMP_DIR/fuzz.log" exit 1 else - echo "Objective found." + echo "qemu_systemmode ${FEATURE}: Objective found." fi ''' @@ -161,8 +185,7 @@ args = [ [tasks.test] clear = true -run_task = { name = ["build"] } -# run_task = { name = ["test_classic", "test_breakpoint", "test_sync_exit"] } +run_task = { name = ["test_classic", "test_breakpoint", "test_sync_exit"] } [tasks.build] clear = true diff --git a/fuzzers/qemu_systemmode/README.md b/fuzzers/qemu_systemmode/README.md index cbc9266d53..12ad9af951 100644 --- a/fuzzers/qemu_systemmode/README.md +++ b/fuzzers/qemu_systemmode/README.md @@ -8,6 +8,22 @@ It comes in three flavours (can be set through features): -`breakpoint`: Interaction with QEMU using the command system, leveraging breakpoints. -`sync_exit`: Interaction with QEMU using the command system, leveraging sync exits. +## Prerequisite + +You will need to have `qemu-img` and `arm-none-eabi-gcc` installed. + +On Ubuntu and Debian, you will need to run +```bash +sudo apt update +sudo apt -y install qemu-utils gcc-arm-none-eabi +``` + +## Build + +```bash +cargo make build +``` + ## Run ```bash @@ -25,5 +41,5 @@ With feature being `classic`, `breakpoint` or `sync_exit`. This will build the desired fuzzer (src/fuzzer_.rs) and a small example binary based on FreeRTOS, which can run under a qemu emulation target. Since the instrumentation is based on snapshots, QEMU needs a virtual drive (even if it is unused...). Thus, the makefile creates a dummy QCOW2 image `dummy.qcow2` (can be found in the `target directory`). -Currently the ``KERNEL`` variable is needed because the fuzzer does not parse QEMUs arguments to find the binary. +Currently, the ``KERNEL`` variable is needed because the fuzzer does not parse QEMUs arguments to find the binary. It is automatically set in the build script. \ No newline at end of file diff --git a/fuzzers/qemu_systemmode/example/main.c b/fuzzers/qemu_systemmode/example/main.c index e1804d3de8..40944fab37 100644 --- a/fuzzers/qemu_systemmode/example/main.c +++ b/fuzzers/qemu_systemmode/example/main.c @@ -8,7 +8,7 @@ int __attribute__((noinline)) BREAKPOINT() { int LLVMFuzzerTestOneInput(unsigned int *Data, unsigned int Size) { #ifdef TARGET_SYNC_EXIT - LIBAFL_EXIT_START_PHYS((unsigned int)Data, Size); + LIBAFL_QEMU_START_PHYS((unsigned int)Data, Size); #endif if (Data[3] == 0) { while (1) {} @@ -27,7 +27,7 @@ int LLVMFuzzerTestOneInput(unsigned int *Data, unsigned int Size) { } } #ifdef TARGET_SYNC_EXIT - LIBAFL_EXIT_END(LIBAFL_EXIT_END_OK); + LIBAFL_QEMU_END(LIBAFL_QEMU_END_OK); #endif return BREAKPOINT(); } diff --git a/libafl/src/observers/concolic/serialization_format.rs b/libafl/src/observers/concolic/serialization_format.rs index 7f32171fc5..1080f0f1bc 100644 --- a/libafl/src/observers/concolic/serialization_format.rs +++ b/libafl/src/observers/concolic/serialization_format.rs @@ -41,8 +41,6 @@ //! //! ... making for a total of 5 bytes. -#![cfg(feature = "std")] - use std::{ fmt::{self, Debug, Formatter}, io::{self, Cursor, Read, Seek, SeekFrom, Write}, diff --git a/libafl_bolts/src/os/unix_signals.rs b/libafl_bolts/src/os/unix_signals.rs index 81893fc13e..b01e0638f1 100644 --- a/libafl_bolts/src/os/unix_signals.rs +++ b/libafl_bolts/src/os/unix_signals.rs @@ -263,7 +263,7 @@ use crate::Error; extern "C" { /// The `libc` `getcontext` - /// For some reason, it's not available on MacOS. + /// For some reason, it's not available on `MacOS`. /// fn getcontext(ucp: *mut ucontext_t) -> c_int; } diff --git a/libafl_cc/src/lib.rs b/libafl_cc/src/lib.rs index d81e038721..5651f12d6e 100644 --- a/libafl_cc/src/lib.rs +++ b/libafl_cc/src/lib.rs @@ -34,7 +34,6 @@ unused_import_braces, unused_qualifications, unused_must_use, - missing_docs, //unused_results ))] #![cfg_attr( diff --git a/libafl_derive/src/lib.rs b/libafl_derive/src/lib.rs index fa91639283..485592a129 100644 --- a/libafl_derive/src/lib.rs +++ b/libafl_derive/src/lib.rs @@ -35,7 +35,6 @@ unused_import_braces, unused_qualifications, unused_must_use, - missing_docs, //unused_results ))] #![cfg_attr( diff --git a/libafl_frida/src/lib.rs b/libafl_frida/src/lib.rs index 738e0a56d3..33ed14c7d6 100644 --- a/libafl_frida/src/lib.rs +++ b/libafl_frida/src/lib.rs @@ -41,7 +41,6 @@ Additional documentation is available in [the `LibAFL` book](https://aflplus.plu unused_import_braces, unused_qualifications, unused_must_use, - missing_docs, //unused_results ))] #![cfg_attr( diff --git a/libafl_qemu/libafl_qemu_build/src/build.rs b/libafl_qemu/libafl_qemu_build/src/build.rs index 378eea1915..45412390c8 100644 --- a/libafl_qemu/libafl_qemu_build/src/build.rs +++ b/libafl_qemu/libafl_qemu_build/src/build.rs @@ -266,10 +266,13 @@ pub fn build( } let libafl_qemu_dir = env::var_os("LIBAFL_QEMU_DIR").map(|x| x.to_string_lossy().to_string()); + let libafl_qemu_clone_dir = + env::var_os("LIBAFL_QEMU_CLONE_DIR").map(|x| x.to_string_lossy().to_string()); let libafl_qemu_force_configure = env::var("LIBAFL_QEMU_FORCE_CONFIGURE").is_ok(); let libafl_qemu_no_build = env::var("LIBAFL_QEMU_NO_BUILD").is_ok(); println!("cargo:rerun-if-env-changed=LIBAFL_QEMU_DIR"); + println!("cargo:rerun-if-env-changed=LIBAFL_QEMU_CLONE_DIR"); println!("cargo:rerun-if-env-changed=LIBAFL_QEMU_FORCE_CONFIGURE"); println!("cargo:rerun-if-env-changed=LIBAFL_QEMU_NO_BUILD"); @@ -286,10 +289,18 @@ pub fn build( let cc_compiler = cc::Build::new().cpp(false).get_compiler(); let cpp_compiler = cc::Build::new().cpp(true).get_compiler(); - let qemu_path = if let Some(qemu_dir) = libafl_qemu_dir.as_ref() { + let libafl_qemu_dir = if let Some(qemu_dir) = libafl_qemu_dir.as_ref() { + if libafl_qemu_clone_dir.is_some() { + println!("cargo:warning=LIBAFL_QEMU_DIR and LIBAFL_QEMU_CLONE_DIR are both set. LIBAFL_QEMU_DIR will be considered in priority"); + } + Path::new(&qemu_dir).to_path_buf() } else { - let qemu_path = target_dir.join(QEMU_DIRNAME); + let qemu_path = if let Some(clone_dir) = &libafl_qemu_clone_dir { + PathBuf::from(clone_dir) + } else { + target_dir.join(QEMU_DIRNAME) + }; let qemu_rev = target_dir.join("QEMU_REVISION"); if qemu_rev.exists() @@ -339,8 +350,8 @@ pub fn build( qemu_path }; - let qemu_build_dir = qemu_path.join("build"); - let config_signature_path = qemu_build_dir.join("libafl_config"); + let libafl_qemu_build_dir = libafl_qemu_dir.join("build"); + let config_signature_path = libafl_qemu_build_dir.join("libafl_config"); let target_suffix = if is_usermode { "linux-user".to_string() @@ -350,12 +361,12 @@ pub fn build( let (output_lib, output_lib_link) = if is_usermode { ( - qemu_build_dir.join(format!("libqemu-{cpu_target}.so")), + libafl_qemu_build_dir.join(format!("libqemu-{cpu_target}.so")), format!("qemu-{cpu_target}"), ) } else { ( - qemu_build_dir.join(format!("libqemu-system-{cpu_target}.so")), + libafl_qemu_build_dir.join(format!("libqemu-system-{cpu_target}.so")), format!("qemu-system-{cpu_target}"), ) }; @@ -365,8 +376,8 @@ pub fn build( let mut config_cmd = configure_qemu( &cc_compiler, &cpp_compiler, - &qemu_path, - &qemu_build_dir, + &libafl_qemu_dir, + &libafl_qemu_build_dir, is_usermode, &cpu_target, &target_suffix, @@ -405,7 +416,7 @@ pub fn build( // Always build by default, make will detect if it is necessary to rebuild qemu if !libafl_qemu_no_build { - let mut build_cmd = build_qemu(&cc_compiler, &cpp_compiler, &qemu_build_dir, jobs); + let mut build_cmd = build_qemu(&cc_compiler, &cpp_compiler, &libafl_qemu_build_dir, jobs); assert!( build_cmd.status().expect("Invoking Make Failed").success(), @@ -439,13 +450,16 @@ pub fn build( */ if cfg!(feature = "shared") { - let qemu_build_dir_str = qemu_build_dir.to_str().expect("Could not convert to str"); + let qemu_build_dir_str = libafl_qemu_build_dir + .to_str() + .expect("Could not convert to str"); println!("cargo:rustc-link-search=native={qemu_build_dir_str}"); println!("cargo:rustc-link-lib=dylib={output_lib_link}"); cargo_add_rpath(qemu_build_dir_str); } else { - let compile_commands_string = &fs::read_to_string(qemu_build_dir.join("linkinfo.json")) - .expect("Failed to read linkinfo.json"); + let compile_commands_string = + &fs::read_to_string(libafl_qemu_build_dir.join("linkinfo.json")) + .expect("Failed to read linkinfo.json"); let linkinfo = json::parse(compile_commands_string).expect("Failed to parse linkinfo.json"); @@ -460,7 +474,7 @@ pub fn build( let mut link_command = cpp_compiler.to_command(); link_command - .current_dir(&qemu_build_dir) + .current_dir(&libafl_qemu_build_dir) .arg("-o") .arg("libqemu-partially-linked.o") .arg("-r") @@ -471,10 +485,11 @@ pub fn build( let output = link_command.output().expect("Partial linked failure"); if !output.status.success() { - fs::write(qemu_build_dir.join("link.command"), link_str).expect("Link command failed."); - fs::write(qemu_build_dir.join("link.stdout"), &output.stdout) + fs::write(libafl_qemu_build_dir.join("link.command"), link_str) + .expect("Link command failed."); + fs::write(libafl_qemu_build_dir.join("link.stdout"), &output.stdout) .expect("Link stdout failed."); - fs::write(qemu_build_dir.join("link.stderr"), &output.stderr) + fs::write(libafl_qemu_build_dir.join("link.stderr"), &output.stderr) .expect("Link stderr failed."); panic!("Linking failed."); } @@ -567,7 +582,7 @@ pub fn build( .current_dir(out_dir_path) .arg("crs") .arg("libqemu-partially-linked.a") - .arg(qemu_build_dir.join("libqemu-partially-linked.o")) + .arg(libafl_qemu_build_dir.join("libqemu-partially-linked.o")) .status() .expect("Ar creation"); @@ -595,7 +610,7 @@ pub fn build( .to_string() .replace( "$ORIGIN", - qemu_build_dir + libafl_qemu_build_dir .as_os_str() .to_str() .expect("Could not convert OsStr to str"), @@ -623,7 +638,7 @@ pub fn build( //} fs::create_dir_all(target_dir.join("pc-bios")).unwrap(); - for path in fs::read_dir(qemu_build_dir.join("pc-bios")).unwrap() { + for path in fs::read_dir(libafl_qemu_build_dir.join("pc-bios")).unwrap() { let path = path.unwrap().path(); if path.is_file() { if let Some(name) = path.file_name() { @@ -635,7 +650,7 @@ pub fn build( } BuildResult { - qemu_path, - build_dir: qemu_build_dir, + qemu_path: libafl_qemu_dir, + build_dir: libafl_qemu_build_dir, } } diff --git a/libafl_qemu/src/hooks.rs b/libafl_qemu/src/hooks.rs index 9b7e336dd7..604725a625 100644 --- a/libafl_qemu/src/hooks.rs +++ b/libafl_qemu/src/hooks.rs @@ -117,7 +117,7 @@ macro_rules! create_wrapper { { unsafe { let hooks = get_qemu_hooks::(); - let func: fn(&mut QemuHooks, Option<&mut S>, $($param_type),*) = transmute(hook as *mut c_void); + let func: fn(&mut QemuHooks, Option<&mut S>, $($param_type),*) = transmute(ptr::from_mut::(hook)); func(hooks, inprocess_get_state::(), $($param),*); } } @@ -144,7 +144,7 @@ macro_rules! create_wrapper { { unsafe { let hooks = get_qemu_hooks::(); - let func: fn(&mut QemuHooks, Option<&mut S>, $($param_type),*) -> $ret_type= transmute(hook as *mut c_void); + let func: fn(&mut QemuHooks, Option<&mut S>, $($param_type),*) -> $ret_type= transmute(ptr::from_mut::(hook)); func(hooks, inprocess_get_state::(), $($param),*) } } diff --git a/libafl_sugar/src/lib.rs b/libafl_sugar/src/lib.rs index fb41e4a5aa..9de7dac2ce 100644 --- a/libafl_sugar/src/lib.rs +++ b/libafl_sugar/src/lib.rs @@ -34,7 +34,6 @@ unused_import_braces, unused_qualifications, unused_must_use, - missing_docs, //unused_results ))] #![cfg_attr( diff --git a/libafl_targets/src/lib.rs b/libafl_targets/src/lib.rs index b2fe9e294a..553001a7af 100644 --- a/libafl_targets/src/lib.rs +++ b/libafl_targets/src/lib.rs @@ -35,7 +35,6 @@ unused_import_braces, unused_qualifications, unused_must_use, - missing_docs, //unused_results ))] #![cfg_attr( diff --git a/libafl_tinyinst/src/lib.rs b/libafl_tinyinst/src/lib.rs index e68c4607d0..a8b95c4387 100644 --- a/libafl_tinyinst/src/lib.rs +++ b/libafl_tinyinst/src/lib.rs @@ -39,7 +39,6 @@ The tinyinst module for `LibAFL`. unused_import_braces, unused_qualifications, unused_must_use, - missing_docs, //unused_results ))] #![cfg_attr( diff --git a/scripts/test_all_fuzzers.sh b/scripts/test_fuzzer.sh similarity index 93% rename from scripts/test_all_fuzzers.sh rename to scripts/test_fuzzer.sh index 94ecf2cfc5..e293948b79 100755 --- a/scripts/test_all_fuzzers.sh +++ b/scripts/test_fuzzer.sh @@ -6,7 +6,9 @@ cd "$SCRIPT_DIR/.." || exit 1 if [[ -z "${RUN_ON_CI}" ]]; then - fuzzer_to_test="$1" + fuzzers=$(find ./fuzzers -mindepth 1 -maxdepth 1 -type d) + backtrace_fuzzers=$(find ./fuzzers/backtrace_baby_fuzzers -mindepth 1 -maxdepth 1 -type d) + fuzzer_to_test="$fuzzers $backtrace_fuzzers" else fuzzer_to_test="$1" export PROFILE=dev