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 <tokazerkje@outlook.com>
This commit is contained in:
parent
fe64d10a5c
commit
fef6c8d1b1
37
.github/workflows/build_and_test.yml
vendored
37
.github/workflows/build_and_test.yml
vendored
@ -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:
|
||||
|
@ -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
|
||||
|
8
.github/workflows/qemu-fuzzer-tester-prepare/action.yml
vendored
Normal file
8
.github/workflows/qemu-fuzzer-tester-prepare/action.yml
vendored
Normal file
@ -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
|
@ -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"]
|
||||
|
@ -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]
|
||||
|
@ -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",
|
||||
]
|
||||
|
@ -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",
|
||||
]
|
||||
|
@ -137,7 +137,7 @@ pub fn fuzz() {
|
||||
"Mapping: 0x{:016x}-0x{:016x}, {}",
|
||||
m.start(),
|
||||
m.end(),
|
||||
m.path().unwrap_or("<EMPTY>")
|
||||
m.path().unwrap_or(&"<EMPTY>".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
@ -255,7 +255,7 @@ pub fn fuzz() {
|
||||
tuple_list!(QemuDrCovHelper::new(
|
||||
QemuInstrumentationAddressRangeFilter::None,
|
||||
rangemap,
|
||||
PathBuf::from(coverage),
|
||||
coverage,
|
||||
false,
|
||||
)),
|
||||
);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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_<feature>.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.
|
@ -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();
|
||||
}
|
||||
|
@ -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},
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -34,7 +34,6 @@
|
||||
unused_import_braces,
|
||||
unused_qualifications,
|
||||
unused_must_use,
|
||||
missing_docs,
|
||||
//unused_results
|
||||
))]
|
||||
#![cfg_attr(
|
||||
|
@ -35,7 +35,6 @@
|
||||
unused_import_braces,
|
||||
unused_qualifications,
|
||||
unused_must_use,
|
||||
missing_docs,
|
||||
//unused_results
|
||||
))]
|
||||
#)]
|
||||
#![cfg_attr(
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ macro_rules! create_wrapper {
|
||||
{
|
||||
unsafe {
|
||||
let hooks = get_qemu_hooks::<QT, S>();
|
||||
let func: fn(&mut QemuHooks<QT, S>, Option<&mut S>, $($param_type),*) = transmute(hook as *mut c_void);
|
||||
let func: fn(&mut QemuHooks<QT, S>, Option<&mut S>, $($param_type),*) = transmute(ptr::from_mut::<c_void>(hook));
|
||||
func(hooks, inprocess_get_state::<S>(), $($param),*);
|
||||
}
|
||||
}
|
||||
@ -144,7 +144,7 @@ macro_rules! create_wrapper {
|
||||
{
|
||||
unsafe {
|
||||
let hooks = get_qemu_hooks::<QT, S>();
|
||||
let func: fn(&mut QemuHooks<QT, S>, Option<&mut S>, $($param_type),*) -> $ret_type= transmute(hook as *mut c_void);
|
||||
let func: fn(&mut QemuHooks<QT, S>, Option<&mut S>, $($param_type),*) -> $ret_type= transmute(ptr::from_mut::<c_void>(hook));
|
||||
func(hooks, inprocess_get_state::<S>(), $($param),*)
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,6 @@
|
||||
unused_import_braces,
|
||||
unused_qualifications,
|
||||
unused_must_use,
|
||||
missing_docs,
|
||||
//unused_results
|
||||
))]
|
||||
#![cfg_attr(
|
||||
|
@ -35,7 +35,6 @@
|
||||
unused_import_braces,
|
||||
unused_qualifications,
|
||||
unused_must_use,
|
||||
missing_docs,
|
||||
//unused_results
|
||||
))]
|
||||
#![cfg_attr(
|
||||
|
@ -39,7 +39,6 @@ The tinyinst module for `LibAFL`.
|
||||
unused_import_braces,
|
||||
unused_qualifications,
|
||||
unused_must_use,
|
||||
missing_docs,
|
||||
//unused_results
|
||||
))]
|
||||
#![cfg_attr(
|
||||
|
@ -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
|
Loading…
x
Reference in New Issue
Block a user