diff --git a/fuzzers/bandfuzz/builder.Dockerfile b/fuzzers/bandfuzz/builder.Dockerfile new file mode 100644 index 000000000..48c35bd99 --- /dev/null +++ b/fuzzers/bandfuzz/builder.Dockerfile @@ -0,0 +1,6 @@ +ARG parent_image +FROM $parent_image +COPY --from=whexy/bandfuzz:sbft_v1 /fuzzers /tmp/fuzzers +COPY --from=whexy/bandfuzz:sbft_v1 /bf /bf +ENV PATH="/bf/llvm/llvm-12/bin:${PATH}" +RUN echo "/bf/llvm/llvm-12/lib" >> /etc/ld.so.conf.d/bandfuzz.conf && ldconfig \ No newline at end of file diff --git a/fuzzers/bandfuzz/fuzzer.py b/fuzzers/bandfuzz/fuzzer.py new file mode 100644 index 000000000..23c6b7fb6 --- /dev/null +++ b/fuzzers/bandfuzz/fuzzer.py @@ -0,0 +1,70 @@ +# BandFuzz +# Author: Wenxuan (wenxuan.shi@northwestern.edu, shiwx.org) + +import os +import shutil +import subprocess + +def build(): + env = os.environ.copy() + src_folder = env['SRC'] + out_folder = os.path.join(env['OUT'], 'target') + build_script = os.path.join(src_folder, 'build.sh') + benchmark = os.getenv('BENCHMARK') + fuzzer = os.getenv('FUZZER') + + # Run bf-cc to build the benchmark + print(f'Building benchmark {benchmark} with fuzzer {fuzzer}!') + subprocess.check_call(['chmod', '+x', build_script]) + subprocess.check_call(['cp', '/bf/compilers.yaml', "."]) + subprocess.check_call(['/bf/bin/bf-cc', '-i', src_folder, '-o', out_folder, build_script], env=env) + + # Copy fuzzers to the out folder + subprocess.check_call(['cp', '-r', '/bf/fuzzers', env['OUT']]) + + # Copy necessary runtime files to the out folder + subprocess.check_call(['mkdir', '-p', os.path.join(env['OUT'], 'llvm')]) + subprocess.check_call(['cp', '-r', '/bf/llvm/llvm-12/bin', os.path.join(env['OUT'], 'llvm', 'bin')]) + subprocess.check_call(['cp', '-r', '/bf/llvm/llvm-12/lib', os.path.join(env['OUT'], 'llvm', 'lib')]) + subprocess.check_call(['cp', '/bf/bin/bf', env['OUT']]) + subprocess.check_call(['cp', '/bf/config_gen.py', env['OUT']]) + + # Copy one target binary to the out folder + # otherwise fuzzbench will complain, because of common/fuzzer_utils.py: get_fuzz_target_binary (line 77) + source_dir = os.path.join(env['OUT'], 'target', 'aflpp') + dest_dir = env['OUT'] + for item in os.listdir(source_dir): + s = os.path.join(source_dir, item) + d = os.path.join(dest_dir, item) + + if os.path.isdir(s): + shutil.copytree(s, d, dirs_exist_ok=True) + else: + shutil.copy2(s, d) + +def fuzz(input_corpus, output_corpus, target_binary): + target_binary_base = os.path.basename(target_binary) + target_folder = os.path.dirname(target_binary) + target_binary_name = os.path.join(target_folder, "target", target_binary_base) + + # Generate config file + with open("config.yaml", "w") as file: + config_gen_script = os.path.join(target_folder,'config_gen.py') + subprocess.check_call(['chmod', '+x', config_gen_script]) + subprocess.check_call([config_gen_script, '-i', input_corpus, '-o', output_corpus, '--', target_binary_name], env=os.environ.copy(), stdout=file) + + # Generate empty seed file if no seed file is provided + if os.listdir(input_corpus): + pass + else: + print('Creating a fake seed file in empty corpus directory.') + default_seed_file = os.path.join(input_corpus, 'default_seed') + with open(default_seed_file, 'w', encoding='utf-8') as file_handle: + file_handle.write('hi') + + # add /out/llvm/lib to ldconfig + with open('/etc/ld.so.conf.d/bandfuzz.conf', 'w') as file: + file.write('/out/llvm/lib\n') + subprocess.check_call(['ldconfig']) + + subprocess.check_call(['./bf', '--lazy=30']) diff --git a/fuzzers/bandfuzz/runner.Dockerfile b/fuzzers/bandfuzz/runner.Dockerfile new file mode 100644 index 000000000..9e483a3be --- /dev/null +++ b/fuzzers/bandfuzz/runner.Dockerfile @@ -0,0 +1,7 @@ +FROM gcr.io/fuzzbench/base-image + +# ! Breaking change: There's something wrong in Google Cloud SDK apt source, so I have to change it back to ubuntu default source. +RUN rm -rf /etc/apt +COPY --from=ubuntu:20.04 /etc/apt/ /etc/apt/ +# ! Before submit anything, please change it back to Google Cloud SDK apt source. +RUN apt-get update -y && apt-get install -y libbfd-dev libunwind-dev \ No newline at end of file diff --git a/fuzzers/fox/builder.Dockerfile b/fuzzers/fox/builder.Dockerfile new file mode 100644 index 000000000..c8619223b --- /dev/null +++ b/fuzzers/fox/builder.Dockerfile @@ -0,0 +1,102 @@ +# 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 ubuntu:focal +# ARG DEBIAN_FRONTEND=noninteractive + +ARG parent_image +FROM $parent_image + +RUN apt-get update && \ + apt-get -y install --no-install-suggests --no-install-recommends \ + automake \ + cmake \ + meson \ + ninja-build \ + bison flex \ + build-essential \ + git \ + binutils \ + python3 python3-dev python3-setuptools python-is-python3 \ + libtool libtool-bin \ + libglib2.0-dev \ + wget vim jupp nano bash-completion less \ + apt-utils apt-transport-https ca-certificates gnupg dialog \ + libpixman-1-dev \ + gnuplot-nox \ + sudo \ + && rm -rf /var/lib/apt/lists/* + +# Add ~/.local/bin and /usr/local/go/bin to the PATH +RUN mkdir -p /home/$USER_NAME/.local/bin +ENV PATH="/home/.local/bin:/usr/local/go/bin:/fox/gllvm_bins:${PATH}" +RUN echo "export PATH=$PATH" >> ~/.bashrc + +RUN apt-get update && \ + apt-get -y install --no-install-suggests --no-install-recommends \ + lsb-release wget software-properties-common gnupg + +RUN wget https://apt.llvm.org/llvm.sh +RUN chmod +x llvm.sh +RUN sudo ./llvm.sh 15 + +RUN update-alternatives --install /usr/bin/clang clang /usr/bin/clang-15 10 \ + --slave /usr/bin/clang++ clang++ /usr/bin/clang++-15 \ + --slave /usr/bin/opt opt /usr/bin/opt-15 +RUN update-alternatives --install /usr/lib/llvm llvm /usr/lib/llvm-15 20 \ + --slave /usr/bin/llvm-config llvm-config /usr/bin/llvm-config-15 \ + --slave /usr/bin/llvm-link llvm-link /usr/bin/llvm-link-15 + +ENV LLVM_CONFIG=llvm-config-15 + +# Import and setup FOX : TODO : add publie repo +RUN git clone https://github.com/adamstorek/FOX.git /fox +RUN git -C /fox checkout sbft24_stable +RUN rm -f /dev/shm/* + +RUN git clone https://github.com/adamstorek/FOX.git /fox_cmplog +RUN git -C /fox_cmplog checkout 4.10c_hybrid_mode +RUN rm -f /dev/shm/* + +# XXX: Set up vanilla AFL++ as a vanilla option to invoke in case the compilation +# fails (Current known failing targets: harfbuzz, systemd, php) +RUN git clone -b dev https://github.com/AFLplusplus/AFLplusplus /afl_vanilla && \ + cd /afl_vanilla && \ + git checkout tags/v4.10c || \ + true + +# Build without Python support as we don't need it. +# Set AFL_NO_X86 to skip flaky tests. +RUN cd /afl_vanilla && \ + unset CFLAGS CXXFLAGS && \ + export CC=clang-15 AFL_NO_X86=1 && \ + PYTHON_INCLUDE=/ make && \ + cp utils/aflpp_driver/libAFLDriver.a / + +RUN cd /fox && \ + unset CFLAGS CXXFLAGS && \ + export CC=clang-15 AFL_NO_X86=1 && \ + PYTHON_INCLUDE=/ make && \ + cp utils/aflpp_driver/libAFLDriver.a / + +RUN cd /fox_cmplog && \ + unset CFLAGS CXXFLAGS && \ + export CC=clang-15 AFL_NO_X86=1 && \ + PYTHON_INCLUDE=/ make && \ + cp utils/aflpp_driver/libAFLDriver.a / + +RUN rm /usr/local/bin/llvm-nm +RUN sudo ln -s /usr/bin/llvm-nm-15 /usr/local/bin/llvm-nm + +RUN rm -rf /usr/local/bin/clang* diff --git a/fuzzers/fox/fuzzer.py b/fuzzers/fox/fuzzer.py new file mode 100644 index 000000000..77519687a --- /dev/null +++ b/fuzzers/fox/fuzzer.py @@ -0,0 +1,390 @@ +# 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 FOX fuzzer.""" + +import os +import shutil +import subprocess +import sys + +from fuzzers import utils + + +def is_benchmark(name): + """Check if the benchmark contains the string |name|""" + benchmark = os.getenv("BENCHMARK", None) + return benchmark is not None and name in benchmark + + +def get_cmplog_build_directory(target_directory): + """Return path to CmpLog target directory.""" + return os.path.join(target_directory, "cmplog") + + +def get_vanilla_build_directory(target_directory): + """Return path to CmpLog target directory.""" + return os.path.join(target_directory, "vanilla") + + +def install(package): + """Install Dependencies""" + subprocess.check_call([sys.executable, "-m", "pip", "install", package]) + + +def install_all(): + """Dependencies""" + # packages = ["decorator==5.1.1", "ipdb==0.13.13", "ipython==8.12.2", + # "networkit==10.1", "numpy==1.24.4","pickleshare==0.7.5", "scipy==1.10.1", + # "tomli==2.0.1"] + packages = [ + "asttokens==2.2.1", "backcall==0.2.0", "decorator==5.1.1", + "executing==1.2.0", "greenstalk==2.0.2", "ipdb==0.13.13", + "ipython==8.12.2", "jedi==0.18.2", "networkit==10.1", "numpy==1.24.4", + "parso==0.8.3", "pexpect==4.8.0", "pickleshare==0.7.5", + "prompt-toolkit==3.0.39", "psutil==5.9.5", "ptyprocess==0.7.0", + "pure-eval==0.2.2", "Pygments==2.15.1", "PyYAML==5.3.1", + "scipy==1.10.1", "six==1.16.0", "stack-data==0.6.2", "tabulate==0.9.0", + "tomli==2.0.1", "traitlets==5.9.0", "typing-extensions==4.7.1", + "wcwidth==0.2.6" + ] + for package in packages: + install(package) + + +def prepare_build_environment(): + """Set environment variables used to build targets for AFL-based + fuzzers.""" + os.environ["AFL_CC"] = "gclang" + os.environ["AFL_CXX"] = "gclang++" + + os.environ["CC"] = "/fox/afl-clang-fast" + os.environ["CXX"] = "/fox/afl-clang-fast++" + os.environ["FUZZER_LIB"] = "/fox/libAFLDriver.a" + + # Fixup a file for mbedtls + if is_benchmark("mbedtls"): + file_path = os.path.join(os.getenv("SRC"), "mbedtls", + "library/CMakeLists.txt") + assert os.path.isfile(file_path), "The file does not exist" + # Remove -Wdocumentation to make compilation pass with clang 15.0.7 + # subst_cmd = r"sed -i 's/\(-Wdocumentation\)//g' {}".format(file_path) + subst_cmd = r"sed -i 's/\(-Wdocumentation\)//g'" + " " + file_path + subprocess.check_call(subst_cmd, shell=True) + + # Fixup a file for openthread + if is_benchmark("openthread"): + mbed_cmake_one = os.path.join(os.getenv("SRC"), + "openthread/third_party/mbedtls/repo", + "library/CMakeLists.txt") + mbed_cmake_two = os.path.join(os.getenv("SRC"), + "openthread/third_party/mbedtls/repo", + "CMakeLists.txt") + assert os.path.isfile(mbed_cmake_one), "The file does not exist" + assert os.path.isfile(mbed_cmake_two), "The file does not exist" + subst_cmd = r"sed -i 's/\(-Wdocumentation\)//g'" + " " + mbed_cmake_one + subprocess.check_call(subst_cmd, shell=True) + subst_cmd = r"sed -i 's/\(-Werror\)//g'" + " " + mbed_cmake_two + subprocess.check_call(subst_cmd, shell=True) + + +def build_fox_binary(): + """Build fox binary""" + + is_vanilla = False + subprocess.check_call(["rm", "-f", "/dev/shm/*"]) + + print("[build 0/2] build target binary") + src = os.getenv("SRC") + work = os.getenv("WORK") + pwd = os.getcwd() + + os.environ["AFL_LLVM_DICT2FILE"] = os.environ["OUT"] + "/keyval.dict" + os.environ["AFL_LLVM_DICT2FILE_NO_MAIN"] = "1" + + # Create personal backups in case + with utils.restore_directory(src), utils.restore_directory(work): + # Restore SRC to its initial state so we can build again without any + # trouble. For some OSS-Fuzz projects, build_benchmark cannot be run + # twice in the same directory without this. + try: + utils.build_benchmark() + + subprocess.check_call([ + "cp", "/dev/shm/br_src_map", + os.path.join(os.environ["OUT"], "br_src_map") + ]) + subprocess.check_call([ + "cp", "/dev/shm/strcmp_err_log", + os.path.join(os.environ["OUT"], "strcmp_err_log") + ]) + subprocess.check_call([ + "cp", "/dev/shm/instrument_meta_data", + os.path.join(os.environ["OUT"], "instrument_meta_data") + ]) + + print("[build 1/2] generate metadata") + # use FUZZ_TARGET env to generate metadata + env = os.environ.copy() + + fuzz_target = os.path.join(os.environ["OUT"], + os.environ["FUZZ_TARGET"]) + subprocess.check_call(["get-bc", fuzz_target], env=env) + + bc_file = fuzz_target + ".bc" + subprocess.check_call(["llvm-dis-15", bc_file], env=env) + + ll_file = fuzz_target + ".ll" + + os.chdir("/out") + gen_graph_python = "/fox/gen_graph_dev_no_dot_15_noasan.py" + subprocess.check_call([ + "python3", gen_graph_python, ll_file, fuzz_target, + "instrument_meta_data" + ], + env=env) + os.chdir(pwd) + except subprocess.CalledProcessError: + print("[X] Compilation or metadata gen failed..using fallback") + # Go back to the base dir where the outfiles are being kept + os.chdir(pwd) + is_vanilla = True + return is_vanilla + + is_vanilla = create_cmplog_binaries() + return is_vanilla + + +def create_cmplog_binaries(): + """Build cmplog binaries""" + + is_vanilla = False + src = os.getenv("SRC") + work = os.getenv("WORK") + pwd = os.getcwd() + + # Create main cmplog binary + with utils.restore_directory(src), utils.restore_directory(work): + # Restore SRC to its initial state so we can build again without any + # trouble. For some OSS-Fuzz projects, build_benchmark cannot be run + # twice in the same directory without this. + new_env = os.environ.copy() + cmplog_hybrid_directory_main = os.path.join(os.getenv("OUT"), + "cmplog_hybrid_main") + new_env["OUT"] = cmplog_hybrid_directory_main + fuzz_target = os.getenv("FUZZ_TARGET") + os.mkdir(cmplog_hybrid_directory_main) + if fuzz_target: + new_env["FUZZ_TARGET"] = os.path.join(cmplog_hybrid_directory_main, + os.path.basename(fuzz_target)) + new_env["CC"] = "/fox_cmplog/afl-clang-fast" + new_env["CXX"] = "/fox_cmplog/afl-clang-fast++" + new_env["FUZZER_LIB"] = "/fox_cmplog/libAFLDriver.a" + try: + utils.build_benchmark(env=new_env) + os.chdir(pwd) + except subprocess.CalledProcessError: + print("[X] Compilation or metadata gen failed for main cmplog") + # Go back to the base dir where the outfiles are being kept + os.chdir(pwd) + is_vanilla = True + return is_vanilla + + # Create cmplog build + # Create personal backups in case + with utils.restore_directory(src), utils.restore_directory(work): + # Restore SRC to its initial state so we can build again without any + # trouble. For some OSS-Fuzz projects, build_benchmark cannot be run + # twice in the same directory without this. + new_env = os.environ.copy() + new_env["AFL_LLVM_CMPLOG"] = "1" + cmplog_hybrid_directory_support = os.path.join(os.getenv("OUT"), + "cmplog_hybrid_support") + new_env["OUT"] = cmplog_hybrid_directory_support + fuzz_target = os.getenv("FUZZ_TARGET") + os.mkdir(cmplog_hybrid_directory_support) + if fuzz_target: + new_env["FUZZ_TARGET"] = os.path.join( + cmplog_hybrid_directory_support, os.path.basename(fuzz_target)) + new_env["CC"] = "/fox_cmplog/afl-clang-fast" + new_env["CXX"] = "/fox_cmplog/afl-clang-fast++" + new_env["FUZZER_LIB"] = "/fox_cmplog/libAFLDriver.a" + try: + utils.build_benchmark(env=new_env) + os.chdir(pwd) + except subprocess.CalledProcessError: + print("[X] Compilation or metadata gen failed for support cmplog") + # Go back to the base dir where the outfiles are being kept + os.chdir(pwd) + is_vanilla = True + return is_vanilla + return is_vanilla + + +def build(): + """Build benchmark.""" + is_vanilla = False + install_all() + prepare_build_environment() + + src = os.getenv("SRC") + work = os.getenv("WORK") + + is_vanilla = build_fox_binary() + + if is_vanilla: + new_env = os.environ.copy() + new_env["CC"] = "/afl_vanilla/afl-clang-fast" + new_env["CXX"] = "/afl_vanilla/afl-clang-fast++" + new_env["FUZZER_LIB"] = "/afl_vanilla/libAFLDriver.a" + vanilla_build_directory = get_vanilla_build_directory(os.getenv("OUT")) + os.mkdir(vanilla_build_directory) + new_env["OUT"] = vanilla_build_directory + fuzz_target = os.getenv("FUZZ_TARGET") + if fuzz_target: + new_env["FUZZ_TARGET"] = os.path.join(vanilla_build_directory, + os.path.basename(fuzz_target)) + with utils.restore_directory(src), utils.restore_directory(work): + utils.build_benchmark(env=new_env) + shutil.copy(new_env["FUZZ_TARGET"], os.getenv("OUT")) + + # Build the vanilla binary + new_env["AFL_LLVM_CMPLOG"] = "1" + + cmplog_build_directory = get_cmplog_build_directory(os.getenv("OUT")) + os.mkdir(cmplog_build_directory) + new_env["OUT"] = cmplog_build_directory + fuzz_target = os.getenv("FUZZ_TARGET") + if fuzz_target: + new_env["FUZZ_TARGET"] = os.path.join(cmplog_build_directory, + os.path.basename(fuzz_target)) + + print("Re-building benchmark for CmpLog fuzzing target") + with utils.restore_directory(src), utils.restore_directory(work): + utils.build_benchmark(env=new_env) + + # Write a flag file to signal that fox processing failed + with open(os.path.join(os.getenv("OUT"), "is_vanilla"), + "w", + encoding="utf-8") as file_desc: + file_desc.write("is_vanilla") + + print("[post_build] Copying afl-fuzz to $OUT directory") + # Copy out the afl-fuzz binary as a build artifact. + shutil.copy("/fox/afl-fuzz", + os.path.join(os.environ["OUT"], "fox_4.09c_hybrid_start")) + shutil.copy("/fox/ensemble_runner.py", os.environ["OUT"]) + shutil.copy("/fox_cmplog/afl-fuzz", + os.path.join(os.environ["OUT"], "cmplog_4.09c_hybrid_start")) + shutil.copy("/afl_vanilla/afl-fuzz", + os.path.join(os.environ["OUT"], "afl-fuzz-vanilla")) + + +def prepare_fuzz_environment(input_corpus): + """Prepare to fuzz with AFL or another AFL-based fuzzer.""" + # Tell AFL to not use its terminal UI so we get usable logs. + os.environ["AFL_NO_UI"] = "1" + # Skip AFL's CPU frequency check (fails on Docker). + os.environ["AFL_SKIP_CPUFREQ"] = "1" + # No need to bind affinity to one core, Docker enforces 1 core usage. + os.environ["AFL_NO_AFFINITY"] = "1" + # AFL will abort on startup if the core pattern sends notifications to + # external programs. We don't care about this. + os.environ["AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES"] = "1" + # Don't exit when crashes are found. This can happen when corpus from + # OSS-Fuzz is used. + os.environ["AFL_SKIP_CRASHES"] = "1" + # Shuffle the queue + os.environ["AFL_SHUFFLE_QUEUE"] = "1" + + #XXX: Added from aflplusplus + os.environ["AFL_FAST_CAL"] = "1" + os.environ["AFL_DISABLE_TRIM"] = "1" + os.environ["AFL_CMPLOG_ONLY_NEW"] = "1" + + # Allows resuming from an already fuzzed outdir (needed for fox hybrid mode) + os.environ["AFL_AUTORESUME"] = "1" + + # AFL needs at least one non-empty seed to start. + utils.create_seed_file_for_empty_corpus(input_corpus) + + +def run_afl_fuzz(input_corpus, output_corpus, target_binary, hide_output=False): + """Run afl-fuzz.""" + # Spawn the afl fuzzing process. + is_vanilla = False + dictionary_path = utils.get_dictionary_path(target_binary) + print("[run_afl_fuzz] Running target with afl-fuzz") + # Check if the fuzzer is to be run in fallback mode or not + if os.path.exists(os.path.join(os.getenv("OUT"), "is_vanilla")): + is_vanilla = True + if not is_vanilla: + cmplog_target_binary_directory_main = os.path.join( + os.path.dirname(target_binary), "cmplog_hybrid_main") + cmplog_target_binary_main = os.path.join( + cmplog_target_binary_directory_main, + os.path.basename(target_binary)) + + cmplog_target_binary_directory_support = os.path.join( + os.path.dirname(target_binary), "cmplog_hybrid_support") + cmplog_target_binary_support = os.path.join( + cmplog_target_binary_directory_support, + os.path.basename(target_binary)) + if dictionary_path: + command = [ + "python", "ensemble_runner.py", "-i", input_corpus, "-o", + output_corpus, "-b", cmplog_target_binary_main, + "--fox_target_binary", target_binary, "-x", "/out/keyval.dict", + dictionary_path, "--cmplog_target_binary", + cmplog_target_binary_support + ] + else: + command = [ + "python", "ensemble_runner.py", "-i", input_corpus, "-o", + output_corpus, "-b", cmplog_target_binary_main, + "--fox_target_binary", target_binary, "-x", "/out/keyval.dict", + "--cmplog_target_binary", cmplog_target_binary_support + ] + else: + # Calculate vanilla binary path from the instrumented target binary. + # Calculate CmpLog binary path from the instrumented target binary. + cmplog_target_binary_directory = (get_cmplog_build_directory( + os.path.dirname(target_binary))) + vanilla_target_binary = os.path.join( + get_vanilla_build_directory(os.path.dirname(target_binary)), + os.path.basename(target_binary)) + cmplog_target_binary = os.path.join(cmplog_target_binary_directory, + os.path.basename(target_binary)) + if dictionary_path: + command = [ + "./afl-fuzz-vanilla", "-i", input_corpus, "-o", output_corpus, + "-t", "1000+", "-m", "none", "-c", cmplog_target_binary, "-x", + "/out/keyval.dict", "-x", dictionary_path, "--", + vanilla_target_binary + ] + else: + command = [ + "./afl-fuzz-vanilla", "-i", input_corpus, "-o", output_corpus, + "-t", "1000+", "-m", "none", "-c", cmplog_target_binary, "-x", + "/out/keyval.dict", "--", vanilla_target_binary + ] + print("[run_afl_fuzz] Running command: " + " ".join(command)) + output_stream = subprocess.DEVNULL if hide_output else None + subprocess.check_call(command, stdout=output_stream, stderr=output_stream) + + +def fuzz(input_corpus, output_corpus, target_binary): + """Run afl-fuzz on target.""" + prepare_fuzz_environment(input_corpus) + + run_afl_fuzz(input_corpus, output_corpus, target_binary) diff --git a/fuzzers/fox/runner.Dockerfile b/fuzzers/fox/runner.Dockerfile new file mode 100644 index 000000000..f0a87f43e --- /dev/null +++ b/fuzzers/fox/runner.Dockerfile @@ -0,0 +1,24 @@ +# 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 + +# 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 +RUN apt-get update && apt install -y unzip git gdb joe diff --git a/fuzzers/mystique/builder.Dockerfile b/fuzzers/mystique/builder.Dockerfile new file mode 100644 index 000000000..9ea480f81 --- /dev/null +++ b/fuzzers/mystique/builder.Dockerfile @@ -0,0 +1,58 @@ +# 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 \ + 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 && \ + yes | bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" llvm.sh 17 && \ + PATH="/root/.cargo/bin/:$PATH" cargo install cargo-make && \ + apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +# Download libafl. +RUN git clone https://github.com/am009/LibAFL.git /libafl + +# Checkout a current commit +RUN cd /libafl && git pull && git checkout c0e20667e14b93f5d234080dc9922c6643f0b8eb +# Note that due a nightly bug it is currently fixed to a known version on top! + + +# export LLVM_BINDIR=/usr/local/bin && \ +# export LLVM_VERSION=15 && \ +# Compile libafl. Let the compiler wrapper call clang 15 in the base image to prevent build failures!! +RUN cd /libafl && \ + unset CFLAGS CXXFLAGS && \ + export LIBAFL_EDGES_MAP_SIZE=2621440 && \ + export LLVM_CONFIG=/usr/local/bin/llvm-config && \ + 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/mystique/description.md b/fuzzers/mystique/description.md new file mode 100644 index 000000000..ea9b947d6 --- /dev/null +++ b/fuzzers/mystique/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/mystique/fuzzer.py b/fuzzers/mystique/fuzzer.py new file mode 100755 index 000000000..45b316aa2 --- /dev/null +++ b/fuzzers/mystique/fuzzer.py @@ -0,0 +1,71 @@ +# 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_clang_cc' + os.environ[ + 'CXX'] = '/libafl/fuzzers/fuzzbench/target/release-fuzzbench/libafl_clang_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' + 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/mystique/runner.Dockerfile b/fuzzers/mystique/runner.Dockerfile new file mode 100644 index 000000000..f0c5eb6cc --- /dev/null +++ b/fuzzers/mystique/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/pastis/builder.Dockerfile b/fuzzers/pastis/builder.Dockerfile index 1a0e8fb5c..93a612e49 100644 --- a/fuzzers/pastis/builder.Dockerfile +++ b/fuzzers/pastis/builder.Dockerfile @@ -1,3 +1,17 @@ +# 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 @@ -25,10 +39,10 @@ RUN apt-get update && \ libstdc++-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-dev # Download afl++. -RUN git clone https://github.com/AFLplusplus/AFLplusplus /afl +RUN git clone https://github.com/AFLplusplus/AFLplusplus.git /afl -# Checkout a current commit -RUN cd /afl && git checkout 35f09e11a4373b0fb42c690d23127c144f72f73c +# Checkout v4.09c. +RUN cd /afl && git checkout -b v4.09c v4.09c # Build without Python support as we don't need it. # Set AFL_NO_X86 to skip flaky tests. @@ -51,25 +65,13 @@ RUN apt-get update -y && \ libblocksruntime-dev \ liblzma-dev -# Copy honggfuzz PASTIS patch. -RUN mkdir /patches -COPY patches/honggfuzz-3a8f2ae-pastis.patch /patches - -# Donwload honggfuzz oss-fuzz version (commit 3a8f2ae41604b6696e7bd5e5cdc0129ce49567c0) -RUN git clone https://github.com/google/honggfuzz.git /honggfuzz && \ - cd /honggfuzz && \ - git checkout 3a8f2ae41604b6696e7bd5e5cdc0129ce49567c0 && \ - cd .. - -# Apply PASTIS patch. -RUN cd / && \ - patch -s -p0 < /patches/honggfuzz-3a8f2ae-pastis.patch - # Set CFLAGS use honggfuzz's defaults except for -mnative which can build CPU # dependent code that may not work on the machines we actually fuzz on. # Create an empty object file which will become the FUZZER_LIB lib (since # honggfuzz doesn't need this when hfuzz-clang(++) is used). -RUN cd /honggfuzz && \ +RUN git clone https://github.com/google/honggfuzz.git /honggfuzz && \ + cd /honggfuzz && \ + git checkout oss-fuzz && \ CFLAGS="-O3 -funroll-loops" make && \ touch empty_lib.c && \ cc -c -o empty_lib.o empty_lib.c diff --git a/fuzzers/pastis/fuzzer.py b/fuzzers/pastis/fuzzer.py index 1ce5058f7..f513eab04 100644 --- a/fuzzers/pastis/fuzzer.py +++ b/fuzzers/pastis/fuzzer.py @@ -35,7 +35,7 @@ "thread_scheduling": 200, "smt_queries_limit": 0, "smt_enumeration_limit": 40, - "coverage_strategy": "PREFIXED_EDGE", + "coverage_strategy": "EDGE", "branch_solving_strategy": [ "ALL_NOT_COVERED" ], @@ -233,26 +233,10 @@ def fuzz(input_corpus, output_corpus, target_binary): # Prepare command-line string. command = [ - 'pastis-benchmark', - 'run', - '-b', - targets_dir, - '-w', - output_corpus, - '-s', - input_corpus, - '-m', - 'FULL', - '-i', - 'ARGV', - '-p', - '5551', - '--triton', - '--hfuzz', - '--hfuzz-threads', - '1', - '--aflpp', - '--skip-cpufreq', + 'pastis-benchmark', 'run', '-b', targets_dir, '-w', output_corpus, '-s', + input_corpus, '-m', 'FULL', '-i', 'ARGV', '-p', '5551', '--triton', + '--hfuzz', '--hfuzz-threads', '1', '--aflpp', '--skip-cpufreq', '--', + '@@' ] print('[fuzz] Running command: ' + ' '.join(command)) diff --git a/fuzzers/pastis/runner.Dockerfile b/fuzzers/pastis/runner.Dockerfile index 5127121de..10e95b8ac 100644 --- a/fuzzers/pastis/runner.Dockerfile +++ b/fuzzers/pastis/runner.Dockerfile @@ -1,3 +1,17 @@ +# 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 # NOTE Comiple Python again with `--enabled-shared`. diff --git a/fuzzers/tunefuzz/builder.Dockerfile b/fuzzers/tunefuzz/builder.Dockerfile new file mode 100644 index 000000000..094496644 --- /dev/null +++ b/fuzzers/tunefuzz/builder.Dockerfile @@ -0,0 +1,107 @@ +# 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 + +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=Etc/UTC + +RUN apt-get update && \ + apt-get install -y \ + build-essential \ + python3-dev \ + python3-setuptools \ + automake \ + cmake \ + git \ + flex \ + bison \ + libglib2.0-dev \ + libpixman-1-dev \ + cargo \ + libgtk-3-dev \ + # for QEMU mode + ninja-build \ + gcc-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-plugin-dev \ + libstdc++-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-dev + +RUN apt install -y git gcc g++ make cmake wget \ + libgmp-dev libmpfr-dev texinfo bison python3 + +RUN apt-get install -y libboost-all-dev libjsoncpp-dev libgraphviz-dev \ + pkg-config libglib2.0-dev findutils + +RUN apt install -y lsb-release wget software-properties-common python3-pip + +# these two packages are automatically installed, libpcap will consider libnl +# installed and try to link with libnl-genl-3-dev, which is not installed. +# Simply remove these packages +RUN apt remove libnl-3-200 libnl-3-dev -y + +RUN pip3 install networkx pydot + +RUN git clone https://github.com/kdsjZh/Fishpp /FishFuzz && \ + cd /FishFuzz && \ + git checkout be113d6a9d27c0b574d083f2d827d1e6c551435d || \ + true + +# build clang-12 with gold plugin +RUN mkdir -p /build && \ + git clone \ + https://github.com/llvm/llvm-project /llvm && \ + git clone \ + --depth 1 \ + --branch binutils-2_40-branch \ + git://sourceware.org/git/binutils-gdb.git /llvm/binutils && \ + cd /llvm/ && git checkout bf7f8d6fa6f460bf0a16ffec319cd71592216bf4 && \ + git apply /FishFuzz/fish_mode/llvm_patch/llvm-15.0/llvm-15-asan.diff && \ + cp /FishFuzz/fish_mode/llvm_patch/llvm-15.0/FishFuzzAddressSanitizer.cpp llvm/lib/Transforms/Instrumentation/ && \ + mkdir /llvm/binutils/build && cd /llvm/binutils/build && \ + CFLAGS="" CXXFLAGS="" CC=gcc CXX=g++ \ + ../configure --enable-gold --enable-plugins --disable-werror && \ + make all-gold -j$(nproc) && \ + cd /llvm/ && mkdir build && cd build &&\ + CFLAGS="" CXXFLAGS="" CC=gcc CXX=g++ \ + cmake -DCMAKE_BUILD_TYPE=Release \ + -DLLVM_BINUTILS_INCDIR=/llvm/binutils/include \ + -DLLVM_ENABLE_PROJECTS="compiler-rt;clang" \ + -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" ../llvm && \ + make -j$(nproc) && \ + cp /llvm/build/lib/LLVMgold.so //usr/lib/bfd-plugins/ && \ + cp /llvm/build/lib/libLTO.so //usr/lib/bfd-plugins/ + + +ENV LLVM_CONFIG=llvm-config + +# make sure our modified clang-12 is called before clang-15, which is in /usr/local/bin +ENV PATH="/llvm/build/bin:${PATH}" +ENV LD_LIBRARY_PATH="/llvm/build/lib/x86_64-unknown-linux-gnu/" + + +# Build without Python support as we don't need it. +# Set AFL_NO_X86 to skip flaky tests. +RUN cd /FishFuzz/ && \ + unset CFLAGS CXXFLAGS CC CXX && \ + git checkout 40947508037b874020c8dd1251359fecaab04b9d src/afl-fuzz-bitmap.c && \ + export AFL_NO_X86=1 && \ + make clean && \ + PYTHON_INCLUDE=/ make && \ + # make -C dyncfg && \ + chmod +x fish_mode/distance/*.py && \ + make install + +RUN wget https://raw.githubusercontent.com/llvm/llvm-project/5feb80e748924606531ba28c97fe65145c65372e/compiler-rt/lib/fuzzer/afl/afl_driver.cpp -O /FishFuzz/afl_driver.cpp && \ + clang++ -stdlib=libc++ -std=c++11 -O2 -c /FishFuzz/afl_driver.cpp -o /FishFuzz/afl_driver.o && \ + ar r /libAFLDriver.a /FishFuzz/afl_driver.o /FishFuzz/afl-compiler-rt.o diff --git a/fuzzers/tunefuzz/fuzzer.py b/fuzzers/tunefuzz/fuzzer.py new file mode 100644 index 000000000..0a79e68b7 --- /dev/null +++ b/fuzzers/tunefuzz/fuzzer.py @@ -0,0 +1,322 @@ +# 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 FishFuzz-AFLplusplus fuzzer.""" + +import os +import shutil + +from fuzzers.afl import fuzzer as afl_fuzzer +from fuzzers import utils + + +def get_cmplog_build_directory(target_directory): + """Return path to CmpLog target directory.""" + return os.path.join(target_directory, 'cmplog') + + +def get_uninstrumented_build_directory(target_directory): + """Return path to CmpLog target directory.""" + return os.path.join(target_directory, 'uninstrumented') + + +def prepare_tmp_files(tmp_dir): + """prepare tmp files""" + if not os.path.isdir(tmp_dir) or os.path.exists(tmp_dir): + os.mkdir(tmp_dir) + fua = tmp_dir + '/idlog' + fub = tmp_dir + '/cg' + fuc = tmp_dir + '/fid' + os.mkdir(fua) + os.mkdir(fub) + os.mkdir(fuc) + fud = 'touch ' + tmp_dir + '/idlog/fid ' + tmp_dir + '/idlog/targid' + os.system(fud) + + +def set_ff_env(): + """set FishFuzz Env before build""" + os.environ['TMP_DIR'] = os.environ['OUT'] + '/TEMP' + os.environ['FF_TMP_DIR'] = os.environ['OUT'] + '/TEMP' + prepare_tmp_files(os.environ['TMP_DIR']) + + +def build(*args): # pylint: disable=too-many-branches,too-many-statements + """Build benchmark.""" + # BUILD_MODES is not already supported by fuzzbench, meanwhile we provide + # a default configuration. + + build_modes = list(args) + if 'BUILD_MODES' in os.environ: + build_modes = os.environ['BUILD_MODES'].split(',') + + # Placeholder comment. + build_directory = os.environ['OUT'] + + # If nothing was set this is the default: + if not build_modes: + build_modes = ['tracepc', 'cmplog', 'dict2file'] + + # For bug type benchmarks we have to instrument via native clang pcguard :( + build_flags = os.environ['CFLAGS'] + os.environ['CFLAGS'] = build_flags + os.environ['USE_FF_INST'] = '1' + + #if build_flags.find( + # 'array-bounds' + #) != -1 and 'qemu' not in build_modes and 'classic' not in build_modes: + # if 'gcc' not in build_modes: + # build_modes[0] = 'native' + + # Instrumentation coverage modes: + if 'lto' in build_modes: + os.environ['CC'] = '/FishFuzz/afl-clang-lto' + os.environ['CXX'] = '/FishFuzz/afl-clang-lto++' + edge_file = build_directory + '/aflpp_edges.txt' + os.environ['AFL_LLVM_DOCUMENT_IDS'] = edge_file + if os.path.isfile('/usr/local/bin/llvm-ranlib-13'): + os.environ['RANLIB'] = 'llvm-ranlib-13' + os.environ['AR'] = 'llvm-ar-13' + os.environ['AS'] = 'llvm-as-13' + elif os.path.isfile('/usr/local/bin/llvm-ranlib-12'): + os.environ['RANLIB'] = 'llvm-ranlib-12' + os.environ['AR'] = 'llvm-ar-12' + os.environ['AS'] = 'llvm-as-12' + else: + os.environ['RANLIB'] = 'llvm-ranlib' + os.environ['AR'] = 'llvm-ar' + os.environ['AS'] = 'llvm-as' + elif 'qemu' in build_modes: + os.environ['CC'] = 'clang' + os.environ['CXX'] = 'clang++' + elif 'gcc' in build_modes: + os.environ['CC'] = 'afl-gcc-fast' + os.environ['CXX'] = 'afl-g++-fast' + if build_flags.find('array-bounds') != -1: + os.environ['CFLAGS'] = '-fsanitize=address -O1' + os.environ['CXXFLAGS'] = '-fsanitize=address -O1' + else: + os.environ['CFLAGS'] = '' + os.environ['CXXFLAGS'] = '' + os.environ['CPPFLAGS'] = '' + else: + os.environ['CC'] = '/FishFuzz/afl-clang-fast' + os.environ['CXX'] = '/FishFuzz/afl-clang-fast++' + + print('AFL++ build: ') + print(build_modes) + + if 'qemu' in build_modes or 'symcc' in build_modes: + os.environ['CFLAGS'] = ' '.join(utils.NO_SANITIZER_COMPAT_CFLAGS) + cxxflags = [utils.LIBCPLUSPLUS_FLAG] + utils.NO_SANITIZER_COMPAT_CFLAGS + os.environ['CXXFLAGS'] = ' '.join(cxxflags) + + if 'tracepc' in build_modes or 'pcguard' in build_modes: + os.environ['AFL_LLVM_USE_TRACE_PC'] = '1' + elif 'classic' in build_modes: + os.environ['AFL_LLVM_INSTRUMENT'] = 'CLASSIC' + elif 'native' in build_modes: + os.environ['AFL_LLVM_INSTRUMENT'] = 'LLVMNATIVE' + + # Instrumentation coverage options: + # Do not use a fixed map location (LTO only) + if 'dynamic' in build_modes: + os.environ['AFL_LLVM_MAP_DYNAMIC'] = '1' + # Use a fixed map location (LTO only) + if 'fixed' in build_modes: + os.environ['AFL_LLVM_MAP_ADDR'] = '0x10000' + # Generate an extra dictionary. + if 'dict2file' in build_modes or 'native' in build_modes: + os.environ['AFL_LLVM_DICT2FILE'] = build_directory + '/afl++.dict' + os.environ['AFL_LLVM_DICT2FILE_NO_MAIN'] = '1' + # Enable context sentitivity for LLVM mode (non LTO only) + if 'ctx' in build_modes: + os.environ['AFL_LLVM_CTX'] = '1' + # Enable N-gram coverage for LLVM mode (non LTO only) + if 'ngram2' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '2' + elif 'ngram3' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '3' + elif 'ngram4' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '4' + elif 'ngram5' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '5' + elif 'ngram6' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '6' + elif 'ngram7' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '7' + elif 'ngram8' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '8' + elif 'ngram16' in build_modes: + os.environ['AFL_LLVM_NGRAM_SIZE'] = '16' + if 'ctx1' in build_modes: + os.environ['AFL_LLVM_CTX_K'] = '1' + elif 'ctx2' in build_modes: + os.environ['AFL_LLVM_CTX_K'] = '2' + elif 'ctx3' in build_modes: + os.environ['AFL_LLVM_CTX_K'] = '3' + elif 'ctx4' in build_modes: + os.environ['AFL_LLVM_CTX_K'] = '4' + + # Only one of the following OR cmplog + # enable laf-intel compare splitting + if 'laf' in build_modes: + os.environ['AFL_LLVM_LAF_SPLIT_SWITCHES'] = '1' + os.environ['AFL_LLVM_LAF_SPLIT_COMPARES'] = '1' + os.environ['AFL_LLVM_LAF_SPLIT_FLOATS'] = '1' + if 'autodict' not in build_modes: + os.environ['AFL_LLVM_LAF_TRANSFORM_COMPARES'] = '1' + + if 'eclipser' in build_modes: + os.environ['FUZZER_LIB'] = '/libStandaloneFuzzTarget.a' + else: + os.environ['FUZZER_LIB'] = '/FishFuzz/afl_driver.o' # '/libAFLDriver.a' + + # Some benchmarks like lcms. (see: + # https://github.com/mm2/Little-CMS/commit/ab1093539b4287c233aca6a3cf53b234faceb792#diff-f0e6d05e72548974e852e8e55dffc4ccR212) + # fail to compile if the compiler outputs things to stderr in unexpected + # cases. Prevent these failures by using AFL_QUIET to stop afl-clang-fast + # from writing AFL specific messages to stderr. + os.environ['AFL_QUIET'] = '1' + os.environ['AFL_MAP_SIZE'] = '2621440' + + src = os.getenv('SRC') + work = os.getenv('WORK') + set_ff_env() + + with utils.restore_directory(src), utils.restore_directory(work): + # Restore SRC to its initial state so we can build again without any + # trouble. For some OSS-Fuzz projects, build_benchmark cannot be run + # twice in the same directory without this. + utils.build_benchmark() + + if 'cmplog' in build_modes and 'qemu' not in build_modes: + + # CmpLog requires an build with different instrumentation. + new_env = os.environ.copy() + new_env['AFL_LLVM_CMPLOG'] = '1' + if 'USE_FF_INST' in new_env: + del new_env['USE_FF_INST'] + + # For CmpLog build, set the OUT and FUZZ_TARGET environment + # variable to point to the new CmpLog build directory. + cmplog_build_directory = get_cmplog_build_directory(build_directory) + os.mkdir(cmplog_build_directory) + new_env['OUT'] = cmplog_build_directory + fuzz_target = os.getenv('FUZZ_TARGET') + if fuzz_target: + new_env['FUZZ_TARGET'] = os.path.join(cmplog_build_directory, + os.path.basename(fuzz_target)) + + print('Re-building benchmark for CmpLog fuzzing target') + utils.build_benchmark(env=new_env) + + if 'symcc' in build_modes: + + symcc_build_directory = get_uninstrumented_build_directory( + build_directory) + os.mkdir(symcc_build_directory) + + # symcc requires an build with different instrumentation. + new_env = os.environ.copy() + new_env['CC'] = '/symcc/build/symcc' + new_env['CXX'] = '/symcc/build/sym++' + new_env['SYMCC_OUTPUT_DIR'] = '/tmp' + new_env['CXXFLAGS'] = new_env['CXXFLAGS'].replace('-stlib=libc++', '') + new_env['FUZZER_LIB'] = '/libfuzzer-harness.o' + new_env['OUT'] = symcc_build_directory + new_env['SYMCC_LIBCXX_PATH'] = '/libcxx_native_build' + new_env['SYMCC_NO_SYMBOLIC_INPUT'] = '1' + new_env['SYMCC_SILENT'] = '1' + + # For symcc build, set the OUT and FUZZ_TARGET environment + # variable to point to the new symcc build directory. + new_env['OUT'] = symcc_build_directory + fuzz_target = os.getenv('FUZZ_TARGET') + if fuzz_target: + new_env['FUZZ_TARGET'] = os.path.join(symcc_build_directory, + os.path.basename(fuzz_target)) + + print('Re-building benchmark for symcc fuzzing target') + utils.build_benchmark(env=new_env) + + shutil.copy('/FishFuzz/afl-fuzz', build_directory) + if os.path.exists('/FishFuzz/afl-qemu-trace'): + shutil.copy('/FishFuzz/afl-qemu-trace', build_directory) + if os.path.exists('/aflpp_qemu_driver_hook.so'): + shutil.copy('/aflpp_qemu_driver_hook.so', build_directory) + if os.path.exists('/get_frida_entry.sh'): + shutil.copy('/FishFuzz/afl-frida-trace.so', build_directory) + shutil.copy('/get_frida_entry.sh', build_directory) + + tdst = os.environ['OUT'] + '/TEMP' + print('[post_build] generating distance files') + xxa = 'python3 /FishFuzz/fish_mode/distance/match_function.py -i ' + tdst + os.system(xxa) + xxb = ( + 'python3 /FishFuzz/fish_mode/distance/calculate_all_distance.py -i ' + + tdst) + os.system(xxb) + + +# pylint: disable=too-many-arguments +def fuzz(input_corpus, + output_corpus, + target_binary, + flags=tuple(), + skip=False, + no_cmplog=False): # pylint: disable=too-many-arguments + """Run fuzzer.""" + # Calculate CmpLog binary path from the instrumented target binary. + target_binary_directory = os.path.dirname(target_binary) + cmplog_target_binary_directory = ( + get_cmplog_build_directory(target_binary_directory)) + target_binary_name = os.path.basename(target_binary) + cmplog_target_binary = os.path.join(cmplog_target_binary_directory, + target_binary_name) + + afl_fuzzer.prepare_fuzz_environment(input_corpus) + # decomment this to enable libdislocator. + # os.environ['AFL_ALIGNED_ALLOC'] = '1' # align malloc to max_align_t + # os.environ['AFL_PRELOAD'] = '/FishFuzz/libdislocator.so' + + flags = list(flags) + + if os.path.exists('./afl++.dict'): + flags += ['-x', './afl++.dict'] + + # Move the following to skip for upcoming _double tests: + if os.path.exists(cmplog_target_binary) and no_cmplog is False: + flags += ['-c', cmplog_target_binary] + + # flags += ['-p', 'explore'] + + os.environ['FUZZ_NEARBY'] = '1' + #os.environ['AFL_IGNORE_TIMEOUTS'] = '1' + os.environ['AFL_IGNORE_UNKNOWN_ENVS'] = '1' + os.environ['AFL_FAST_CAL'] = '1' + os.environ['AFL_NO_WARN_INSTABILITY'] = '1' + + if not skip: + os.environ['AFL_DISABLE_TRIM'] = '1' + os.environ['AFL_CMPLOG_ONLY_NEW'] = '1' + if 'ADDITIONAL_ARGS' in os.environ: + flags += os.environ['ADDITIONAL_ARGS'].split(' ') + + os.environ['TMP_DIR'] = os.environ['OUT'] + '/TEMP' + + afl_fuzzer.run_afl_fuzz(input_corpus, + output_corpus, + target_binary, + additional_flags=flags) diff --git a/fuzzers/tunefuzz/runner.Dockerfile b/fuzzers/tunefuzz/runner.Dockerfile new file mode 100644 index 000000000..1be76e230 --- /dev/null +++ b/fuzzers/tunefuzz/runner.Dockerfile @@ -0,0 +1,44 @@ +# 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 + +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=Etc/UTC + +RUN apt update && apt install -y git gcc g++ make cmake wget \ + libgmp-dev libmpfr-dev texinfo bison python3 + +# for runtime library, we just need libc++-12-dev libc++abi-12-dev +RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|apt-key add - && \ + printf "deb http://apt.llvm.org/focal/ llvm-toolchain-focal main\n" \ + "deb-src http://apt.llvm.org/focal/ llvm-toolchain-focal main\n" \ + "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-12 main\n" \ + "deb-src http://apt.llvm.org/focal/ llvm-toolchain-focal-12 main\n" \ + >> /etc/apt/sources.list && \ + apt update && \ + apt install libc++-12-dev libc++abi-12-dev -y + +# for FF runtime +RUN apt-get install -y libboost-all-dev libjsoncpp-dev libgraphviz-dev \ + pkg-config libglib2.0-dev # libunwind-17 + +ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/out" +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/gcbrun_experiment.py b/service/gcbrun_experiment.py index f19ab493d..bff2e7b7c 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.""" +# A dummy comment import logging import os