diff --git a/.gitignore b/.gitignore index d225542e..982a95e7 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ /third_party/fuchsia/qemu /third_party/fuchsia/sdk /third_party/gtest/gtest +/third_party/libfuzzer /third_party/linux/.cipd /third_party/linux/clang /third_party/linux/sysroot diff --git a/DEPS b/DEPS index fdb148d7..5f96b781 100644 --- a/DEPS +++ b/DEPS @@ -30,6 +30,9 @@ deps = { 'crashpad/third_party/mini_chromium/mini_chromium': Var('chromium_git') + '/chromium/mini_chromium@' + 'd5a36d3c51a7a270afc2c888baaaec2a6e496219', + 'crashpad/third_party/libfuzzer/src': + Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git@' + + 'fda403cf93ecb8792cb1d061564d89a6553ca020', 'crashpad/third_party/zlib/zlib': Var('chromium_git') + '/chromium/src/third_party/zlib@' + '13dc246a58e4b72104d35f9b1809af95221ebda7', diff --git a/build/BUILD.gn b/build/BUILD.gn index 5e7aed0c..0ef1127f 100644 --- a/build/BUILD.gn +++ b/build/BUILD.gn @@ -37,3 +37,15 @@ group("default_exe_manifest_win") { ] } } + +config("crashpad_fuzzer_flags") { + cflags = [ + "-fsanitize=address", + "-fsanitize-address-use-after-scope", + "-fsanitize=fuzzer", + ] + + ldflags = [ + "-fsanitize=address", + ] +} diff --git a/build/BUILDCONFIG.gn b/build/BUILDCONFIG.gn index 0e6da165..95dc2771 100644 --- a/build/BUILDCONFIG.gn +++ b/build/BUILDCONFIG.gn @@ -46,6 +46,10 @@ declare_args() { # and logging. When false, enables the release configuration, with additional # optimizations. is_debug = false + + # When true, build all code with -fsanitize=fuzzer, and enable various + # *_fuzzer targets. + crashpad_use_libfuzzer = false } _default_configs = [ @@ -53,6 +57,10 @@ _default_configs = [ "//third_party/mini_chromium/mini_chromium/build:Wexit_time_destructors", ] +if (crashpad_use_libfuzzer) { + _default_configs += [ "//build:crashpad_fuzzer_flags" ] +} + _default_executable_configs = _default_configs + [ "//third_party/mini_chromium/mini_chromium/build:executable", diff --git a/build/crashpad_fuzzer_test.gni b/build/crashpad_fuzzer_test.gni new file mode 100644 index 00000000..8e0eaa9f --- /dev/null +++ b/build/crashpad_fuzzer_test.gni @@ -0,0 +1,46 @@ +# Copyright 2018 The Crashpad Authors. All rights reserved. +# +# 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. + +import("crashpad_buildconfig.gni") +import("test.gni") + +template("fuzzer_test") { + if (crashpad_is_standalone && crashpad_use_libfuzzer) { + test(target_name) { + forward_variables_from(invoker, + [ + "cflags", + "cflags_cc", + "check_includes", + "defines", + "include_dirs", + "sources", + ]) + configs += [ "..:crashpad_config" ] + if (defined(invoker.deps)) { + deps = invoker.deps + } + deps += [ "../third_party/libfuzzer" ] + + if (!defined(invoker.cflags)) { + cflags = [] + } + cflags += [ "-fsanitize=fuzzer" ] + } + } else { + not_needed(invoker, "*") + group(target_name) { + } + } +} diff --git a/snapshot/BUILD.gn b/snapshot/BUILD.gn index 825c9f16..ac3125ce 100644 --- a/snapshot/BUILD.gn +++ b/snapshot/BUILD.gn @@ -13,6 +13,7 @@ # limitations under the License. import("../build/crashpad_buildconfig.gni") +import("../build/crashpad_fuzzer_test.gni") if (crashpad_is_in_chromium) { import("//build/config/compiler/compiler.gni") @@ -238,6 +239,17 @@ if (crashpad_is_win) { } } +fuzzer_test("elf_image_reader_fuzzer") { + sources = [ + "elf/elf_image_reader_fuzzer.cc", + ] + + deps = [ + ":snapshot", + "../third_party/mini_chromium:base", + ] +} + static_library("test_support") { testonly = true diff --git a/snapshot/elf/elf_image_reader_fuzzer.cc b/snapshot/elf/elf_image_reader_fuzzer.cc new file mode 100644 index 00000000..1686650b --- /dev/null +++ b/snapshot/elf/elf_image_reader_fuzzer.cc @@ -0,0 +1,75 @@ +// Copyright 2018 The Crashpad Authors. All rights reserved. +// +// 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 "base/logging.h" +#include "snapshot/elf/elf_image_reader.h" +#include "util/process/process_memory.h" + +using namespace crashpad; + +class FakeProcessMemory : public ProcessMemory { + public: + FakeProcessMemory(const uint8_t* data, size_t size, VMAddress fake_base) + : data_(data), size_(size), fake_base_(fake_base) {} + + ssize_t ReadUpTo(VMAddress address, + size_t size, + void* buffer) const override { + VMAddress offset_in_data = address - fake_base_; + if (offset_in_data > size_) + return -1; + ssize_t read_size = std::min(size_ - offset_in_data, size); + memcpy(buffer, &data_[offset_in_data], read_size); + return read_size; + } + + private: + const uint8_t* data_; + size_t size_; + VMAddress fake_base_; +}; + +extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) { + // Swallow all logs to avoid spam. + logging::SetLogMessageHandler( + [](logging::LogSeverity, const char*, int, size_t, const std::string&) { + return true; + }); + return 0; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + constexpr size_t kBase = 0x10000; + FakeProcessMemory process_memory(data, size, kBase); + ProcessMemoryRange process_memory_range; + process_memory_range.Initialize(&process_memory, true, kBase, size); + + ElfImageReader reader; + if (!reader.Initialize(process_memory_range, kBase)) + return 0; + + ElfImageReader::NoteReader::Result result; + std::string note_name; + std::string note_desc; + ElfImageReader::NoteReader::NoteType note_type; + auto notes = reader.Notes(-1); + while ((result = notes->NextNote(¬e_name, ¬e_type, ¬e_desc)) == + ElfImageReader::NoteReader::Result::kSuccess) { + LOG(ERROR) << note_name << note_type << note_desc; + } + + return 0; +} diff --git a/snapshot/elf/elf_image_reader_fuzzer_corpus/crashpad_snapshot_test_both_dt_hash_styles.so b/snapshot/elf/elf_image_reader_fuzzer_corpus/crashpad_snapshot_test_both_dt_hash_styles.so new file mode 100755 index 00000000..4dc7cdbe Binary files /dev/null and b/snapshot/elf/elf_image_reader_fuzzer_corpus/crashpad_snapshot_test_both_dt_hash_styles.so differ diff --git a/snapshot/elf/elf_image_reader_fuzzer_corpus/ret42 b/snapshot/elf/elf_image_reader_fuzzer_corpus/ret42 new file mode 100755 index 00000000..59eb8f2b Binary files /dev/null and b/snapshot/elf/elf_image_reader_fuzzer_corpus/ret42 differ diff --git a/third_party/libfuzzer/BUILD.gn b/third_party/libfuzzer/BUILD.gn new file mode 100644 index 00000000..ac815dad --- /dev/null +++ b/third_party/libfuzzer/BUILD.gn @@ -0,0 +1,49 @@ +# Copyright 2018 The Crashpad Authors. All rights reserved. +# +# 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. + +source_set("libfuzzer") { + if (crashpad_use_libfuzzer) { + sources = [ + "src/FuzzerClangCounters.cpp", + "src/FuzzerCrossOver.cpp", + "src/FuzzerDriver.cpp", + "src/FuzzerExtFunctionsDlsym.cpp", + "src/FuzzerExtFunctionsDlsymWin.cpp", + "src/FuzzerExtFunctionsWeak.cpp", + "src/FuzzerExtFunctionsWeakAlias.cpp", + "src/FuzzerExtraCounters.cpp", + "src/FuzzerIO.cpp", + "src/FuzzerIOPosix.cpp", + "src/FuzzerIOWindows.cpp", + "src/FuzzerLoop.cpp", + "src/FuzzerMain.cpp", + "src/FuzzerMerge.cpp", + "src/FuzzerMutate.cpp", + "src/FuzzerSHA1.cpp", + "src/FuzzerShmemPosix.cpp", + "src/FuzzerShmemWindows.cpp", + "src/FuzzerTracePC.cpp", + "src/FuzzerUtil.cpp", + "src/FuzzerUtilDarwin.cpp", + "src/FuzzerUtilLinux.cpp", + "src/FuzzerUtilPosix.cpp", + "src/FuzzerUtilWindows.cpp", + ] + + configs -= [ + "//third_party/mini_chromium/mini_chromium/build:Wexit_time_destructors", + "//build:crashpad_fuzzer_flags", + ] + } +}