1 // Copyright 2019 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stddef.h>
6 #include <stdint.h>
7
8 #include "cgptlib.h"
9 #include "gpt.h"
10
11 struct MockDisk {
12 size_t sector_shift;
13 const uint8_t* data;
14 size_t size;
15 };
16
17 // GPT disk parameters provided by the fuzzer test case. See GptData type
18 // definition for details.
19 struct GptDataParams {
20 uint32_t sector_shift;
21 uint32_t flags;
22 uint64_t streaming_drive_sectors;
23 uint64_t gpt_drive_sectors;
24 } __attribute__((packed));
25
26 static struct MockDisk mock_disk;
27
VbExDiskRead(vb2ex_disk_handle_t h,uint64_t lba_start,uint64_t lba_count,void * buffer)28 vb2_error_t VbExDiskRead(vb2ex_disk_handle_t h, uint64_t lba_start,
29 uint64_t lba_count, void *buffer)
30 {
31 size_t lba_size = mock_disk.size >> mock_disk.sector_shift;
32 if (lba_start > lba_size || lba_size - lba_start < lba_count) {
33 return VB2_ERROR_UNKNOWN;
34 }
35
36 size_t start = lba_start << mock_disk.sector_shift;
37 size_t size = lba_count << mock_disk.sector_shift;
38
39 memcpy(buffer, &mock_disk.data[start], size);
40 return VB2_SUCCESS;
41 }
42
43 int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
44
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)45 int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
46 struct GptDataParams params;
47 if (size < sizeof(params)) {
48 return 0;
49 }
50 memcpy(¶ms, data, sizeof(params));
51
52 // Enforce a valid sector size. The sector size must accommodate the GPT
53 // header (the code assumes this) and large values don't make sense
54 // either (both in terms of actual hardware parameters and ability for
55 // the fuzzer to deal with effectively).
56 if (params.sector_shift < 9) {
57 params.sector_shift = 9; // 512 byte sectors min.
58 }
59 if (params.sector_shift > 12) {
60 params.sector_shift = 12; // 4K sectors max.
61 }
62
63 mock_disk.sector_shift = params.sector_shift;
64 mock_disk.data = data + sizeof(params);
65 mock_disk.size = size - sizeof(params);
66
67 GptData gpt;
68 memset(&gpt, 0, sizeof(gpt));
69 gpt.sector_bytes = 1ULL << params.sector_shift;
70 gpt.streaming_drive_sectors = params.streaming_drive_sectors;
71 gpt.gpt_drive_sectors = params.gpt_drive_sectors;
72 gpt.flags = params.flags;
73
74 if (0 == AllocAndReadGptData(0, &gpt)) {
75 int result = GptInit(&gpt);
76 while (GPT_SUCCESS == result) {
77 uint64_t part_start, part_size;
78 result = GptNextKernelEntry(&gpt, &part_start,
79 &part_size);
80 }
81 }
82
83 WriteAndFreeGptData(0, &gpt);
84
85 return 0;
86 }
87