summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMattias Nissler <mnissler@chromium.org>2019-10-14 17:03:45 +0200
committerCommit Bot <commit-bot@chromium.org>2019-10-17 06:08:24 +0000
commit089a944d51778640d26a125123e1d1946c828e90 (patch)
treeeb050cd9b57200e79d7daab55c4113a6b57fe3a3
parent7be3991ed441865f325182885ea08dc199ddbfd5 (diff)
downloadvboot-stabilize-12607.3.B.tar.gz
This adds a fuzzer binary to exercise GPT parsing. BUG=chromium:1014101 TEST=Build and run fuzzer. BRANCH=none Change-Id: Idecc0ddf491e976d4e01f5778e51a01ac317d961 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/1859595 Reviewed-by: Julius Werner <jwerner@chromium.org> Tested-by: Manoj Gupta <manojgupta@chromium.org> Commit-Queue: Manoj Gupta <manojgupta@chromium.org>
-rw-r--r--Makefile22
-rw-r--r--tests/cgpt_fuzzer.c86
2 files changed, 108 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index d5aa28f3..93ac67c1 100644
--- a/Makefile
+++ b/Makefile
@@ -242,6 +242,10 @@ LDFLAGS += -static
PKG_CONFIG += --static
endif
+ifneq (${FUZZ_FLAGS},)
+CFLAGS += ${FUZZ_FLAGS}
+endif
+
# Optional Libraries
LIBZIP_VERSION := $(shell ${PKG_CONFIG} --modversion libzip 2>/dev/null)
HAVE_LIBZIP := $(if ${LIBZIP_VERSION},1)
@@ -775,6 +779,14 @@ TEST21_BINS = $(addprefix ${BUILD}/,${TEST21_NAMES})
# Directory containing test keys
TEST_KEYS = ${SRC_RUN}/tests/testkeys
+# ----------------------------------------------------------------------------
+# Fuzzing binaries
+
+FUZZ_TEST_NAMES = \
+ tests/cgpt_fuzzer
+
+FUZZ_TEST_BINS = $(addprefix ${BUILD}/,${FUZZ_TEST_NAMES})
+FUZZ_TEST_OBJS += $(addsuffix .o,${FUZZ_TEST_BINS})
##############################################################################
# Finally, some targets. High-level ones first.
@@ -793,6 +805,7 @@ host_tools: utils futil tests
.PHONY: host_stuff
host_stuff: utillib hostlib \
+ $(if $(filter x86_64,${ARCH}),fuzzers) \
$(if ${NO_BUILD_TOOLS},,cgpt host_tools)
.PHONY: clean
@@ -1073,6 +1086,15 @@ ${TESTLIB}: ${TESTLIB_OBJS}
@${PRINTF} " AR $(subst ${BUILD}/,,$@)\n"
${Q}ar qc $@ $^
+# ----------------------------------------------------------------------------
+# Fuzzers
+
+.PHONY: fuzzers
+fuzzers: ${FUZZ_TEST_BINS}
+
+${FUZZ_TEST_BINS}: ${FWLIB}
+${FUZZ_TEST_BINS}: LIBS = ${FWLIB}
+${FUZZ_TEST_BINS}: LDFLAGS += -fsanitize=fuzzer
# ----------------------------------------------------------------------------
# Generic build rules. LIBS and OBJS can be overridden to tweak the generic
diff --git a/tests/cgpt_fuzzer.c b/tests/cgpt_fuzzer.c
new file mode 100644
index 00000000..51ba72a3
--- /dev/null
+++ b/tests/cgpt_fuzzer.c
@@ -0,0 +1,86 @@
+// Copyright 2019 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "cgptlib.h"
+#include "gpt.h"
+
+struct MockDisk {
+ size_t sector_shift;
+ const uint8_t* data;
+ size_t size;
+};
+
+// GPT disk parameters provided by the fuzzer test case. See GptData type
+// definition for details.
+struct GptDataParams {
+ uint32_t sector_shift;
+ uint32_t flags;
+ uint64_t streaming_drive_sectors;
+ uint64_t gpt_drive_sectors;
+} __attribute__((packed));
+
+static struct MockDisk mock_disk;
+
+vb2_error_t VbExDiskRead(VbExDiskHandle_t h, uint64_t lba_start,
+ uint64_t lba_count, void *buffer)
+{
+ size_t lba_size = mock_disk.size >> mock_disk.sector_shift;
+ if (lba_start > lba_size || lba_size - lba_start < lba_count) {
+ return VB2_ERROR_UNKNOWN;
+ }
+
+ size_t start = lba_start << mock_disk.sector_shift;
+ size_t size = lba_count << mock_disk.sector_shift;
+
+ memcpy(buffer, &mock_disk.data[start], size);
+ return VB2_SUCCESS;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
+
+int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ struct GptDataParams params;
+ if (size < sizeof(params)) {
+ return 0;
+ }
+ memcpy(&params, data, sizeof(params));
+
+ // Enforce a sane sector size. The sector size must accommodate the GPT
+ // header (the code assumes this) and large values don't make sense
+ // either (both in terms of actual hardware parameters and ability for
+ // the fuzzer to deal with effectively).
+ if (params.sector_shift < 9) {
+ params.sector_shift = 9; // 512 byte sectors min.
+ }
+ if (params.sector_shift > 12) {
+ params.sector_shift = 12; // 4K sectors max.
+ }
+
+ mock_disk.sector_shift = params.sector_shift;
+ mock_disk.data = data + sizeof(params);
+ mock_disk.size = size - sizeof(params);
+
+ GptData gpt;
+ memset(&gpt, 0, sizeof(gpt));
+ gpt.sector_bytes = 1ULL << params.sector_shift;
+ gpt.streaming_drive_sectors = params.streaming_drive_sectors;
+ gpt.gpt_drive_sectors = params.gpt_drive_sectors;
+ gpt.flags = params.flags;
+
+ if (0 == AllocAndReadGptData(0, &gpt)) {
+ int result = GptInit(&gpt);
+ while (GPT_SUCCESS == result) {
+ uint64_t part_start, part_size;
+ result = GptNextKernelEntry(&gpt, &part_start,
+ &part_size);
+ }
+ }
+
+ WriteAndFreeGptData(0, &gpt);
+
+ return 0;
+}