diff --git a/.github/workflows/fuzzers.yml b/.github/workflows/fuzzers.yml index 7e3de9639..d6cf1aa1f 100644 --- a/.github/workflows/fuzzers.yml +++ b/.github/workflows/fuzzers.yml @@ -31,6 +31,7 @@ jobs: - mopt # Greybox fuzzers. - wingfuzz + - libafl_forkserver # - tortoisefuzz # To Be Fixed. # Symbolic ececution. # - klee # To Be Fixed. diff --git a/fuzzers/afl_collision_free/fuzzer.py b/fuzzers/afl_collision_free/fuzzer.py deleted file mode 100755 index 8c4a5be4e..000000000 --- a/fuzzers/afl_collision_free/fuzzer.py +++ /dev/null @@ -1,140 +0,0 @@ -# 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 AFL fuzzer.""" - -import json -import os -import shutil -import subprocess - -from fuzzers import utils - - -def prepare_build_environment(): - """Set environment variables used to build targets for AFL-based - fuzzers.""" - cflags = ['-fsanitize-coverage=trace-pc-guard'] - utils.append_flags('CFLAGS', cflags) - utils.append_flags('CXXFLAGS', cflags) - - os.environ['CC'] = 'clang' - os.environ['CXX'] = 'clang++' - os.environ['FUZZER_LIB'] = '/libAFL.a' - - -def build(): - """Build benchmark.""" - prepare_build_environment() - - utils.build_benchmark() - - print('[post_build] Copying afl-fuzz to $OUT directory') - # Copy out the afl-fuzz binary as a build artifact. - shutil.copy('/afl/afl-fuzz', os.environ['OUT']) - - -def get_stats(output_corpus, fuzzer_log): # pylint: disable=unused-argument - """Gets fuzzer stats for AFL.""" - # Get a dictionary containing the stats AFL reports. - stats_file = os.path.join(output_corpus, 'fuzzer_stats') - with open(stats_file, encoding='utf-8') as file_handle: - stats_file_lines = file_handle.read().splitlines() - stats_file_dict = {} - for stats_line in stats_file_lines: - key, value = stats_line.split(': ') - stats_file_dict[key.strip()] = value.strip() - - # Report to FuzzBench the stats it accepts. - stats = {'execs_per_sec': float(stats_file_dict['execs_per_sec'])} - return json.dumps(stats) - - -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' - # Sets AFL to avoid collisions - os.environ['AFL_COLLISION_FREE'] = '1' - - # AFL needs at least one non-empty seed to start. - utils.create_seed_file_for_empty_corpus(input_corpus) - - -def check_skip_det_compatible(additional_flags): - """ Checks if additional flags are compatible with '-d' option""" - # AFL refuses to take in '-d' with '-M' or '-S' options for parallel mode. - # (cf. https://github.com/google/AFL/blob/8da80951/afl-fuzz.c#L7477) - if '-M' in additional_flags or '-S' in additional_flags: - return False - return True - - -def run_afl_fuzz(input_corpus, - output_corpus, - target_binary, - additional_flags=None, - hide_output=False): - """Run afl-fuzz.""" - # Spawn the afl fuzzing process. - print('[run_afl_fuzz] Running target with afl-fuzz') - command = [ - './afl-fuzz', - '-i', - input_corpus, - '-o', - output_corpus, - # Use no memory limit as ASAN doesn't play nicely with one. - '-m', - 'none', - '-t', - '1000+', # Use same default 1 sec timeout, but add '+' to skip hangs. - ] - # Use '-d' to skip deterministic mode, as long as it it compatible with - # additional flags. - if not additional_flags or check_skip_det_compatible(additional_flags): - command.append('-d') - if additional_flags: - command.extend(additional_flags) - dictionary_path = utils.get_dictionary_path(target_binary) - if dictionary_path: - command.extend(['-x', dictionary_path]) - command += [ - '--', - target_binary, - # Pass INT_MAX to afl the maximize the number of persistent loops it - # performs. - '2147483647' - ] - 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/afl_double_timeout/fuzzer.py b/fuzzers/afl_double_timeout/fuzzer.py deleted file mode 100755 index 9876a0e47..000000000 --- a/fuzzers/afl_double_timeout/fuzzer.py +++ /dev/null @@ -1,140 +0,0 @@ -# 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 AFL fuzzer.""" - -import json -import os -import shutil -import subprocess - -from fuzzers import utils - - -def prepare_build_environment(): - """Set environment variables used to build targets for AFL-based - fuzzers.""" - cflags = ['-fsanitize-coverage=trace-pc-guard'] - utils.append_flags('CFLAGS', cflags) - utils.append_flags('CXXFLAGS', cflags) - - os.environ['CC'] = 'clang' - os.environ['CXX'] = 'clang++' - os.environ['FUZZER_LIB'] = '/libAFL.a' - - -def build(): - """Build benchmark.""" - prepare_build_environment() - - utils.build_benchmark() - - print('[post_build] Copying afl-fuzz to $OUT directory') - # Copy out the afl-fuzz binary as a build artifact. - shutil.copy('/afl/afl-fuzz', os.environ['OUT']) - - -def get_stats(output_corpus, fuzzer_log): # pylint: disable=unused-argument - """Gets fuzzer stats for AFL.""" - # Get a dictionary containing the stats AFL reports. - stats_file = os.path.join(output_corpus, 'fuzzer_stats') - with open(stats_file, encoding='utf-8') as file_handle: - stats_file_lines = file_handle.read().splitlines() - stats_file_dict = {} - for stats_line in stats_file_lines: - key, value = stats_line.split(': ') - stats_file_dict[key.strip()] = value.strip() - - # Report to FuzzBench the stats it accepts. - stats = {'execs_per_sec': float(stats_file_dict['execs_per_sec'])} - return json.dumps(stats) - - -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' - # Sets AFL timeout to be the double compared to the default heuristics - os.environ['AFL_DOUBLE_TIMEOUT'] = '1' - - # AFL needs at least one non-empty seed to start. - utils.create_seed_file_for_empty_corpus(input_corpus) - - -def check_skip_det_compatible(additional_flags): - """ Checks if additional flags are compatible with '-d' option""" - # AFL refuses to take in '-d' with '-M' or '-S' options for parallel mode. - # (cf. https://github.com/google/AFL/blob/8da80951/afl-fuzz.c#L7477) - if '-M' in additional_flags or '-S' in additional_flags: - return False - return True - - -def run_afl_fuzz(input_corpus, - output_corpus, - target_binary, - additional_flags=None, - hide_output=False): - """Run afl-fuzz.""" - # Spawn the afl fuzzing process. - print('[run_afl_fuzz] Running target with afl-fuzz') - command = [ - './afl-fuzz', - '-i', - input_corpus, - '-o', - output_corpus, - # Use no memory limit as ASAN doesn't play nicely with one. - '-m', - 'none', - '-t', - '1000+', # Use same default 1 sec timeout, but add '+' to skip hangs. - ] - # Use '-d' to skip deterministic mode, as long as it it compatible with - # additional flags. - if not additional_flags or check_skip_det_compatible(additional_flags): - command.append('-d') - if additional_flags: - command.extend(additional_flags) - dictionary_path = utils.get_dictionary_path(target_binary) - if dictionary_path: - command.extend(['-x', dictionary_path]) - command += [ - '--', - target_binary, - # Pass INT_MAX to afl the maximize the number of persistent loops it - # performs. - '2147483647' - ] - 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/afl_no_favfactor/fuzzer.py b/fuzzers/afl_no_favfactor/fuzzer.py deleted file mode 100755 index ec2e3d5ac..000000000 --- a/fuzzers/afl_no_favfactor/fuzzer.py +++ /dev/null @@ -1,140 +0,0 @@ -# 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 AFL fuzzer.""" - -import json -import os -import shutil -import subprocess - -from fuzzers import utils - - -def prepare_build_environment(): - """Set environment variables used to build targets for AFL-based - fuzzers.""" - cflags = ['-fsanitize-coverage=trace-pc-guard'] - utils.append_flags('CFLAGS', cflags) - utils.append_flags('CXXFLAGS', cflags) - - os.environ['CC'] = 'clang' - os.environ['CXX'] = 'clang++' - os.environ['FUZZER_LIB'] = '/libAFL.a' - - -def build(): - """Build benchmark.""" - prepare_build_environment() - - utils.build_benchmark() - - print('[post_build] Copying afl-fuzz to $OUT directory') - # Copy out the afl-fuzz binary as a build artifact. - shutil.copy('/afl/afl-fuzz', os.environ['OUT']) - - -def get_stats(output_corpus, fuzzer_log): # pylint: disable=unused-argument - """Gets fuzzer stats for AFL.""" - # Get a dictionary containing the stats AFL reports. - stats_file = os.path.join(output_corpus, 'fuzzer_stats') - with open(stats_file, encoding='utf-8') as file_handle: - stats_file_lines = file_handle.read().splitlines() - stats_file_dict = {} - for stats_line in stats_file_lines: - key, value = stats_line.split(': ') - stats_file_dict[key.strip()] = value.strip() - - # Report to FuzzBench the stats it accepts. - stats = {'execs_per_sec': float(stats_file_dict['execs_per_sec'])} - return json.dumps(stats) - - -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' - # Disables AFL corpus culling prioritization - os.environ['AFL_NO_FAV_FACTOR'] = '1' - - # AFL needs at least one non-empty seed to start. - utils.create_seed_file_for_empty_corpus(input_corpus) - - -def check_skip_det_compatible(additional_flags): - """ Checks if additional flags are compatible with '-d' option""" - # AFL refuses to take in '-d' with '-M' or '-S' options for parallel mode. - # (cf. https://github.com/google/AFL/blob/8da80951/afl-fuzz.c#L7477) - if '-M' in additional_flags or '-S' in additional_flags: - return False - return True - - -def run_afl_fuzz(input_corpus, - output_corpus, - target_binary, - additional_flags=None, - hide_output=False): - """Run afl-fuzz.""" - # Spawn the afl fuzzing process. - print('[run_afl_fuzz] Running target with afl-fuzz') - command = [ - './afl-fuzz', - '-i', - input_corpus, - '-o', - output_corpus, - # Use no memory limit as ASAN doesn't play nicely with one. - '-m', - 'none', - '-t', - '1000+', # Use same default 1 sec timeout, but add '+' to skip hangs. - ] - # Use '-d' to skip deterministic mode, as long as it it compatible with - # additional flags. - if not additional_flags or check_skip_det_compatible(additional_flags): - command.append('-d') - if additional_flags: - command.extend(additional_flags) - dictionary_path = utils.get_dictionary_path(target_binary) - if dictionary_path: - command.extend(['-x', dictionary_path]) - command += [ - '--', - target_binary, - # Pass INT_MAX to afl the maximize the number of persistent loops it - # performs. - '2147483647' - ] - 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/afl_no_favored/fuzzer.py b/fuzzers/afl_no_favored/fuzzer.py deleted file mode 100755 index 90c7a08ab..000000000 --- a/fuzzers/afl_no_favored/fuzzer.py +++ /dev/null @@ -1,140 +0,0 @@ -# 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 AFL fuzzer.""" - -import json -import os -import shutil -import subprocess - -from fuzzers import utils - - -def prepare_build_environment(): - """Set environment variables used to build targets for AFL-based - fuzzers.""" - cflags = ['-fsanitize-coverage=trace-pc-guard'] - utils.append_flags('CFLAGS', cflags) - utils.append_flags('CXXFLAGS', cflags) - - os.environ['CC'] = 'clang' - os.environ['CXX'] = 'clang++' - os.environ['FUZZER_LIB'] = '/libAFL.a' - - -def build(): - """Build benchmark.""" - prepare_build_environment() - - utils.build_benchmark() - - print('[post_build] Copying afl-fuzz to $OUT directory') - # Copy out the afl-fuzz binary as a build artifact. - shutil.copy('/afl/afl-fuzz', os.environ['OUT']) - - -def get_stats(output_corpus, fuzzer_log): # pylint: disable=unused-argument - """Gets fuzzer stats for AFL.""" - # Get a dictionary containing the stats AFL reports. - stats_file = os.path.join(output_corpus, 'fuzzer_stats') - with open(stats_file, encoding='utf-8') as file_handle: - stats_file_lines = file_handle.read().splitlines() - stats_file_dict = {} - for stats_line in stats_file_lines: - key, value = stats_line.split(': ') - stats_file_dict[key.strip()] = value.strip() - - # Report to FuzzBench the stats it accepts. - stats = {'execs_per_sec': float(stats_file_dict['execs_per_sec'])} - return json.dumps(stats) - - -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' - # Disables AFL corpus culling - os.environ['AFL_NO_FAVORED'] = '1' - - # AFL needs at least one non-empty seed to start. - utils.create_seed_file_for_empty_corpus(input_corpus) - - -def check_skip_det_compatible(additional_flags): - """ Checks if additional flags are compatible with '-d' option""" - # AFL refuses to take in '-d' with '-M' or '-S' options for parallel mode. - # (cf. https://github.com/google/AFL/blob/8da80951/afl-fuzz.c#L7477) - if '-M' in additional_flags or '-S' in additional_flags: - return False - return True - - -def run_afl_fuzz(input_corpus, - output_corpus, - target_binary, - additional_flags=None, - hide_output=False): - """Run afl-fuzz.""" - # Spawn the afl fuzzing process. - print('[run_afl_fuzz] Running target with afl-fuzz') - command = [ - './afl-fuzz', - '-i', - input_corpus, - '-o', - output_corpus, - # Use no memory limit as ASAN doesn't play nicely with one. - '-m', - 'none', - '-t', - '1000+', # Use same default 1 sec timeout, but add '+' to skip hangs. - ] - # Use '-d' to skip deterministic mode, as long as it it compatible with - # additional flags. - if not additional_flags or check_skip_det_compatible(additional_flags): - command.append('-d') - if additional_flags: - command.extend(additional_flags) - dictionary_path = utils.get_dictionary_path(target_binary) - if dictionary_path: - command.extend(['-x', dictionary_path]) - command += [ - '--', - target_binary, - # Pass INT_MAX to afl the maximize the number of persistent loops it - # performs. - '2147483647' - ] - 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/afl_no_trim/fuzzer.py b/fuzzers/afl_no_trim/fuzzer.py deleted file mode 100755 index 7430d9316..000000000 --- a/fuzzers/afl_no_trim/fuzzer.py +++ /dev/null @@ -1,140 +0,0 @@ -# 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 AFL fuzzer.""" - -import json -import os -import shutil -import subprocess - -from fuzzers import utils - - -def prepare_build_environment(): - """Set environment variables used to build targets for AFL-based - fuzzers.""" - cflags = ['-fsanitize-coverage=trace-pc-guard'] - utils.append_flags('CFLAGS', cflags) - utils.append_flags('CXXFLAGS', cflags) - - os.environ['CC'] = 'clang' - os.environ['CXX'] = 'clang++' - os.environ['FUZZER_LIB'] = '/libAFL.a' - - -def build(): - """Build benchmark.""" - prepare_build_environment() - - utils.build_benchmark() - - print('[post_build] Copying afl-fuzz to $OUT directory') - # Copy out the afl-fuzz binary as a build artifact. - shutil.copy('/afl/afl-fuzz', os.environ['OUT']) - - -def get_stats(output_corpus, fuzzer_log): # pylint: disable=unused-argument - """Gets fuzzer stats for AFL.""" - # Get a dictionary containing the stats AFL reports. - stats_file = os.path.join(output_corpus, 'fuzzer_stats') - with open(stats_file, encoding='utf-8') as file_handle: - stats_file_lines = file_handle.read().splitlines() - stats_file_dict = {} - for stats_line in stats_file_lines: - key, value = stats_line.split(': ') - stats_file_dict[key.strip()] = value.strip() - - # Report to FuzzBench the stats it accepts. - stats = {'execs_per_sec': float(stats_file_dict['execs_per_sec'])} - return json.dumps(stats) - - -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' - # Disables AFL testcase trimming - os.environ['AFL_DISABLE_TRIM'] = '1' - - # AFL needs at least one non-empty seed to start. - utils.create_seed_file_for_empty_corpus(input_corpus) - - -def check_skip_det_compatible(additional_flags): - """ Checks if additional flags are compatible with '-d' option""" - # AFL refuses to take in '-d' with '-M' or '-S' options for parallel mode. - # (cf. https://github.com/google/AFL/blob/8da80951/afl-fuzz.c#L7477) - if '-M' in additional_flags or '-S' in additional_flags: - return False - return True - - -def run_afl_fuzz(input_corpus, - output_corpus, - target_binary, - additional_flags=None, - hide_output=False): - """Run afl-fuzz.""" - # Spawn the afl fuzzing process. - print('[run_afl_fuzz] Running target with afl-fuzz') - command = [ - './afl-fuzz', - '-i', - input_corpus, - '-o', - output_corpus, - # Use no memory limit as ASAN doesn't play nicely with one. - '-m', - 'none', - '-t', - '1000+', # Use same default 1 sec timeout, but add '+' to skip hangs. - ] - # Use '-d' to skip deterministic mode, as long as it it compatible with - # additional flags. - if not additional_flags or check_skip_det_compatible(additional_flags): - command.append('-d') - if additional_flags: - command.extend(additional_flags) - dictionary_path = utils.get_dictionary_path(target_binary) - if dictionary_path: - command.extend(['-x', dictionary_path]) - command += [ - '--', - target_binary, - # Pass INT_MAX to afl the maximize the number of persistent loops it - # performs. - '2147483647' - ] - 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/afl_scheduling_lifo/fuzzer.py b/fuzzers/afl_scheduling_lifo/fuzzer.py deleted file mode 100755 index 328b3b718..000000000 --- a/fuzzers/afl_scheduling_lifo/fuzzer.py +++ /dev/null @@ -1,140 +0,0 @@ -# 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 AFL fuzzer.""" - -import json -import os -import shutil -import subprocess - -from fuzzers import utils - - -def prepare_build_environment(): - """Set environment variables used to build targets for AFL-based - fuzzers.""" - cflags = ['-fsanitize-coverage=trace-pc-guard'] - utils.append_flags('CFLAGS', cflags) - utils.append_flags('CXXFLAGS', cflags) - - os.environ['CC'] = 'clang' - os.environ['CXX'] = 'clang++' - os.environ['FUZZER_LIB'] = '/libAFL.a' - - -def build(): - """Build benchmark.""" - prepare_build_environment() - - utils.build_benchmark() - - print('[post_build] Copying afl-fuzz to $OUT directory') - # Copy out the afl-fuzz binary as a build artifact. - shutil.copy('/afl/afl-fuzz', os.environ['OUT']) - - -def get_stats(output_corpus, fuzzer_log): # pylint: disable=unused-argument - """Gets fuzzer stats for AFL.""" - # Get a dictionary containing the stats AFL reports. - stats_file = os.path.join(output_corpus, 'fuzzer_stats') - with open(stats_file, encoding='utf-8') as file_handle: - stats_file_lines = file_handle.read().splitlines() - stats_file_dict = {} - for stats_line in stats_file_lines: - key, value = stats_line.split(': ') - stats_file_dict[key.strip()] = value.strip() - - # Report to FuzzBench the stats it accepts. - stats = {'execs_per_sec': float(stats_file_dict['execs_per_sec'])} - return json.dumps(stats) - - -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' - # Sets corpus scheduling with LIFO policy - os.environ['AFL_LIFO_CORPUS'] = '1' - - # AFL needs at least one non-empty seed to start. - utils.create_seed_file_for_empty_corpus(input_corpus) - - -def check_skip_det_compatible(additional_flags): - """ Checks if additional flags are compatible with '-d' option""" - # AFL refuses to take in '-d' with '-M' or '-S' options for parallel mode. - # (cf. https://github.com/google/AFL/blob/8da80951/afl-fuzz.c#L7477) - if '-M' in additional_flags or '-S' in additional_flags: - return False - return True - - -def run_afl_fuzz(input_corpus, - output_corpus, - target_binary, - additional_flags=None, - hide_output=False): - """Run afl-fuzz.""" - # Spawn the afl fuzzing process. - print('[run_afl_fuzz] Running target with afl-fuzz') - command = [ - './afl-fuzz', - '-i', - input_corpus, - '-o', - output_corpus, - # Use no memory limit as ASAN doesn't play nicely with one. - '-m', - 'none', - '-t', - '1000+', # Use same default 1 sec timeout, but add '+' to skip hangs. - ] - # Use '-d' to skip deterministic mode, as long as it it compatible with - # additional flags. - if not additional_flags or check_skip_det_compatible(additional_flags): - command.append('-d') - if additional_flags: - command.extend(additional_flags) - dictionary_path = utils.get_dictionary_path(target_binary) - if dictionary_path: - command.extend(['-x', dictionary_path]) - command += [ - '--', - target_binary, - # Pass INT_MAX to afl the maximize the number of persistent loops it - # performs. - '2147483647' - ] - 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/afl_scheduling_random/fuzzer.py b/fuzzers/afl_scheduling_random/fuzzer.py deleted file mode 100755 index af9ebc313..000000000 --- a/fuzzers/afl_scheduling_random/fuzzer.py +++ /dev/null @@ -1,140 +0,0 @@ -# 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 AFL fuzzer.""" - -import json -import os -import shutil -import subprocess - -from fuzzers import utils - - -def prepare_build_environment(): - """Set environment variables used to build targets for AFL-based - fuzzers.""" - cflags = ['-fsanitize-coverage=trace-pc-guard'] - utils.append_flags('CFLAGS', cflags) - utils.append_flags('CXXFLAGS', cflags) - - os.environ['CC'] = 'clang' - os.environ['CXX'] = 'clang++' - os.environ['FUZZER_LIB'] = '/libAFL.a' - - -def build(): - """Build benchmark.""" - prepare_build_environment() - - utils.build_benchmark() - - print('[post_build] Copying afl-fuzz to $OUT directory') - # Copy out the afl-fuzz binary as a build artifact. - shutil.copy('/afl/afl-fuzz', os.environ['OUT']) - - -def get_stats(output_corpus, fuzzer_log): # pylint: disable=unused-argument - """Gets fuzzer stats for AFL.""" - # Get a dictionary containing the stats AFL reports. - stats_file = os.path.join(output_corpus, 'fuzzer_stats') - with open(stats_file, encoding='utf-8') as file_handle: - stats_file_lines = file_handle.read().splitlines() - stats_file_dict = {} - for stats_line in stats_file_lines: - key, value = stats_line.split(': ') - stats_file_dict[key.strip()] = value.strip() - - # Report to FuzzBench the stats it accepts. - stats = {'execs_per_sec': float(stats_file_dict['execs_per_sec'])} - return json.dumps(stats) - - -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' - # Sets AFL to use a random selection for the corpus scheduling - os.environ['AFL_RANDOMIC_CORPUS'] = '1' - - # AFL needs at least one non-empty seed to start. - utils.create_seed_file_for_empty_corpus(input_corpus) - - -def check_skip_det_compatible(additional_flags): - """ Checks if additional flags are compatible with '-d' option""" - # AFL refuses to take in '-d' with '-M' or '-S' options for parallel mode. - # (cf. https://github.com/google/AFL/blob/8da80951/afl-fuzz.c#L7477) - if '-M' in additional_flags or '-S' in additional_flags: - return False - return True - - -def run_afl_fuzz(input_corpus, - output_corpus, - target_binary, - additional_flags=None, - hide_output=False): - """Run afl-fuzz.""" - # Spawn the afl fuzzing process. - print('[run_afl_fuzz] Running target with afl-fuzz') - command = [ - './afl-fuzz', - '-i', - input_corpus, - '-o', - output_corpus, - # Use no memory limit as ASAN doesn't play nicely with one. - '-m', - 'none', - '-t', - '1000+', # Use same default 1 sec timeout, but add '+' to skip hangs. - ] - # Use '-d' to skip deterministic mode, as long as it it compatible with - # additional flags. - if not additional_flags or check_skip_det_compatible(additional_flags): - command.append('-d') - if additional_flags: - command.extend(additional_flags) - dictionary_path = utils.get_dictionary_path(target_binary) - if dictionary_path: - command.extend(['-x', dictionary_path]) - command += [ - '--', - target_binary, - # Pass INT_MAX to afl the maximize the number of persistent loops it - # performs. - '2147483647' - ] - 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/afl_score_max/fuzzer.py b/fuzzers/afl_score_max/fuzzer.py deleted file mode 100755 index 58b8860f4..000000000 --- a/fuzzers/afl_score_max/fuzzer.py +++ /dev/null @@ -1,140 +0,0 @@ -# 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 AFL fuzzer.""" - -import json -import os -import shutil -import subprocess - -from fuzzers import utils - - -def prepare_build_environment(): - """Set environment variables used to build targets for AFL-based - fuzzers.""" - cflags = ['-fsanitize-coverage=trace-pc-guard'] - utils.append_flags('CFLAGS', cflags) - utils.append_flags('CXXFLAGS', cflags) - - os.environ['CC'] = 'clang' - os.environ['CXX'] = 'clang++' - os.environ['FUZZER_LIB'] = '/libAFL.a' - - -def build(): - """Build benchmark.""" - prepare_build_environment() - - utils.build_benchmark() - - print('[post_build] Copying afl-fuzz to $OUT directory') - # Copy out the afl-fuzz binary as a build artifact. - shutil.copy('/afl/afl-fuzz', os.environ['OUT']) - - -def get_stats(output_corpus, fuzzer_log): # pylint: disable=unused-argument - """Gets fuzzer stats for AFL.""" - # Get a dictionary containing the stats AFL reports. - stats_file = os.path.join(output_corpus, 'fuzzer_stats') - with open(stats_file, encoding='utf-8') as file_handle: - stats_file_lines = file_handle.read().splitlines() - stats_file_dict = {} - for stats_line in stats_file_lines: - key, value = stats_line.split(': ') - stats_file_dict[key.strip()] = value.strip() - - # Report to FuzzBench the stats it accepts. - stats = {'execs_per_sec': float(stats_file_dict['execs_per_sec'])} - return json.dumps(stats) - - -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' - # Maximize the score - os.environ['AFL_MAX_ENERGY'] = '1' - - # AFL needs at least one non-empty seed to start. - utils.create_seed_file_for_empty_corpus(input_corpus) - - -def check_skip_det_compatible(additional_flags): - """ Checks if additional flags are compatible with '-d' option""" - # AFL refuses to take in '-d' with '-M' or '-S' options for parallel mode. - # (cf. https://github.com/google/AFL/blob/8da80951/afl-fuzz.c#L7477) - if '-M' in additional_flags or '-S' in additional_flags: - return False - return True - - -def run_afl_fuzz(input_corpus, - output_corpus, - target_binary, - additional_flags=None, - hide_output=False): - """Run afl-fuzz.""" - # Spawn the afl fuzzing process. - print('[run_afl_fuzz] Running target with afl-fuzz') - command = [ - './afl-fuzz', - '-i', - input_corpus, - '-o', - output_corpus, - # Use no memory limit as ASAN doesn't play nicely with one. - '-m', - 'none', - '-t', - '1000+', # Use same default 1 sec timeout, but add '+' to skip hangs. - ] - # Use '-d' to skip deterministic mode, as long as it it compatible with - # additional flags. - if not additional_flags or check_skip_det_compatible(additional_flags): - command.append('-d') - if additional_flags: - command.extend(additional_flags) - dictionary_path = utils.get_dictionary_path(target_binary) - if dictionary_path: - command.extend(['-x', dictionary_path]) - command += [ - '--', - target_binary, - # Pass INT_MAX to afl the maximize the number of persistent loops it - # performs. - '2147483647' - ] - 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/afl_score_min/fuzzer.py b/fuzzers/afl_score_min/fuzzer.py deleted file mode 100755 index e0ec33354..000000000 --- a/fuzzers/afl_score_min/fuzzer.py +++ /dev/null @@ -1,140 +0,0 @@ -# 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 AFL fuzzer.""" - -import json -import os -import shutil -import subprocess - -from fuzzers import utils - - -def prepare_build_environment(): - """Set environment variables used to build targets for AFL-based - fuzzers.""" - cflags = ['-fsanitize-coverage=trace-pc-guard'] - utils.append_flags('CFLAGS', cflags) - utils.append_flags('CXXFLAGS', cflags) - - os.environ['CC'] = 'clang' - os.environ['CXX'] = 'clang++' - os.environ['FUZZER_LIB'] = '/libAFL.a' - - -def build(): - """Build benchmark.""" - prepare_build_environment() - - utils.build_benchmark() - - print('[post_build] Copying afl-fuzz to $OUT directory') - # Copy out the afl-fuzz binary as a build artifact. - shutil.copy('/afl/afl-fuzz', os.environ['OUT']) - - -def get_stats(output_corpus, fuzzer_log): # pylint: disable=unused-argument - """Gets fuzzer stats for AFL.""" - # Get a dictionary containing the stats AFL reports. - stats_file = os.path.join(output_corpus, 'fuzzer_stats') - with open(stats_file, encoding='utf-8') as file_handle: - stats_file_lines = file_handle.read().splitlines() - stats_file_dict = {} - for stats_line in stats_file_lines: - key, value = stats_line.split(': ') - stats_file_dict[key.strip()] = value.strip() - - # Report to FuzzBench the stats it accepts. - stats = {'execs_per_sec': float(stats_file_dict['execs_per_sec'])} - return json.dumps(stats) - - -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' - # Sets AFL minimum score - os.environ['AFL_MIN_ENERGY'] = '1' - - # AFL needs at least one non-empty seed to start. - utils.create_seed_file_for_empty_corpus(input_corpus) - - -def check_skip_det_compatible(additional_flags): - """ Checks if additional flags are compatible with '-d' option""" - # AFL refuses to take in '-d' with '-M' or '-S' options for parallel mode. - # (cf. https://github.com/google/AFL/blob/8da80951/afl-fuzz.c#L7477) - if '-M' in additional_flags or '-S' in additional_flags: - return False - return True - - -def run_afl_fuzz(input_corpus, - output_corpus, - target_binary, - additional_flags=None, - hide_output=False): - """Run afl-fuzz.""" - # Spawn the afl fuzzing process. - print('[run_afl_fuzz] Running target with afl-fuzz') - command = [ - './afl-fuzz', - '-i', - input_corpus, - '-o', - output_corpus, - # Use no memory limit as ASAN doesn't play nicely with one. - '-m', - 'none', - '-t', - '1000+', # Use same default 1 sec timeout, but add '+' to skip hangs. - ] - # Use '-d' to skip deterministic mode, as long as it it compatible with - # additional flags. - if not additional_flags or check_skip_det_compatible(additional_flags): - command.append('-d') - if additional_flags: - command.extend(additional_flags) - dictionary_path = utils.get_dictionary_path(target_binary) - if dictionary_path: - command.extend(['-x', dictionary_path]) - command += [ - '--', - target_binary, - # Pass INT_MAX to afl the maximize the number of persistent loops it - # performs. - '2147483647' - ] - 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/afl_score_no_novel_prioritization/fuzzer.py b/fuzzers/afl_score_no_novel_prioritization/fuzzer.py deleted file mode 100755 index ab296b70a..000000000 --- a/fuzzers/afl_score_no_novel_prioritization/fuzzer.py +++ /dev/null @@ -1,140 +0,0 @@ -# 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 AFL fuzzer.""" - -import json -import os -import shutil -import subprocess - -from fuzzers import utils - - -def prepare_build_environment(): - """Set environment variables used to build targets for AFL-based - fuzzers.""" - cflags = ['-fsanitize-coverage=trace-pc-guard'] - utils.append_flags('CFLAGS', cflags) - utils.append_flags('CXXFLAGS', cflags) - - os.environ['CC'] = 'clang' - os.environ['CXX'] = 'clang++' - os.environ['FUZZER_LIB'] = '/libAFL.a' - - -def build(): - """Build benchmark.""" - prepare_build_environment() - - utils.build_benchmark() - - print('[post_build] Copying afl-fuzz to $OUT directory') - # Copy out the afl-fuzz binary as a build artifact. - shutil.copy('/afl/afl-fuzz', os.environ['OUT']) - - -def get_stats(output_corpus, fuzzer_log): # pylint: disable=unused-argument - """Gets fuzzer stats for AFL.""" - # Get a dictionary containing the stats AFL reports. - stats_file = os.path.join(output_corpus, 'fuzzer_stats') - with open(stats_file, encoding='utf-8') as file_handle: - stats_file_lines = file_handle.read().splitlines() - stats_file_dict = {} - for stats_line in stats_file_lines: - key, value = stats_line.split(': ') - stats_file_dict[key.strip()] = value.strip() - - # Report to FuzzBench the stats it accepts. - stats = {'execs_per_sec': float(stats_file_dict['execs_per_sec'])} - return json.dumps(stats) - - -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' - # Disable handicap - os.environ['AFL_DISABLE_HANDICAP'] = '1' - - # AFL needs at least one non-empty seed to start. - utils.create_seed_file_for_empty_corpus(input_corpus) - - -def check_skip_det_compatible(additional_flags): - """ Checks if additional flags are compatible with '-d' option""" - # AFL refuses to take in '-d' with '-M' or '-S' options for parallel mode. - # (cf. https://github.com/google/AFL/blob/8da80951/afl-fuzz.c#L7477) - if '-M' in additional_flags or '-S' in additional_flags: - return False - return True - - -def run_afl_fuzz(input_corpus, - output_corpus, - target_binary, - additional_flags=None, - hide_output=False): - """Run afl-fuzz.""" - # Spawn the afl fuzzing process. - print('[run_afl_fuzz] Running target with afl-fuzz') - command = [ - './afl-fuzz', - '-i', - input_corpus, - '-o', - output_corpus, - # Use no memory limit as ASAN doesn't play nicely with one. - '-m', - 'none', - '-t', - '1000+', # Use same default 1 sec timeout, but add '+' to skip hangs. - ] - # Use '-d' to skip deterministic mode, as long as it it compatible with - # additional flags. - if not additional_flags or check_skip_det_compatible(additional_flags): - command.append('-d') - if additional_flags: - command.extend(additional_flags) - dictionary_path = utils.get_dictionary_path(target_binary) - if dictionary_path: - command.extend(['-x', dictionary_path]) - command += [ - '--', - target_binary, - # Pass INT_MAX to afl the maximize the number of persistent loops it - # performs. - '2147483647' - ] - 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/afl_score_random/fuzzer.py b/fuzzers/afl_score_random/fuzzer.py deleted file mode 100755 index d951d749f..000000000 --- a/fuzzers/afl_score_random/fuzzer.py +++ /dev/null @@ -1,140 +0,0 @@ -# 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 AFL fuzzer.""" - -import json -import os -import shutil -import subprocess - -from fuzzers import utils - - -def prepare_build_environment(): - """Set environment variables used to build targets for AFL-based - fuzzers.""" - cflags = ['-fsanitize-coverage=trace-pc-guard'] - utils.append_flags('CFLAGS', cflags) - utils.append_flags('CXXFLAGS', cflags) - - os.environ['CC'] = 'clang' - os.environ['CXX'] = 'clang++' - os.environ['FUZZER_LIB'] = '/libAFL.a' - - -def build(): - """Build benchmark.""" - prepare_build_environment() - - utils.build_benchmark() - - print('[post_build] Copying afl-fuzz to $OUT directory') - # Copy out the afl-fuzz binary as a build artifact. - shutil.copy('/afl/afl-fuzz', os.environ['OUT']) - - -def get_stats(output_corpus, fuzzer_log): # pylint: disable=unused-argument - """Gets fuzzer stats for AFL.""" - # Get a dictionary containing the stats AFL reports. - stats_file = os.path.join(output_corpus, 'fuzzer_stats') - with open(stats_file, encoding='utf-8') as file_handle: - stats_file_lines = file_handle.read().splitlines() - stats_file_dict = {} - for stats_line in stats_file_lines: - key, value = stats_line.split(': ') - stats_file_dict[key.strip()] = value.strip() - - # Report to FuzzBench the stats it accepts. - stats = {'execs_per_sec': float(stats_file_dict['execs_per_sec'])} - return json.dumps(stats) - - -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' - # Sets AFL score to random constant - os.environ['AFL_RANDOM_ENERGY'] = '1' - - # AFL needs at least one non-empty seed to start. - utils.create_seed_file_for_empty_corpus(input_corpus) - - -def check_skip_det_compatible(additional_flags): - """ Checks if additional flags are compatible with '-d' option""" - # AFL refuses to take in '-d' with '-M' or '-S' options for parallel mode. - # (cf. https://github.com/google/AFL/blob/8da80951/afl-fuzz.c#L7477) - if '-M' in additional_flags or '-S' in additional_flags: - return False - return True - - -def run_afl_fuzz(input_corpus, - output_corpus, - target_binary, - additional_flags=None, - hide_output=False): - """Run afl-fuzz.""" - # Spawn the afl fuzzing process. - print('[run_afl_fuzz] Running target with afl-fuzz') - command = [ - './afl-fuzz', - '-i', - input_corpus, - '-o', - output_corpus, - # Use no memory limit as ASAN doesn't play nicely with one. - '-m', - 'none', - '-t', - '1000+', # Use same default 1 sec timeout, but add '+' to skip hangs. - ] - # Use '-d' to skip deterministic mode, as long as it it compatible with - # additional flags. - if not additional_flags or check_skip_det_compatible(additional_flags): - command.append('-d') - if additional_flags: - command.extend(additional_flags) - dictionary_path = utils.get_dictionary_path(target_binary) - if dictionary_path: - command.extend(['-x', dictionary_path]) - command += [ - '--', - target_binary, - # Pass INT_MAX to afl the maximize the number of persistent loops it - # performs. - '2147483647' - ] - 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/afl_splicing_mutation/fuzzer.py b/fuzzers/afl_splicing_mutation/fuzzer.py deleted file mode 100755 index 7c4c44180..000000000 --- a/fuzzers/afl_splicing_mutation/fuzzer.py +++ /dev/null @@ -1,138 +0,0 @@ -# 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 AFL fuzzer.""" - -import json -import os -import shutil -import subprocess - -from fuzzers import utils - - -def prepare_build_environment(): - """Set environment variables used to build targets for AFL-based - fuzzers.""" - cflags = ['-fsanitize-coverage=trace-pc-guard'] - utils.append_flags('CFLAGS', cflags) - utils.append_flags('CXXFLAGS', cflags) - - os.environ['CC'] = 'clang' - os.environ['CXX'] = 'clang++' - os.environ['FUZZER_LIB'] = '/libAFL.a' - - -def build(): - """Build benchmark.""" - prepare_build_environment() - - utils.build_benchmark() - - print('[post_build] Copying afl-fuzz to $OUT directory') - # Copy out the afl-fuzz binary as a build artifact. - shutil.copy('/afl/afl-fuzz', os.environ['OUT']) - - -def get_stats(output_corpus, fuzzer_log): # pylint: disable=unused-argument - """Gets fuzzer stats for AFL.""" - # Get a dictionary containing the stats AFL reports. - stats_file = os.path.join(output_corpus, 'fuzzer_stats') - with open(stats_file, encoding='utf-8') as file_handle: - stats_file_lines = file_handle.read().splitlines() - stats_file_dict = {} - for stats_line in stats_file_lines: - key, value = stats_line.split(': ') - stats_file_dict[key.strip()] = value.strip() - - # Report to FuzzBench the stats it accepts. - stats = {'execs_per_sec': float(stats_file_dict['execs_per_sec'])} - return json.dumps(stats) - - -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' - - # AFL needs at least one non-empty seed to start. - utils.create_seed_file_for_empty_corpus(input_corpus) - - -def check_skip_det_compatible(additional_flags): - """ Checks if additional flags are compatible with '-d' option""" - # AFL refuses to take in '-d' with '-M' or '-S' options for parallel mode. - # (cf. https://github.com/google/AFL/blob/8da80951/afl-fuzz.c#L7477) - if '-M' in additional_flags or '-S' in additional_flags: - return False - return True - - -def run_afl_fuzz(input_corpus, - output_corpus, - target_binary, - additional_flags=None, - hide_output=False): - """Run afl-fuzz.""" - # Spawn the afl fuzzing process. - print('[run_afl_fuzz] Running target with afl-fuzz') - command = [ - './afl-fuzz', - '-i', - input_corpus, - '-o', - output_corpus, - # Use no memory limit as ASAN doesn't play nicely with one. - '-m', - 'none', - '-t', - '1000+', # Use same default 1 sec timeout, but add '+' to skip hangs. - ] - # Use '-d' to skip deterministic mode, as long as it it compatible with - # additional flags. - if not additional_flags or check_skip_det_compatible(additional_flags): - command.append('-d') - if additional_flags: - command.extend(additional_flags) - dictionary_path = utils.get_dictionary_path(target_binary) - if dictionary_path: - command.extend(['-x', dictionary_path]) - command += [ - '--', - target_binary, - # Pass INT_MAX to afl the maximize the number of persistent loops it - # performs. - '2147483647' - ] - 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/libafl_forkserver/builder.Dockerfile b/fuzzers/libafl_forkserver/builder.Dockerfile new file mode 100644 index 000000000..4121c94e4 --- /dev/null +++ b/fuzzers/libafl_forkserver/builder.Dockerfile @@ -0,0 +1,56 @@ +# 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 + +# Install dependencies. +RUN apt-get update && \ + apt-get install -y build-essential libstdc++5 libtool-bin automake flex \ + bison libglib2.0-dev python3-setuptools unzip python3-dev joe curl \ + cmake git apt-utils apt-transport-https ca-certificates libdbus-1-dev + +# 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 && \ + rm /rustup.sh + +# Download afl++. +RUN git clone https://github.com/AFLplusplus/AFLplusplus /afl + +# Checkout a current commit +RUN cd /afl && git checkout 8cdc48f73a17ddd557897f2098937a8ba3bfe184 + +# Build without Python support as we don't need it. +# Set AFL_NO_X86 to skip flaky tests. +RUN cd /afl && \ + unset CFLAGS CXXFLAGS && \ + export CC=clang AFL_NO_X86=1 && \ + PYTHON_INCLUDE=/ make && \ + make install && \ + cp utils/aflpp_driver/libAFLDriver.a / + +# Download libafl. +RUN git clone https://github.com/AFLplusplus/LibAFL /libafl + +# Checkout a current commit +RUN cd /libafl && git checkout 664e87809e6005f1814df1b55a345e7b2247f15b + +# Compile libafl. +RUN cd /libafl && \ + unset CFLAGS CXXFLAGS && \ + cd ./fuzzers/fuzzbench_forkserver && \ + PATH="/root/.cargo/bin/:$PATH" cargo build --release + diff --git a/fuzzers/libafl_forkserver/description.md b/fuzzers/libafl_forkserver/description.md new file mode 100644 index 000000000..445a27663 --- /dev/null +++ b/fuzzers/libafl_forkserver/description.md @@ -0,0 +1,13 @@ +# aflplusplus + +AFL++ fuzzer instance that has the following config active for all benchmarks: + - PCGUARD instrumentation + - cmplog feature + - "fast" power schedule + - persistent mode + shared memory test cases + +Repository: [https://github.com/AFLplusplus/AFLplusplus/](https://github.com/AFLplusplus/AFLplusplus/) + +[builder.Dockerfile](builder.Dockerfile) +[fuzzer.py](fuzzer.py) +[runner.Dockerfile](runner.Dockerfile) diff --git a/fuzzers/libafl_forkserver/fuzzer.py b/fuzzers/libafl_forkserver/fuzzer.py new file mode 100755 index 000000000..c8b66976f --- /dev/null +++ b/fuzzers/libafl_forkserver/fuzzer.py @@ -0,0 +1,67 @@ +# 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 fuzzer with an AFL++ forkserver.""" + +import os +import shutil +import subprocess + +from fuzzers import utils +from fuzzers.aflplusplus import fuzzer as aflplusplus_fuzzer +from fuzzers.libafl import fuzzer as libafl_fuzzer + + +def build(): + """Build benchmark.""" + # Build the target with AFL++ + aflplusplus_fuzzer.build('tracepc', 'cmplog', 'dict2file') + + # Copy to fuzzer to OUT + build_directory = os.environ['OUT'] + fuzzer = '/libafl/fuzzers/fuzzbench_forkserver/' \ + 'target/release/fuzzbench_forkserver' + shutil.copy(fuzzer, build_directory) + + +def fuzz(input_corpus, output_corpus, target_binary): + """Run fuzzer.""" + # Calculate CmpLog binary path from the instrumented target binary. + target_binary_directory = os.path.dirname(target_binary) + cmplog_target_binary_directory = \ + aflplusplus_fuzzer.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) + + # Setup env vars + libafl_fuzzer.prepare_fuzz_environment(input_corpus) + + # Merge dictionaries + dictionary_path = utils.get_dictionary_path(target_binary) + if os.path.exists('./afl++.dict'): + if dictionary_path: + with open('./afl++.dict', encoding='utf-8') as dictfile: + autodict = dictfile.read() + with open(dictionary_path, 'a', encoding='utf-8') as dictfile: + dictfile.write(autodict) + else: + dictionary_path = './afl++.dict' + + # Run the fuzzer + command = ['./fuzzbench_forkserver', '-c', cmplog_target_binary] + if dictionary_path: + command += (['-x', dictionary_path]) + command += (['-o', output_corpus, '-i', input_corpus, target_binary]) + print(command) + subprocess.check_call(command) diff --git a/fuzzers/libafl_forkserver/runner.Dockerfile b/fuzzers/libafl_forkserver/runner.Dockerfile new file mode 100644 index 000000000..7aa1da8e4 --- /dev/null +++ b/fuzzers/libafl_forkserver/runner.Dockerfile @@ -0,0 +1,23 @@ +# 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 diff --git a/service/experiment-requests.yaml b/service/experiment-requests.yaml index d12fa2da2..3680bd5f6 100644 --- a/service/experiment-requests.yaml +++ b/service/experiment-requests.yaml @@ -20,6 +20,16 @@ # Please add new experiment requests towards the top of this file. # +- experiment: 2023-01-05-libafl + description: "Test the LibAFL forkserver" + type: bug + fuzzers: + - aflplusplus + - entropic + - libfuzzer + - honggfuzz + - libafl + - libafl_forkserver - experiment: 2023-01-10-aflpp description: "Test if the previous aflpp build failure is flaky."