Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

infra: add support for non-persistent mode AFL #7343

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions infra/base-images/base-runner/run_fuzzer
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ if [[ "$FUZZING_ENGINE" = afl ]]; then

CMD_LINE="$OUT/afl-fuzz $AFL_FUZZER_ARGS -i $CORPUS_DIR -o $FUZZER_OUT $(get_dictionary) $* -- $OUT/$FUZZER"

if [[ "$FUZZER" == *"non_persistent"* ]]; then
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe put a TODO here to reference an issue for a long term solution to identifying non-persistent AFL fuzz targets.

@vanhauser-thc Do you have an ideas about how we can identify if a fuzz target uses persistent mode or not?
We can't just look for __afl_manual_init can we?
Note that LLVMFuzzerTestOneInput will also be in the binary so that the rest of the infra can identify it as a fuzz target.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, can you change this to TODO(https://github.com/google/oss-fuzz/issues/7347):...?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the AFL way is to check for the string ##SIG_AFL_PERSISTENT## in the binary. if that is present, then it is persistent.
for deferred forkserver it is ##SIG_AFL_DEFER_FORKSRV##
note that you can have the forkserver (well you should have one, better performance) without persistent mode - and vice versa.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note that you can have the forkserver (well you should have one, better performance) without persistent mode - and vice versa.

Interesting -- is this by setting N here to 1 https://github.com/AFLplusplus/AFLplusplus/blob/1d4f1e48797c064ee71441ba555b29fc3f467983/utils/aflpp_driver/aflpp_driver.c#L336 using this logic https://github.com/AFLplusplus/AFLplusplus/blob/1d4f1e48797c064ee71441ba555b29fc3f467983/utils/aflpp_driver/aflpp_driver.c#L306 ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no.
if you use the aflpp driver you automatically have persistent mode. (and a deferred forkserver).
for non-persistent mode you dont need to (and you should not) use aflppdriver

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey David can you implement a solution based on Marc's feedback.
Basically check if the binary doesn't contain ##SIG_AFL_PERSISTENT## and then treat it as non-persistent.

CMD_LINE="$CMD_LINE @@"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are all non-persistent targets called like this: ./target inputfile? without any other command line options? If not maybe this needs a `target.nonpersistent" config file that defines how the target is to be called.
and note that afl++ can also send on stdin

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah exactly, I'm going to make an API for doing this in the .options file we already support.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we always add the @@ here? That way we don't need to scan the binary, oss fuzz doesn't have to care

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a) because otherwise it is not needed, b) I am not sure if the current commit on oss-fuzz of afl++ is one that works fine, or is an older one that has that strong performance decrease otherwise. I want to push an update, but not before next week.

Copy link

@domenukk domenukk Nov 9, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood.
I'm just saying, not having to grep through a potentially Chrome-sized binary vs adding an needless commandline flag may be worth it
Of course only makes sense if the target still works then (latest AFL++ version). Maybe keep it in mind :)

fi

echo afl++ setup:
env|grep AFL_
cat "$OUT/afl_options.txt"
Expand Down
16 changes: 15 additions & 1 deletion projects/binutils/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,20 @@ done
#
# Compile fuzzers
#
# compile non-persistent fuzzers
if [ "$SANITIZER" != "coverage" ]
then
$CC $CFLAGS -DHAVE_CONFIG_H -DOBJDUMP_PRIVATE_VECTORS="" -I. -I../bfd -I./../bfd -I./../include \
-I./../zlib -DLOCALEDIR="\"/usr/local/share/locale\"" \
-Dbin_dummy_emulation=bin_vanilla_emulation -W -Wall -MT \
fuzz_readelf_non_persistent.o -MD -MP -c -o fuzz_readelf_non_persistent.o fuzz_readelf_non_persistent.c

$CXX $CXXFLAGS -W -Wall -I./../zlib \
-o $OUT/fuzz_readelf_non_persistent fuzz_readelf_non_persistent.o \
version.o unwind-ia64.o dwarf.o elfcomm.o demanguse.o -Wl,--start-group ${LIBS} -Wl,--end-group
fi

# compile persistent fuzzers
fuzz_compile () {
src=$1
dst=$2
Expand Down Expand Up @@ -170,7 +184,7 @@ then
fi

# Copy seeds out
for fuzzname in readelf_pef readelf_elf32_csky readelf_elf64_mmix readelf_elf32_littlearm readelf_elf32_bigarm objdump objdump_safe nm objcopy bdf windres addr2line dwarf; do
for fuzzname in readelf_pef readelf_elf32_csky readelf_elf64_mmix readelf_elf32_littlearm readelf_elf32_bigarm objdump objdump_safe nm objcopy bdf windres addr2line dwarf readelf_non_persistent; do
cp $SRC/binary-samples/oss-fuzz-binutils/general_seeds.zip $OUT/fuzz_${fuzzname}_seed_corpus.zip
done
# Seed targeted the pef file format
Expand Down
27 changes: 27 additions & 0 deletions projects/binutils/fuzz_readelf_non_persistent.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* Copyright 2022 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.
*/

#include "readelf.h"
DavidKorczynski marked this conversation as resolved.
Show resolved Hide resolved

// Hack to satisfy OSS-Fuzz logic that looks for
// LLVMFuzzerTestOneInput in a binary.
char *random_string = "LLVMFuzzerTestOneInput";
DavidKorczynski marked this conversation as resolved.
Show resolved Hide resolved

static char *my_argv[5];
int main(int argc, char **argv) {
my_argv[0] = argv[0];
my_argv[1] = "-a";
my_argv[2] = argv[1];
my_argv[3] = NULL;
my_argv[4] = random_string;
return old_main(3, my_argv);
}