1*57696d54SAkhilesh Sanikop /*
2*57696d54SAkhilesh Sanikop * Copyright (C) 2020 The Android Open Source Project
3*57696d54SAkhilesh Sanikop *
4*57696d54SAkhilesh Sanikop * This software is licensed under the terms of the GNU General Public
5*57696d54SAkhilesh Sanikop * License version 2, as published by the Free Software Foundation, and
6*57696d54SAkhilesh Sanikop * may be copied, distributed, and modified under those terms.
7*57696d54SAkhilesh Sanikop *
8*57696d54SAkhilesh Sanikop * This program is distributed in the hope that it will be useful,
9*57696d54SAkhilesh Sanikop * but WITHOUT ANY WARRANTY; without even the implied warranty of
10*57696d54SAkhilesh Sanikop * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11*57696d54SAkhilesh Sanikop * GNU General Public License for more details.
12*57696d54SAkhilesh Sanikop */
13*57696d54SAkhilesh Sanikop
14*57696d54SAkhilesh Sanikop #include <fstream>
15*57696d54SAkhilesh Sanikop #include <iostream>
16*57696d54SAkhilesh Sanikop #include <functional>
17*57696d54SAkhilesh Sanikop #include "diskio.h"
18*57696d54SAkhilesh Sanikop #include "gpt.h"
19*57696d54SAkhilesh Sanikop #include "parttypes.h"
20*57696d54SAkhilesh Sanikop
21*57696d54SAkhilesh Sanikop #include <fuzzer/FuzzedDataProvider.h>
22*57696d54SAkhilesh Sanikop
23*57696d54SAkhilesh Sanikop const int8_t kQuiet = 1;
24*57696d54SAkhilesh Sanikop const int8_t kMinRuns = 1;
25*57696d54SAkhilesh Sanikop const int8_t kGPTMaxRuns = 24;
26*57696d54SAkhilesh Sanikop const int16_t kMaxByte = 256;
27*57696d54SAkhilesh Sanikop const std::string kShowCommand = "show";
28*57696d54SAkhilesh Sanikop const std::string kGetCommand = "get";
29*57696d54SAkhilesh Sanikop const std::string kTempFile = "/dev/tempfile";
30*57696d54SAkhilesh Sanikop const std::string kNull = "/dev/null";
31*57696d54SAkhilesh Sanikop const std::string kBackup = "/dev/gptbackup";
32*57696d54SAkhilesh Sanikop const std::string kDoesNotExist = "/dev/does_not_exist";
33*57696d54SAkhilesh Sanikop
34*57696d54SAkhilesh Sanikop std::ofstream silence(kNull);
35*57696d54SAkhilesh Sanikop
36*57696d54SAkhilesh Sanikop class GptfFuzzer {
37*57696d54SAkhilesh Sanikop public:
GptfFuzzer(const uint8_t * data,size_t size)38*57696d54SAkhilesh Sanikop GptfFuzzer(const uint8_t *data, size_t size) : mFdp(data, size) {
39*57696d54SAkhilesh Sanikop mDisk.OpenForRead(static_cast<const unsigned char *>(data), size);
40*57696d54SAkhilesh Sanikop }
41*57696d54SAkhilesh Sanikop
~GptfFuzzer()42*57696d54SAkhilesh Sanikop ~GptfFuzzer() { mDisk.Close(); }
43*57696d54SAkhilesh Sanikop
44*57696d54SAkhilesh Sanikop void process();
45*57696d54SAkhilesh Sanikop
46*57696d54SAkhilesh Sanikop private:
47*57696d54SAkhilesh Sanikop void init();
48*57696d54SAkhilesh Sanikop FuzzedDataProvider mFdp;
49*57696d54SAkhilesh Sanikop DiskIO mDisk;
50*57696d54SAkhilesh Sanikop GPTData mGptData;
51*57696d54SAkhilesh Sanikop };
52*57696d54SAkhilesh Sanikop
init()53*57696d54SAkhilesh Sanikop void GptfFuzzer::init() {
54*57696d54SAkhilesh Sanikop if (mFdp.ConsumeBool()) {
55*57696d54SAkhilesh Sanikop mGptData.SetDisk(mDisk);
56*57696d54SAkhilesh Sanikop } else {
57*57696d54SAkhilesh Sanikop mGptData.SetDisk(kTempFile);
58*57696d54SAkhilesh Sanikop }
59*57696d54SAkhilesh Sanikop
60*57696d54SAkhilesh Sanikop uint64_t startSector = mFdp.ConsumeIntegral<uint64_t>();
61*57696d54SAkhilesh Sanikop uint64_t endSector =
62*57696d54SAkhilesh Sanikop mFdp.ConsumeIntegralInRange<uint64_t>(startSector, UINT64_MAX);
63*57696d54SAkhilesh Sanikop mGptData.CreatePartition(mFdp.ConsumeIntegral<uint8_t>() /* partNum */,
64*57696d54SAkhilesh Sanikop startSector, endSector);
65*57696d54SAkhilesh Sanikop
66*57696d54SAkhilesh Sanikop const UnicodeString name = mFdp.ConsumeRandomLengthString(NAME_SIZE);
67*57696d54SAkhilesh Sanikop uint8_t partNum = mFdp.ConsumeIntegral<uint8_t>();
68*57696d54SAkhilesh Sanikop if (mGptData.SetName(partNum, name)) {
69*57696d54SAkhilesh Sanikop PartType pType;
70*57696d54SAkhilesh Sanikop mGptData.ChangePartType(partNum, pType);
71*57696d54SAkhilesh Sanikop }
72*57696d54SAkhilesh Sanikop
73*57696d54SAkhilesh Sanikop if (mFdp.ConsumeBool()) {
74*57696d54SAkhilesh Sanikop mGptData.SetAlignment(mFdp.ConsumeIntegral<uint32_t>() /* n */);
75*57696d54SAkhilesh Sanikop }
76*57696d54SAkhilesh Sanikop
77*57696d54SAkhilesh Sanikop if (mFdp.ConsumeBool()) {
78*57696d54SAkhilesh Sanikop GUIDData gData(mFdp.ConsumeRandomLengthString(kMaxByte));
79*57696d54SAkhilesh Sanikop gData.Randomize();
80*57696d54SAkhilesh Sanikop mGptData.SetDiskGUID(gData);
81*57696d54SAkhilesh Sanikop mGptData.SaveGPTBackup(kBackup);
82*57696d54SAkhilesh Sanikop mGptData.SetPartitionGUID(mFdp.ConsumeIntegral<uint8_t>() /* pn */, gData);
83*57696d54SAkhilesh Sanikop }
84*57696d54SAkhilesh Sanikop
85*57696d54SAkhilesh Sanikop if (mFdp.ConsumeBool()) {
86*57696d54SAkhilesh Sanikop mGptData.RandomizeGUIDs();
87*57696d54SAkhilesh Sanikop }
88*57696d54SAkhilesh Sanikop
89*57696d54SAkhilesh Sanikop if (mFdp.ConsumeBool()) {
90*57696d54SAkhilesh Sanikop mGptData.LoadGPTBackup(kBackup);
91*57696d54SAkhilesh Sanikop }
92*57696d54SAkhilesh Sanikop
93*57696d54SAkhilesh Sanikop if (mFdp.ConsumeBool()) {
94*57696d54SAkhilesh Sanikop mGptData.SaveGPTData(kQuiet);
95*57696d54SAkhilesh Sanikop }
96*57696d54SAkhilesh Sanikop
97*57696d54SAkhilesh Sanikop if (mFdp.ConsumeBool()) {
98*57696d54SAkhilesh Sanikop mGptData.SaveMBR();
99*57696d54SAkhilesh Sanikop }
100*57696d54SAkhilesh Sanikop }
101*57696d54SAkhilesh Sanikop
process()102*57696d54SAkhilesh Sanikop void GptfFuzzer::process() {
103*57696d54SAkhilesh Sanikop init();
104*57696d54SAkhilesh Sanikop int8_t runs = mFdp.ConsumeIntegralInRange<int32_t>(kMinRuns, kGPTMaxRuns);
105*57696d54SAkhilesh Sanikop
106*57696d54SAkhilesh Sanikop while (--runs && mFdp.remaining_bytes()) {
107*57696d54SAkhilesh Sanikop auto invokeGPTAPI = mFdp.PickValueInArray<const std::function<void()>>({
108*57696d54SAkhilesh Sanikop [&]() {
109*57696d54SAkhilesh Sanikop mGptData.XFormDisklabel(
110*57696d54SAkhilesh Sanikop mFdp.ConsumeIntegral<uint8_t>() /* partNum */);
111*57696d54SAkhilesh Sanikop },
112*57696d54SAkhilesh Sanikop [&]() {
113*57696d54SAkhilesh Sanikop mGptData.OnePartToMBR(mFdp.ConsumeIntegral<uint8_t>() /* gptPart */,
114*57696d54SAkhilesh Sanikop mFdp.ConsumeIntegral<uint8_t>() /* mbrPart */);
115*57696d54SAkhilesh Sanikop },
116*57696d54SAkhilesh Sanikop [&]() {
117*57696d54SAkhilesh Sanikop uint32_t numSegments;
118*57696d54SAkhilesh Sanikop uint64_t largestSegment;
119*57696d54SAkhilesh Sanikop mGptData.FindFreeBlocks(&numSegments, &largestSegment);
120*57696d54SAkhilesh Sanikop },
121*57696d54SAkhilesh Sanikop [&]() {
122*57696d54SAkhilesh Sanikop mGptData.FindFirstInLargest();
123*57696d54SAkhilesh Sanikop },
124*57696d54SAkhilesh Sanikop [&]() {
125*57696d54SAkhilesh Sanikop mGptData.FindLastAvailable();
126*57696d54SAkhilesh Sanikop },
127*57696d54SAkhilesh Sanikop [&]() {
128*57696d54SAkhilesh Sanikop mGptData.FindFirstFreePart();
129*57696d54SAkhilesh Sanikop },
130*57696d54SAkhilesh Sanikop [&]() {
131*57696d54SAkhilesh Sanikop mGptData.MoveMainTable(
132*57696d54SAkhilesh Sanikop mFdp.ConsumeIntegral<uint64_t>() /* pteSector */);
133*57696d54SAkhilesh Sanikop },
134*57696d54SAkhilesh Sanikop [&]() {
135*57696d54SAkhilesh Sanikop mGptData.Verify();
136*57696d54SAkhilesh Sanikop },
137*57696d54SAkhilesh Sanikop [&]() {
138*57696d54SAkhilesh Sanikop mGptData.SortGPT();
139*57696d54SAkhilesh Sanikop },
140*57696d54SAkhilesh Sanikop [&]() {
141*57696d54SAkhilesh Sanikop std::string command = mFdp.ConsumeBool() ? kShowCommand : kGetCommand;
142*57696d54SAkhilesh Sanikop std::string randomCommand = mFdp.ConsumeRandomLengthString(kMaxByte);
143*57696d54SAkhilesh Sanikop mGptData.ManageAttributes(
144*57696d54SAkhilesh Sanikop mFdp.ConsumeIntegral<uint8_t>() /* partNum */,
145*57696d54SAkhilesh Sanikop mFdp.ConsumeBool() ? command : randomCommand,
146*57696d54SAkhilesh Sanikop mFdp.ConsumeRandomLengthString(kMaxByte) /* bits */);
147*57696d54SAkhilesh Sanikop },
148*57696d54SAkhilesh Sanikop });
149*57696d54SAkhilesh Sanikop invokeGPTAPI();
150*57696d54SAkhilesh Sanikop }
151*57696d54SAkhilesh Sanikop if (mFdp.ConsumeBool()) {
152*57696d54SAkhilesh Sanikop mGptData.LoadPartitions(kDoesNotExist);
153*57696d54SAkhilesh Sanikop }
154*57696d54SAkhilesh Sanikop if (mFdp.ConsumeBool()) {
155*57696d54SAkhilesh Sanikop mGptData.SwapPartitions(mFdp.ConsumeIntegral<uint8_t>() /* partNum1 */,
156*57696d54SAkhilesh Sanikop mFdp.ConsumeIntegral<uint8_t>() /* partNum2 */);
157*57696d54SAkhilesh Sanikop }
158*57696d54SAkhilesh Sanikop mGptData.DeletePartition(mFdp.ConsumeIntegral<uint8_t>() /* partNum */);
159*57696d54SAkhilesh Sanikop mGptData.DestroyMBR();
160*57696d54SAkhilesh Sanikop mGptData.DestroyGPT();
161*57696d54SAkhilesh Sanikop }
162*57696d54SAkhilesh Sanikop
LLVMFuzzerInitialize(int *,char ***)163*57696d54SAkhilesh Sanikop extern "C" int LLVMFuzzerInitialize(int *, char ***) {
164*57696d54SAkhilesh Sanikop std::cout.rdbuf(silence.rdbuf());
165*57696d54SAkhilesh Sanikop std::cerr.rdbuf(silence.rdbuf());
166*57696d54SAkhilesh Sanikop return 0;
167*57696d54SAkhilesh Sanikop }
168*57696d54SAkhilesh Sanikop
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)169*57696d54SAkhilesh Sanikop extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
170*57696d54SAkhilesh Sanikop GptfFuzzer gptfFuzzer(data, size);
171*57696d54SAkhilesh Sanikop gptfFuzzer.process();
172*57696d54SAkhilesh Sanikop return 0;
173*57696d54SAkhilesh Sanikop }
174