1 /*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18 #include <record_file.h>
19 #include "fuzzer/FuzzedDataProvider.h"
20
21 using namespace simpleperf;
22 using namespace std;
23 using namespace android;
24 static uint32_t kMaxLen = 100;
25 static uint32_t kMinCount = 1;
26 static uint32_t kMaxCount = 1000;
27 static uint32_t kMinASCII = 0;
28 static uint32_t kMaxASCII = 255;
29
30 class SimplePerfWriterFuzzer {
31 public:
SimplePerfWriterFuzzer(const uint8_t * data,size_t size)32 SimplePerfWriterFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {
33 /**
34 * Use maximum of 80% of buffer to write in FD and save at least 20% for fuzzing other APIs
35 */
36 const int32_t dataSize = mFdp.ConsumeIntegralInRange<int32_t>(0, (size * 80) / 100);
37 std::vector<uint8_t> dataPointer = mFdp.ConsumeBytes<uint8_t>(dataSize);
38 android::base::WriteFully(mTempfile.fd, dataPointer.data(), dataPointer.size());
39 }
40 void process();
41
42 private:
43 FuzzedDataProvider mFdp;
44 TemporaryFile mTempfile;
45 EventAttrIds mAttributeIDs;
46 bool AddEvents();
47 void CreateRecord();
48 };
49
AddEvents()50 bool SimplePerfWriterFuzzer::AddEvents() {
51 size_t eventNo = mFdp.ConsumeIntegralInRange<size_t>(kMinCount, kMaxCount);
52 for (size_t idx = 0; idx < eventNo; ++idx) {
53 string event = mFdp.ConsumeRandomLengthString(kMaxLen);
54 if (event.size() == 0) {
55 event = "cpu-cycles";
56 }
57 uint64_t fakeID = mAttributeIDs.size();
58 mAttributeIDs.resize(mAttributeIDs.size() + 1);
59 EventAttrWithId& attrID = mAttributeIDs.back();
60 std::unique_ptr<EventTypeAndModifier> eventTypeModifier = ParseEventType(event);
61 if (!eventTypeModifier) {
62 return false;
63 }
64 attrID.attr = CreateDefaultPerfEventAttr(eventTypeModifier->event_type);
65 attrID.ids.push_back(fakeID);
66 }
67 return true;
68 }
69
process()70 void SimplePerfWriterFuzzer::process() {
71 std::unique_ptr<RecordFileWriter> writer = RecordFileWriter::CreateInstance(mTempfile.path);
72 if (!writer.get()) {
73 return;
74 }
75 writer->WriteAttrSection(mAttributeIDs);
76 int32_t features = mFdp.ConsumeIntegralInRange<int32_t>(kMinCount, kMaxCount);
77
78 if (!AddEvents()) {
79 return;
80 }
81
82 string event = mFdp.ConsumeRandomLengthString(kMaxLen);
83 size_t index = mFdp.ConsumeIntegralInRange<size_t>(0, mAttributeIDs.size() - 1);
84 perf_event_attr attr = mAttributeIDs[index].attr;
85 MmapRecord mmprcd(
86 attr, mFdp.ConsumeBool() /* in_kernel */, getpid() /* pid */, gettid() /* tid */,
87 mFdp.ConsumeIntegral<uint64_t>() /* addr */, mFdp.ConsumeIntegral<uint64_t>() /* len */,
88 mFdp.ConsumeIntegral<uint64_t>() /* pgoff */, event,
89 mFdp.ConsumeIntegral<uint64_t>() /* event_id */, mFdp.ConsumeIntegral<uint64_t>() /* time */);
90
91 writer->WriteRecord(mmprcd);
92 writer->BeginWriteFeatures(features);
93 std::vector<Dso*> dsos;
94 while (features-- > 0) {
95 auto invokeWriter = mFdp.PickValueInArray<const std::function<void()>>({
96 [&]() {
97 BuildId build_id(mFdp.ConsumeRandomLengthString(kMaxLen));
98 std::vector<BuildIdRecord> buildIdRecords;
99 buildIdRecords.push_back(
100 BuildIdRecord(mFdp.ConsumeBool() /* in_kernel */, getpid() /* pid */, build_id,
101 mFdp.ConsumeRandomLengthString(kMaxLen) /* filename */));
102 writer->WriteBuildIdFeature(buildIdRecords);
103 },
104 [&]() {
105 writer->WriteFeatureString(
106 mFdp.ConsumeBool() ? PerfFileFormat::FEAT_OSRELEASE : PerfFileFormat::FEAT_ARCH,
107 mFdp.ConsumeRandomLengthString(kMaxLen) /* string */);
108 },
109 [&]() {
110 std::vector<std::string> cmdline;
111 cmdline.push_back("simpleperf");
112 int32_t iter = mFdp.ConsumeIntegralInRange<int32_t>(kMinCount, kMaxCount);
113 for (int32_t idx = 0; idx < iter; ++idx) {
114 cmdline.push_back(mFdp.ConsumeRandomLengthString(kMaxLen));
115 }
116 writer->WriteCmdlineFeature(cmdline);
117 },
118 [&]() {
119 int32_t iter = mFdp.ConsumeIntegralInRange<int32_t>(kMinCount, kMaxCount);
120 for (int32_t idx = 0; idx < iter; ++idx) {
121 DsoType dso_type =
122 (DsoType)mFdp.ConsumeIntegralInRange<size_t>(DSO_KERNEL, DSO_UNKNOWN_FILE);
123 std::unique_ptr<Dso> dso =
124 Dso::CreateDso(dso_type, mFdp.ConsumeRandomLengthString(kMaxLen) /* path */,
125 mFdp.ConsumeBool() /* force_64bit */);
126 if (dso) {
127 dsos.push_back(dso.release());
128 }
129 }
130 writer->WriteFileFeatures(dsos);
131 },
132 [&]() {
133 std::unordered_map<std::string, std::string> info_map;
134 int32_t iter = mFdp.ConsumeIntegralInRange<int32_t>(kMinCount, kMaxCount);
135 for (int32_t idx = 0; idx < iter; ++idx) {
136 std::string key = mFdp.ConsumeRandomLengthString(kMaxLen);
137 std::string value = mFdp.ConsumeRandomLengthString(kMaxLen);
138 info_map[key] = value;
139 }
140 writer->WriteMetaInfoFeature(info_map);
141 },
142 [&]() { writer->WriteBranchStackFeature(); },
143 [&]() {
144 std::vector<uint64_t> auxtrace;
145 int32_t iter = mFdp.ConsumeIntegralInRange<int32_t>(kMinCount, kMaxCount);
146 for (int32_t idx = 0; idx < iter; ++idx) {
147 auxtrace.push_back(mFdp.ConsumeIntegral<uint64_t>());
148 }
149 writer->WriteAuxTraceFeature(auxtrace);
150 },
151 [&]() {
152 DebugUnwindFeature debugVector;
153 int32_t iter = mFdp.ConsumeIntegralInRange<int32_t>(kMinCount, kMaxCount);
154 for (int32_t idx = 0; idx < iter; ++idx) {
155 DebugUnwindFile testFile;
156 testFile.path = mFdp.ConsumeRandomLengthString(kMaxLen);
157 testFile.size = kMaxLen;
158 debugVector.push_back(testFile);
159 }
160 writer->WriteDebugUnwindFeature(debugVector);
161 },
162 });
163 invokeWriter();
164 }
165 writer->EndWriteFeatures();
166 writer->Close();
167 for (Dso* dso : dsos) {
168 delete dso;
169 dso = nullptr;
170 }
171 }
172
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)173 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
174 SimplePerfWriterFuzzer simplePerfWriterFuzzer(data, size);
175 simplePerfWriterFuzzer.process();
176 return 0;
177 }
178