diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ffb0e908..21fddfbf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: runs-on: "${{ matrix.os }}" strategy: matrix: - os: [ubuntu-24.04, ubuntu-22.04] + os: [ubuntu-24.04, ubuntu-22.04, ubuntu-24.04-arm] env: AFL_SKIP_CPUFREQ: 1 AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: 1 diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml index 5c44f714..4a4fa028 100644 --- a/.github/workflows/container.yml +++ b/.github/workflows/container.yml @@ -35,20 +35,41 @@ jobs: apt-get install -y libcmocka-dev && make -i tests " + build-and-test-arm64: + name: Test arm64 image + runs-on: ubuntu-24.04-arm + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Build arm64 + uses: docker/build-push-action@v6 + with: + context: . + tags: aflplusplus:test-arm64 + load: true + cache-to: type=gha,mode=max + build-args: | + TEST_BUILD=1 + - name: Test arm64 + run: > + docker run --rm aflplusplus:test-arm64 bash -c " + apt-get update && + apt-get install -y libcmocka-dev && + make -i tests + " push: name: Push amd64 and arm64 images runs-on: ubuntu-latest needs: - build-and-test-amd64 + - build-and-test-arm64 if: ${{ github.event_name == 'push' && github.repository == 'AFLplusplus/AFLplusplus' }} steps: - name: Checkout uses: actions/checkout@v3 - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - with: - platforms: arm64 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Login to docker.io diff --git a/Dockerfile b/Dockerfile index 99998a61..ece1239c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -61,6 +61,7 @@ RUN apt-get update && \ RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCC_VERSION} 0 && \ update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${GCC_VERSION} 0 && \ + update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++-${GCC_VERSION} 0 && \ update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${LLVM_VERSION} 0 && \ update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-${LLVM_VERSION} 0 diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm index df3994a0..653d3b68 100644 --- a/GNUmakefile.llvm +++ b/GNUmakefile.llvm @@ -237,20 +237,21 @@ ifeq "$(LLVM_LTO)" "1" ifeq "$(AFL_REAL_LD)" "" ifneq "$(shell readlink $(LLVM_BINDIR)/ld.lld 2>&1)" "" AFL_REAL_LD = $(LLVM_BINDIR)/ld.lld - else ifneq "$(shell command -v ld.lld 2>/dev/null)" "" - AFL_REAL_LD = $(shell command -v ld.lld) - TMP_LDLDD_VERSION = $(shell $(AFL_REAL_LD) --version | awk '{ print $$2 }') - ifeq "$(LLVMVER)" "$(TMP_LDLDD_VERSION)" - $(warning ld.lld found in a weird location ($(AFL_REAL_LD)), but its the same version as LLVM so we will allow it) + else + ifneq "$(shell command -v ld.lld 2>/dev/null)" "" + AFL_REAL_LD = $(shell command -v ld.lld) + TMP_LDLDD_VERSION = $(shell $(AFL_REAL_LD) --version | awk '{ print $$2 }') + ifeq "$(LLVMVER)" "$(TMP_LDLDD_VERSION)" + $(warning ld.lld found in a weird location ($(AFL_REAL_LD)), but its the same version as LLVM so we will allow it) + else + $(warning ld.lld found in a weird location ($(AFL_REAL_LD)) and its of a different version than LLMV ($(TMP_LDLDD_VERSION) vs. $(LLVMVER)) - cannot enable LTO mode) + AFL_REAL_LD= + LLVM_LTO = 0 + endif else - $(warning ld.lld found in a weird location ($(AFL_REAL_LD)) and its of a different version than LLMV ($(TMP_LDLDD_VERSION) vs. $(LLVMVER)) - cannot enable LTO mode) - AFL_REAL_LD= + $(warning ld.lld not found, cannot enable LTO mode) LLVM_LTO = 0 endif - undefine TMP_LDLDD_VERSION - else - $(warning ld.lld not found, cannot enable LTO mode) - LLVM_LTO = 0 endif endif else @@ -272,12 +273,6 @@ ifeq "$(LLVM_LTO)" "1" endif endif -ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fdebug-prefix-map=$(CURDIR)=llvm_mode -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" - AFL_CLANG_DEBUG_PREFIX = -fdebug-prefix-map="$(CURDIR)=llvm_mode" -else - AFL_CLANG_DEBUG_PREFIX = -endif - IS_IOS := $(findstring ios, $(shell $(CC) --version 2>/dev/null)) CFLAGS ?= -O3 -funroll-loops -fPIC @@ -290,7 +285,7 @@ CFLAGS_SAFE := -Wall -g -Wno-cast-qual -Wno-variadic-macros -Wno-pointer-sig -DAFL_CLANG_FLTO=\"$(AFL_CLANG_FLTO)\" -DAFL_REAL_LD=\"$(AFL_REAL_LD)\" \ -DAFL_CLANG_LDPATH=\"$(AFL_CLANG_LDPATH)\" -DAFL_CLANG_FUSELD=\"$(AFL_CLANG_FUSELD)\" \ -DCLANG_BIN=\"$(CLANG_BIN)\" -DCLANGPP_BIN=\"$(CLANGPP_BIN)\" -DUSE_BINDIR=$(USE_BINDIR) \ - -Wno-unused-function $(AFL_CLANG_DEBUG_PREFIX) + -Wno-unused-function ifndef LLVM_DEBUG CFLAGS_SAFE += -Wno-deprecated endif diff --git a/docs/env_variables.md b/docs/env_variables.md index 727feb16..ed44c256 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -107,6 +107,7 @@ fairly broad use of environment variables instead: conditions - `AFL_USE_UBSAN=1` - activates the undefined behavior sanitizer - `AFL_UBSAN_VERBOSE=1` - outputs detailed diagnostic information when undefined behavior is detected, instead of simply terminating with "Illegal Instruction" + . `AFL_USE_RTSAN` . activates the realtime sanitizer (realtime violations in deterministic run time constraints). (clang 20 minimum) - Note: both `AFL_CFISAN_VERBOSE=1` and `AFL_UBSAN_VERBOSE=1` are disabled by default as verbose output can significantly slow down fuzzing performance. Use these options only during debugging or when additional crash diagnostics are required diff --git a/docs/features.md b/docs/features.md index b75c103c..e98d60fe 100644 --- a/docs/features.md +++ b/docs/features.md @@ -106,6 +106,7 @@ Among others, the following features and patches have been integrated: * Win32 PE binary-only fuzzing with QEMU and Wine * AFLfast's power schedules by Marcel Böhme: [https://github.com/mboehme/aflfast](https://github.com/mboehme/aflfast) +* The fast deterministic stage by Han Zheng: [https://github.com/hexhive/mendelFuzz-Artifact/](https://github.com/hexhive/mendelFuzz-Artifact/) * The MOpt mutator: [https://github.com/puppet-meteor/MOpt-AFL](https://github.com/puppet-meteor/MOpt-AFL) * LLVM mode Ngram coverage by Adrian Herrera diff --git a/instrumentation/README.lto.md b/instrumentation/README.lto.md index 6c26c7d3..6c2915d8 100644 --- a/instrumentation/README.lto.md +++ b/instrumentation/README.lto.md @@ -79,11 +79,11 @@ LLVM 13 to 19 should be available in all current Linux repositories. That part is easy. Just set `LLVM_CONFIG` to the llvm-config-VERSION and build AFL++, e.g. for -LLVM 15: +LLVM 19: ``` cd ~/AFLplusplus -export LLVM_CONFIG=llvm-config-15 +export LLVM_CONFIG=llvm-config-19 make sudo make install ``` @@ -96,7 +96,7 @@ Also, the instrument file listing (AFL_LLVM_ALLOWLIST/AFL_LLVM_DENYLIST -> [README.instrument_list.md](README.instrument_list.md)) and laf-intel/compcov (AFL_LLVM_LAF_* -> [README.laf-intel.md](README.laf-intel.md)) work. -Example (note that you might need to add the version, e.g. `llvm-ar-15`: +Example (note that you might need to add the version, e.g. `llvm-ar-19`: ``` CC=afl-clang-lto CXX=afl-clang-lto++ RANLIB=llvm-ranlib AR=llvm-ar AS=llvm-as ./configure diff --git a/src/afl-cc.c b/src/afl-cc.c index 56627566..12a361a8 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -181,7 +181,7 @@ typedef struct aflcc_state { have_pic, have_c, shared_linking, partial_linking, non_dash, have_fp, have_flto, have_hidden, have_fortify, have_fcf, have_staticasan, have_rust_asanrt, have_asan, have_msan, have_ubsan, have_lsan, have_tsan, - have_cfisan; + have_cfisan, have_rtsan; // u8 *march_opt; u8 need_aflpplib; @@ -1152,7 +1152,8 @@ void instrument_mode_by_environ(aflcc_state_t *aflcc) { static void instrument_opt_mode_exclude(aflcc_state_t *aflcc) { if ((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX) && - (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER)) { + (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER) && + aflcc->compiler_mode != LTO) { FATAL("you cannot set CTX and CALLER together"); @@ -2031,6 +2032,11 @@ void add_sanitizers(aflcc_state_t *aflcc, char **envp) { } + if (getenv("AFL_USE_RTSAN") && !aflcc->have_rtsan) { + insert_param(aflcc, "-fsanitize=realtime"); + aflcc->have_rtsan = 1; + } + if (getenv("AFL_USE_CFISAN") || aflcc->have_cfisan) { if (aflcc->compiler_mode == GCC_PLUGIN || aflcc->compiler_mode == GCC) { @@ -2971,7 +2977,8 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) { " AFL_USE_MSAN: activate memory sanitizer\n" " AFL_USE_UBSAN: activate undefined behaviour sanitizer\n" " AFL_USE_TSAN: activate thread sanitizer\n" - " AFL_USE_LSAN: activate leak-checker sanitizer\n"); + " AFL_USE_LSAN: activate leak-checker sanitizer\n" + " AFL_USE_RTSAN: activate realtime sanitizer\n"); if (aflcc->have_gcc_plugin) SAYF( diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 877b120e..bd3378f9 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -29,7 +29,7 @@ #include #include "asanfuzz.h" -static u16 count_class_lookup16[65536]; +u16 count_class_lookup16[65536]; /* Destructively simplify trace by eliminating hit count information and replacing it with 0x80 or 0x01 depending on whether the tuple diff --git a/utils/aflpp_driver/aflpp_driver.c b/utils/aflpp_driver/aflpp_driver.c index 9b79ef9b..6cf62dab 100644 --- a/utils/aflpp_driver/aflpp_driver.c +++ b/utils/aflpp_driver/aflpp_driver.c @@ -392,10 +392,6 @@ __attribute__((weak)) int LLVMFuzzerRunDriver( __afl_manual_init(); - // Call LLVMFuzzerTestOneInput here so that coverage caused by initialization - // on the first execution of LLVMFuzzerTestOneInput is ignored. - callback(dummy_input, 4); - __asan_poison_memory_region(__afl_fuzz_ptr, MAX_FILE); size_t prev_length = 0;