diff --git a/fuzzers/libafl_rand_scheduler/builder.Dockerfile b/fuzzers/libafl_rand_scheduler/builder.Dockerfile new file mode 100644 index 000000000..cc348e702 --- /dev/null +++ b/fuzzers/libafl_rand_scheduler/builder.Dockerfile @@ -0,0 +1,61 @@ +# Copyright 2020 Google LLC +# +# 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. + +ARG parent_image +FROM $parent_image + +# Uninstall old Rust & Install the latest one. +RUN if which rustup; then rustup self uninstall -y; fi && \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ + sh /rustup.sh --default-toolchain nightly-2023-09-21 -y && \ + rm /rustup.sh + +# Install dependencies. +RUN apt-get update && \ + apt-get remove -y llvm-10 && \ + apt-get install -y \ + build-essential \ + lsb-release wget software-properties-common gnupg && \ + apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ + libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ + apt-utils apt-transport-https ca-certificates joe curl && \ + wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && ./llvm.sh 17 + +RUN wget https://gist.githubusercontent.com/tokatoka/26f4ba95991c6e33139999976332aa8e/raw/698ac2087d58ce5c7a6ad59adce58dbfdc32bd46/createAliases.sh && chmod u+x ./createAliases.sh && ./createAliases.sh + +# Uninstall old Rust & Install the latest one. +RUN if which rustup; then rustup self uninstall -y; fi && \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ + sh /rustup.sh --default-toolchain nightly-2024-06-16 -y && \ + rm /rustup.sh + +# Download libafl. +RUN git clone https://github.com/AFLplusplus/LibAFL /libafl + +# Checkout a current commit +COPY ./patch /libafl/patch +RUN cd /libafl && git pull && git checkout b4efb6151550a37f61a869acf2957a1b07894a93 && git apply patch || true +# Note that due a nightly bug it is currently fixed to a known version on top! + +# Compile libafl. +RUN cd /libafl && \ + unset CFLAGS CXXFLAGS && \ + export LIBAFL_EDGES_MAP_SIZE=2621440 && \ + cd ./fuzzers/fuzzbench && \ + PATH="/root/.cargo/bin/:$PATH" cargo build --profile release-fuzzbench --features no_link_main + +# Auxiliary weak references. +RUN cd /libafl/fuzzers/fuzzbench && \ + clang -c stub_rt.c && \ + ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/libafl_rand_scheduler/description.md b/fuzzers/libafl_rand_scheduler/description.md new file mode 100644 index 000000000..ea9b947d6 --- /dev/null +++ b/fuzzers/libafl_rand_scheduler/description.md @@ -0,0 +1,11 @@ +# libafl + +libafl fuzzer instance + - cmplog feature + - persistent mode + +Repository: [https://github.com/AFLplusplus/libafl/](https://github.com/AFLplusplus/libafl/) + +[builder.Dockerfile](builder.Dockerfile) +[fuzzer.py](fuzzer.py) +[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/libafl_rand_scheduler/fuzzer.py b/fuzzers/libafl_rand_scheduler/fuzzer.py new file mode 100755 index 000000000..0f191a744 --- /dev/null +++ b/fuzzers/libafl_rand_scheduler/fuzzer.py @@ -0,0 +1,72 @@ +# Copyright 2020 Google LLC +# +# 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. +# +"""Integration code for a LibAFL-based fuzzer.""" + +import os +import subprocess + +from fuzzers import utils + + +def prepare_fuzz_environment(input_corpus): + """Prepare to fuzz with a LibAFL-based fuzzer.""" + os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:'\ + 'malloc_context_size=0:symbolize=0:'\ + 'allocator_may_return_null=1:'\ + 'detect_odr_violation=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_abort=0:'\ + 'handle_sigfpe=0:handle_sigill=0' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:'\ + 'allocator_release_to_os_interval_ms=500:'\ + 'handle_abort=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_sigfpe=0:'\ + 'handle_sigill=0:print_stacktrace=0:'\ + 'symbolize=0:symbolize_inline_frames=0' + # Create at least one non-empty seed to start. + utils.create_seed_file_for_empty_corpus(input_corpus) + + +def build(): # pylint: disable=too-many-branches,too-many-statements + """Build benchmark.""" + os.environ[ + 'CC'] = '/libafl/fuzzers/fuzzbench/target/release-fuzzbench/libafl_cc' + os.environ[ + 'CXX'] = '/libafl/fuzzers/fuzzbench/target/release-fuzzbench/libafl_cxx' + + os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' + + cflags = ['--libafl'] + cxxflags = ['--libafl', '--std=c++14'] + utils.append_flags('CFLAGS', cflags) + utils.append_flags('CXXFLAGS', cxxflags) + utils.append_flags('LDFLAGS', cflags) + + os.environ['FUZZER_LIB'] = '/stub_rt.a' + utils.build_benchmark() + + +def fuzz(input_corpus, output_corpus, target_binary): + """Run fuzzer.""" + prepare_fuzz_environment(input_corpus) + dictionary_path = utils.get_dictionary_path(target_binary) + command = [target_binary] + if dictionary_path: + command += (['-x', dictionary_path]) + command += (['-o', output_corpus, '-i', input_corpus]) + fuzzer_env = os.environ.copy() + fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' + print(command) + subprocess.check_call(command, cwd=os.environ['OUT'], env=fuzzer_env) diff --git a/fuzzers/libafl_rand_scheduler/patch b/fuzzers/libafl_rand_scheduler/patch new file mode 100644 index 000000000..6f6e13bcd --- /dev/null +++ b/fuzzers/libafl_rand_scheduler/patch @@ -0,0 +1,39 @@ +diff --git a/fuzzers/fuzzbench/src/lib.rs b/fuzzers/fuzzbench/src/lib.rs +index 9b162a48..af4ff31f 100644 +--- a/fuzzers/fuzzbench/src/lib.rs ++++ b/fuzzers/fuzzbench/src/lib.rs +@@ -29,9 +29,7 @@ use libafl::{ + StdMOptMutator, StdScheduledMutator, Tokens, + }, + observers::{CanTrack, HitcountsMapObserver, TimeObserver}, +- schedulers::{ +- powersched::PowerSchedule, IndexesLenTimeMinimizerScheduler, StdWeightedScheduler, +- }, ++ schedulers::RandScheduler, + stages::{ + calibrate::CalibrationStage, power::StdPowerMutationalStage, StdMutationalStage, + TracingStage, +@@ -307,11 +305,8 @@ fn fuzz( + + let power = StdPowerMutationalStage::new(mutator); + +- // A minimization+queue policy to get testcasess from the corpus +- let scheduler = IndexesLenTimeMinimizerScheduler::new( +- &edges_observer, +- StdWeightedScheduler::with_schedule(&mut state, &edges_observer, Some(PowerSchedule::FAST)), +- ); ++ // A random scheduler ++ let scheduler = RandScheduler::new(); + + // A fuzzer with feedbacks and a corpus scheduler + let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); +diff --git a/libafl_bolts/build.rs b/libafl_bolts/build.rs +index 5253398d..39acd4c6 100644 +--- a/libafl_bolts/build.rs ++++ b/libafl_bolts/build.rs +@@ -1,3 +1,5 @@ ++#![feature(error_in_core)] ++ + #[rustversion::nightly] + fn nightly() { + println!("cargo:rustc-cfg=nightly"); diff --git a/fuzzers/libafl_rand_scheduler/runner.Dockerfile b/fuzzers/libafl_rand_scheduler/runner.Dockerfile new file mode 100644 index 000000000..f0c5eb6cc --- /dev/null +++ b/fuzzers/libafl_rand_scheduler/runner.Dockerfile @@ -0,0 +1,25 @@ +# Copyright 2020 Google LLC +# +# 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. + +FROM gcr.io/fuzzbench/base-image + +RUN apt install libjemalloc2 + +# This makes interactive docker runs painless: +ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" +#ENV AFL_MAP_SIZE=2621440 +ENV PATH="$PATH:/out" +ENV AFL_SKIP_CPUFREQ=1 +ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 +ENV AFL_TESTCACHE_SIZE=2 diff --git a/fuzzers/prescientfuzz/builder.Dockerfile b/fuzzers/prescientfuzz/builder.Dockerfile new file mode 100644 index 000000000..1dd37a126 --- /dev/null +++ b/fuzzers/prescientfuzz/builder.Dockerfile @@ -0,0 +1,49 @@ +# Copyright 2020 Google LLC +# +# 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. + +ARG parent_image +FROM $parent_image + +# Uninstall old Rust & Install the latest one. +RUN if which rustup; then rustup self uninstall -y; fi && \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > /rustup.sh && \ + sh /rustup.sh -y && \ + /root/.cargo/bin/rustup toolchain install nightly && \ + rm /rustup.sh + +RUN apt-get update && \ + apt-get install -y \ + build-essential \ + cargo && \ + apt-get install -y wget libstdc++5 libtool-bin automake flex bison \ + libglib2.0-dev libpixman-1-dev python3-setuptools unzip \ + apt-utils apt-transport-https ca-certificates joe curl && \ + PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make + +# Download PrescientFuzz +RUN git clone https://github.com/DanBlackwell/PrescientFuzz /PrescientFuzz +RUN cd /PrescientFuzz && git fetch && git checkout 9014fe72a16af3b7298e9c2f80512f21f479223a + +# Compile PrescientFuzz. +RUN cd /PrescientFuzz && \ + unset CFLAGS CXXFLAGS && \ + export CC=clang AFL_NO_X86 && \ + export LIBAFL_EDGES_MAP_SIZE=2621440 && \ + cd ./fuzzers/fuzzbench && \ + PATH="/root/.cargo/bin/:$PATH" cargo +nightly build --profile release-fuzzbench --features no_link_main + +# Auxiliary weak references. +RUN cd /PrescientFuzz/fuzzers/fuzzbench && \ + clang -c stub_rt.c && \ + ar r /stub_rt.a stub_rt.o diff --git a/fuzzers/prescientfuzz/description.md b/fuzzers/prescientfuzz/description.md new file mode 100644 index 000000000..452b0e374 --- /dev/null +++ b/fuzzers/prescientfuzz/description.md @@ -0,0 +1,8 @@ +# PrescientFuzz + +based on libafl fuzzer instance + - persistent mode + +[builder.Dockerfile](builder.Dockerfile) +[fuzzer.py](fuzzer.py) +[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/prescientfuzz/fuzzer.py b/fuzzers/prescientfuzz/fuzzer.py new file mode 100755 index 000000000..5f2dfa95f --- /dev/null +++ b/fuzzers/prescientfuzz/fuzzer.py @@ -0,0 +1,83 @@ +# Copyright 2020 Google LLC +# +# 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. +# +"""Integration code for a LibAFL-based fuzzer.""" + +import os +import sys +import subprocess +from pathlib import Path + +from fuzzers import utils + + +def prepare_fuzz_environment(input_corpus): + """Prepare to fuzz with a LibAFL-based fuzzer.""" + os.environ['ASAN_OPTIONS'] = 'abort_on_error=1:detect_leaks=0:'\ + 'malloc_context_size=0:symbolize=0:'\ + 'allocator_may_return_null=1:'\ + 'detect_odr_violation=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_abort=0:'\ + 'handle_sigfpe=0:handle_sigill=0' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=1:'\ + 'allocator_release_to_os_interval_ms=500:'\ + 'handle_abort=0:handle_segv=0:'\ + 'handle_sigbus=0:handle_sigfpe=0:'\ + 'handle_sigill=0:print_stacktrace=0:'\ + 'symbolize=0:symbolize_inline_frames=0' + # Create at least one non-empty seed to start. + utils.create_seed_file_for_empty_corpus(input_corpus) + + +def build(): + """Build benchmark.""" + os.environ['CC'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cc') + os.environ['CXX'] = ('/PrescientFuzz/fuzzers/fuzzbench/target/' + 'release-fuzzbench/libafl_cxx') + + os.environ['ASAN_OPTIONS'] = 'abort_on_error=0:allocator_may_return_null=1' + os.environ['UBSAN_OPTIONS'] = 'abort_on_error=0' + + cflags = ['--libafl'] + utils.append_flags('CFLAGS', cflags) + utils.append_flags('CXXFLAGS', cflags) + utils.append_flags('LDFLAGS', cflags) + + os.environ['FUZZER_LIB'] = '/stub_rt.a' + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + Path(cfg_file).touch() + os.environ['AFL_LLVM_CFG_FILE'] = cfg_file + utils.build_benchmark() + + +def fuzz(input_corpus, output_corpus, target_binary): + """Run fuzzer.""" + prepare_fuzz_environment(input_corpus) + dictionary_path = utils.get_dictionary_path(target_binary) + command = [target_binary] + if dictionary_path: + command += (['-x', dictionary_path]) + build_directory = os.environ['OUT'] + cfg_file = build_directory + '/afl_cfg.bin' + if os.path.exists(cfg_file): + command += (['-c', cfg_file]) + else: + sys.exit(1) + command += (['-o', output_corpus, '-i', input_corpus, '-b', '0.9999']) + fuzzer_env = os.environ.copy() + fuzzer_env['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libjemalloc.so.2' + print(command) + subprocess.check_call(command, cwd=os.environ['OUT'], env=fuzzer_env) diff --git a/fuzzers/prescientfuzz/runner.Dockerfile b/fuzzers/prescientfuzz/runner.Dockerfile new file mode 100644 index 000000000..1a023b81e --- /dev/null +++ b/fuzzers/prescientfuzz/runner.Dockerfile @@ -0,0 +1,25 @@ +# Copyright 2020 Google LLC +# +# 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. + +FROM gcr.io/fuzzbench/base-image + +RUN apt install libjemalloc2 + +# This makes interactive docker runs painless: +ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" +ENV AFL_MAP_SIZE=2621440 +ENV PATH="$PATH:/out" +ENV AFL_SKIP_CPUFREQ=1 +ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 +ENV AFL_TESTCACHE_SIZE=2 diff --git a/service/automatic_run_experiment.py b/service/automatic_run_experiment.py index 38c9059ad..f1d9f180e 100644 --- a/service/automatic_run_experiment.py +++ b/service/automatic_run_experiment.py @@ -64,7 +64,7 @@ def _get_description(experiment_config: dict) -> Optional[str]: def _use_oss_fuzz_corpus(experiment_config: dict) -> bool: """Returns the oss_fuzz_corpus flag of the experiment described by |experiment_config| as a bool.""" - return bool(experiment_config.get('oss-fuzz-corpus')) + return bool(experiment_config.get('oss_fuzz_corpus')) def _get_requested_experiments(): diff --git a/service/experiment-config.yaml b/service/experiment-config.yaml index b9acb09f8..53885721b 100644 --- a/service/experiment-config.yaml +++ b/service/experiment-config.yaml @@ -15,7 +15,7 @@ preemptible_runners: true # This experiment should generate a report that is combined with other public # "production" experiments. -merge_with_nonprivate: true +merge_with_nonprivate: false # This experiment should be merged with other reports in later experiments. private: false diff --git a/service/gcbrun_experiment.py b/service/gcbrun_experiment.py index f19ab493d..36892f9a0 100644 --- a/service/gcbrun_experiment.py +++ b/service/gcbrun_experiment.py @@ -16,6 +16,7 @@ """Entrypoint for gcbrun into run_experiment. This script will get the command from the last PR comment containing "/gcbrun" and pass it to run_experiment.py which will run an experiment.""" +# Please don't break the linter import logging import os