From aa83381257bbf55d71c6a4b0f56f805409776047 Mon Sep 17 00:00:00 2001 From: DavidKorczynski Date: Wed, 16 Mar 2022 23:54:15 +0000 Subject: [PATCH] elfutils: add and expand library fuzzers (#7395) * elfutils: make name more appropriate * elfutils: update libelf fuzzer * elfutils: add fuzz-libdwfl * elfutils: nits * elfutils: fix build --- projects/elfutils/build.sh | 15 ++++-- projects/elfutils/fuzz-libdwfl.c | 53 +++++++++++++++++++ ...{fuzz-elf-get-sections.c => fuzz-libelf.c} | 46 +++++++++++----- 3 files changed, 98 insertions(+), 16 deletions(-) create mode 100644 projects/elfutils/fuzz-libdwfl.c rename projects/elfutils/{fuzz-elf-get-sections.c => fuzz-libelf.c} (73%) diff --git a/projects/elfutils/build.sh b/projects/elfutils/build.sh index 7ee20cb9f..c1c10b924 100755 --- a/projects/elfutils/build.sh +++ b/projects/elfutils/build.sh @@ -93,11 +93,20 @@ $CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzz-dwfl-core.o \ $CC $CFLAGS \ -D_GNU_SOURCE -DHAVE_CONFIG_H \ -I. -I./lib -I./libelf -I./libebl -I./libdw -I./libdwelf -I./libdwfl -I./libasm \ - -c "$SRC/fuzz-elf-get-sections.c" -o fuzz-elf-get-sections.o -$CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzz-elf-get-sections.o \ + -c "$SRC/fuzz-libelf.c" -o fuzz-libelf.o +$CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzz-libelf.o \ ./libasm/libasm.a ./libebl/libebl.a ./backends/libebl_backends.a ./libcpu/libcpu.a \ ./libdw/libdw.a ./libelf/libelf.a ./lib/libeu.a -l:libz.a \ - -o "$OUT/fuzz-elf-get-sections" + -o "$OUT/fuzz-libelf" + +$CC $CFLAGS \ + -D_GNU_SOURCE -DHAVE_CONFIG_H \ + -I. -I./lib -I./libelf -I./libebl -I./libdw -I./libdwelf -I./libdwfl -I./libasm \ + -c "$SRC/fuzz-libdwfl.c" -o fuzz-libdwfl.o +$CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzz-libdwfl.o \ + ./libasm/libasm.a ./libebl/libebl.a ./backends/libebl_backends.a ./libcpu/libcpu.a \ + ./libdw/libdw.a ./libelf/libelf.a ./lib/libeu.a -l:libz.a \ + -o "$OUT/fuzz-libdwfl" # Corpus cp "$SRC/fuzz-dwfl-core_seed_corpus.zip" "$OUT" diff --git a/projects/elfutils/fuzz-libdwfl.c b/projects/elfutils/fuzz-libdwfl.c new file mode 100644 index 000000000..2a1378bec --- /dev/null +++ b/projects/elfutils/fuzz-libdwfl.c @@ -0,0 +1,53 @@ +/* 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include "libdwfl.h" + +static const char *debuginfo_path = ""; +static const Dwfl_Callbacks cb = { + NULL, + dwfl_standard_find_debuginfo, + NULL, + (char **)&debuginfo_path, +}; + + +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); + + Dwarf_Addr bias = 0; + Dwfl *dwfl = dwfl_begin(&cb); + dwfl_report_begin(dwfl); + + Dwfl_Module *mod = dwfl_report_offline(dwfl, filename, filename, -1); + Dwarf *res = dwfl_module_getdwarf(mod, &bias); + + dwfl_end (dwfl); + unlink(filename); + return 0; +} diff --git a/projects/elfutils/fuzz-elf-get-sections.c b/projects/elfutils/fuzz-libelf.c similarity index 73% rename from projects/elfutils/fuzz-elf-get-sections.c rename to projects/elfutils/fuzz-libelf.c index 1110330ca..f255e1e3a 100644 --- a/projects/elfutils/fuzz-elf-get-sections.c +++ b/projects/elfutils/fuzz-libelf.c @@ -10,7 +10,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -/* Inspired by the elfgetzdata.c test */ #include #include #include @@ -21,17 +20,8 @@ limitations under the License. #include #include -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 objdump.c +void fuzz_logic_one(char *filename, int compression_type) { (void)elf_version(EV_CURRENT); int fd = open(filename, O_RDONLY); Elf *elf = elf_begin(fd, ELF_C_READ, NULL); @@ -50,7 +40,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // so it resembles the test code. // Compress and get data of the section if ((shdr->sh_flags & SHF_COMPRESSED) != 0) { - if (elf_compress(scn, 0, 0) >= 0) { + if (elf_compress(scn, compression_type, 0) >= 0) { elf_getdata(scn, NULL); } } else if (name != NULL) { @@ -63,8 +53,38 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { } elf_end(elf); } - close(fd); +} + +void fuzz_logic_twice(char *filename, int open_flags, Elf_Cmd cmd) { + (void)elf_version(EV_CURRENT); + int fd = open(filename, open_flags); + Elf *elf = elf_begin(fd, cmd, NULL); + if (elf != NULL) { + size_t elf_size = 0; + elf_rawfile(elf, &elf_size); + elf_end(elf); + } + close(fd); +} + +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); + + fuzz_logic_one(filename, 0); + fuzz_logic_one(filename, 1); + fuzz_logic_twice(filename, O_RDONLY, ELF_C_READ); + fuzz_logic_twice(filename, O_RDONLY | O_WRONLY, ELF_C_RDWR); + fuzz_logic_twice(filename, O_RDONLY, ELF_C_READ_MMAP); + fuzz_logic_twice(filename, O_RDONLY | O_WRONLY, ELF_C_RDWR_MMAP); + unlink(filename); return 0; }