From 26dd8cfa83fd829d4dff321394e6b73aaaa7d252 Mon Sep 17 00:00:00 2001 From: DavidKorczynski Date: Thu, 21 Oct 2021 21:48:11 +0100 Subject: [PATCH] binutils: add objdump and nm fuzzer, and refactor (#6632) * binutils: refactor and objdump and nm fuzzer * cleanup build * binutils: remove tabs * binutils: bit more cleanup * binutils: fix typo --- projects/binutils/build.sh | 59 ++++++++++++++++++++++++-------- projects/binutils/fuzz_nm.c | 38 ++++++++++++++++++++ projects/binutils/fuzz_objdump.c | 47 +++++++++++++++++++++++++ projects/binutils/fuzz_readelf.c | 5 +++ 4 files changed, 134 insertions(+), 15 deletions(-) create mode 100644 projects/binutils/fuzz_nm.c create mode 100644 projects/binutils/fuzz_objdump.c diff --git a/projects/binutils/build.sh b/projects/binutils/build.sh index 2b5142483..ae1b266fe 100755 --- a/projects/binutils/build.sh +++ b/projects/binutils/build.sh @@ -39,37 +39,66 @@ mkdir fuzz cp ../fuzz_*.c fuzz/ cd fuzz +LIBS="../opcodes/libopcodes.a ../libctf/.libs/libctf.a ../bfd/libbfd.a ../zlib/libz.a ../libiberty/libiberty.a" for i in fuzz_disassemble fuzz_bfd; do $CC $CFLAGS -I ../include -I ../bfd -I ../opcodes -c $i.c -o $i.o - $CXX $CXXFLAGS $i.o -o $OUT/$i $LIB_FUZZING_ENGINE ../opcodes/libopcodes.a ../bfd/libbfd.a ../libiberty/libiberty.a ../zlib/libz.a + $CXX $CXXFLAGS $i.o -o $OUT/$i $LIB_FUZZING_ENGINE -Wl,--start-group ${LIBS} -Wl,--end-group done # TODO build corpuses # Now compile the src/binutils fuzzers cd ../binutils -# First copy the fuzzers, modify applications and copile object files -for i in readelf; do +# Compile the fuzzers. +# The general strategy is to remove main functions such that the fuzzer (which has its own main) +# can link against the code. + +# Patching +# First do readelf. We do this by changing readelf.c to readelf.h - the others will be changed +# to fuzz_readelf.h where readelf is their respective name. The reason it's different for readelf +# is because readelf does not have a header file so we can use readelf.h instead, and changing it +# might cause an annoyance on monorail since bugs will be relocated as the files will be different. +cp ../../fuzz_readelf.c . +sed 's/main (int argc/old_main (int argc, char **argv);\nint old_main (int argc/' readelf.c >> readelf.h + +# Patch the remainders +for i in objdump nm; do cp ../../fuzz_$i.c . + sed 's/main (int argc/old_main (int argc, char **argv);\nint old_main (int argc/' $i.c >> fuzz_$i.h +done - # Modify main functions so we dont have them anymore - sed 's/main (int argc/old_main (int argc, char **argv);\nint old_main (int argc/' $i.c >> $i.h - - # Compile object file - $CC $CFLAGS -DHAVE_CONFIG_H -I. -I../bfd -I./../bfd -I./../include -I./../zlib -DLOCALEDIR="\"/usr/local/share/locale\"" -Dbin_dummy_emulation=bin_vanilla_emulation -W -Wall -MT fuzz_$i.o -MD -MP -c -o fuzz_$i.o fuzz_$i.c +# Compile +for i in objdump readelf nm; do + $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_$i.o -MD -MP -c -o fuzz_$i.o fuzz_$i.c done # Link the files # Only link if they exist if ([ -f dwarf.o ] && [ -f elfcomm.o ] && [ -f version.o ]); then ## Readelf - $CXX $CXXFLAGS $LIB_FUZZING_ENGINE -W -Wall -I./../zlib -o fuzz_readelf fuzz_readelf.o version.o unwind-ia64.o dwarf.o elfcomm.o ../libctf/.libs/libctf-nobfd.a -L/src/binutils-gdb/zlib -lz ../libiberty/libiberty.a - mv fuzz_readelf $OUT/fuzz_readelf + $CXX $CXXFLAGS $LIB_FUZZING_ENGINE -W -Wall -I./../zlib \ + -o $OUT/fuzz_readelf fuzz_readelf.o \ + version.o unwind-ia64.o dwarf.o elfcomm.o \ + ../libctf/.libs/libctf-nobfd.a -L/src/binutils-gdb/zlib -lz ../libiberty/libiberty.a - ### Set up seed corpus for readelf in the form of a single ELF file. - zip fuzz_readelf_seed_corpus.zip /src/fuzz_readelf_seed_corpus/simple_elf - mv fuzz_readelf_seed_corpus.zip $OUT/ + # Link objdump fuzzer + OBJS="dwarf.o prdbg.o rddbg.o unwind-ia64.o debug.o stabs.o rdcoff.o bucomm.o version.o filemode.o elfcomm.o od-xcoff.o" + $CXX $CXXFLAGS $LIB_FUZZING_ENGINE -I./../zlib \ + -o $OUT/fuzz_objdump fuzz_objdump.o ${OBJS} \ + -Wl,--start-group ${LIBS} -Wl,--end-group - ## Copy over the options file - cp $SRC/fuzz_readelf.options $OUT/fuzz_readelf.options + # Link nm fuzzer + $CXX $CXXFLAGS $LIB_FUZZING_ENGINE -I./../zlib \ + -o $OUT/fuzz_nm fuzz_nm.o bucomm.o version.o filemode.o \ + -Wl,--start-group ${LIBS} -Wl,--end-group fi + +# Set up seed corpus for readelf in the form of a single ELF file. +zip fuzz_readelf_seed_corpus.zip /src/fuzz_readelf_seed_corpus/simple_elf +mv fuzz_readelf_seed_corpus.zip $OUT/ + +# Copy over the options file +cp $SRC/fuzz_readelf.options $OUT/fuzz_readelf.options diff --git a/projects/binutils/fuzz_nm.c b/projects/binutils/fuzz_nm.c new file mode 100644 index 000000000..05c2de98d --- /dev/null +++ b/projects/binutils/fuzz_nm.c @@ -0,0 +1,38 @@ +/* Copyright 2021 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. +*/ + +/* + * We convert nm.c into a header file to make convenient for fuzzing. + * We do this for several of the binutils applications when creating + * the binutils fuzzers. + */ +#include "fuzz_nm.h" + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); +int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + char filename[256]; + sprintf(filename, "/tmp/libfuzzer.%d", getpid()); + FILE *fp = fopen(filename, "wb"); + if (!fp) { + return 0; + } + fwrite(data, size, 1, fp); + fclose(fp); + + // Main fuzz entrypoint in nm.c + display_file(filename); + + unlink(filename); + return 0; +} diff --git a/projects/binutils/fuzz_objdump.c b/projects/binutils/fuzz_objdump.c new file mode 100644 index 000000000..c92fdda82 --- /dev/null +++ b/projects/binutils/fuzz_objdump.c @@ -0,0 +1,47 @@ +/* Copyright 2021 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. +*/ + +/* + * We convert objdump.c into a header file to make convenient for fuzzing. + * We do this for several of the binutils applications when creating + * the binutils fuzzers. + */ +#include "fuzz_objdump.h" + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); +int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + char filename[256]; + sprintf(filename, "/tmp/libfuzzer.%d", getpid()); + FILE *fp = fopen(filename, "wb"); + if (!fp) { + return 0; + } + fwrite(data, size, 1, fp); + fclose(fp); + + process_links = true; + do_follow_links = true; + dump_section_contents = true; + dump_section_headers = true; + dump_private_headers = true; + dump_ar_hdrs = true; + dump_reloc_info = true; + dump_dynamic_reloc_info = true; + + // Main fuzz entrypoint in objdump.c + display_file(filename, NULL, true); + + unlink(filename); + return 0; +} diff --git a/projects/binutils/fuzz_readelf.c b/projects/binutils/fuzz_readelf.c index e615a225e..409cd6a4e 100644 --- a/projects/binutils/fuzz_readelf.c +++ b/projects/binutils/fuzz_readelf.c @@ -13,6 +13,11 @@ See the License for the specific language governing permissions and limitations under the License. */ +/* + * We convert readelf.c into a header file to make convenient for fuzzing. + * We do this for several of the binutils applications when creating + * the binutils fuzzers. + */ #include "readelf.h" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);