From 49a2e71ae07b3bf0375cb2506a352616bd44842f Mon Sep 17 00:00:00 2001 From: Eugene Rodionov Date: Wed, 16 Feb 2022 01:45:13 +0000 Subject: [PATCH] Create an initial version of libfdt fuzzer. Test: SANITIZE_HOST=address m libfdt_fuzzer Test: out/host/linux-x86/fuzz/x86_64/libfdt_fuzzer/libfdt_fuzzer Bug: 217650981 Change-Id: Ib1e26fe0b8e8d3f94fc1c5455853d57ccf348d1c --- fuzzing/Android.bp | 15 ++++++++++++++ fuzzing/libfdt_fuzzer.cpp | 42 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 fuzzing/Android.bp create mode 100644 fuzzing/libfdt_fuzzer.cpp diff --git a/fuzzing/Android.bp b/fuzzing/Android.bp new file mode 100644 index 0000000..ddda130 --- /dev/null +++ b/fuzzing/Android.bp @@ -0,0 +1,15 @@ +// Copyright 2022 The Android Open Source Project +package { + default_applicable_licenses: ["external_dtc_license"], +} + +cc_fuzz { + name: "libfdt_fuzzer", + srcs: [ + "libfdt_fuzzer.cpp", + ], + static_libs: [ + "libfdt", + ], + host_supported: true, +} diff --git a/fuzzing/libfdt_fuzzer.cpp b/fuzzing/libfdt_fuzzer.cpp new file mode 100644 index 0000000..4a0b1fc --- /dev/null +++ b/fuzzing/libfdt_fuzzer.cpp @@ -0,0 +1,42 @@ +#include +#include +#include +#include + +#include "libfdt.h" +#include "libfdt_env.h" + +void walk_device_tree(const void *device_tree, int parent_node) { + int len = 0; + const char *node_name = fdt_get_name(device_tree, parent_node, &len); + if (node_name != NULL) { + // avoid clang complaining about unused variable node_name and force + // ASan to validate string pointer in strlen call. + assert(strlen(node_name) == len); + } + + uint32_t phandle = fdt_get_phandle(device_tree, parent_node); + if (phandle != 0) { + assert(parent_node == fdt_node_offset_by_phandle(device_tree, phandle)); + } + + // recursively walk the node's children + for (int node = fdt_first_subnode(device_tree, parent_node); node >= 0; + node = fdt_next_subnode(device_tree, node)) { + walk_device_tree(device_tree, node); + } +} + +// Information on device tree is available in external/dtc/Documentation/ +// folder. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + // Non-zero return values are reserved for future use. + if (size < FDT_V17_SIZE) return 0; + + if (fdt_check_header(data) != 0) return 0; + + int root_node_offset = 0; + walk_device_tree(data, root_node_offset); + + return 0; +} \ No newline at end of file