xref: /aosp_15_r20/external/vboot_reference/tests/cgpt_fuzzer.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
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(&params, 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