| // 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(¶ms, data, sizeof(params)); |
| |
| // Enforce a valid 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; |
| } |