1 /*
2 * Copyright 2020 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 // Authors: corbin.souffrant@leviathansecurity.com
17 // brian.balling@leviathansecurity.com
18
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <unistd.h>
22
23 #include <memory>
24 #include <string>
25 #include <thread>
26 #include <utility>
27
28 #include <fuzzer/FuzzedDataProvider.h>
29 #include <pdx/rpc/argument_encoder.h>
30 #include <pdx/rpc/array_wrapper.h>
31 #include <pdx/rpc/default_initialization_allocator.h>
32 #include <pdx/rpc/payload.h>
33 #include <pdx/rpc/serializable.h>
34 #include <pdx/rpc/serialization.h>
35 #include <pdx/rpc/string_wrapper.h>
36 #include <pdx/utility.h>
37
38 using namespace android::pdx;
39 using namespace android::pdx::rpc;
40
41 struct FuzzType {
42 int a;
43 float b;
44 std::string c;
45
FuzzTypeFuzzType46 FuzzType() {}
FuzzTypeFuzzType47 FuzzType(int a, float b, const std::string& c) : a(a), b(b), c(c) {}
48
49 private:
50 PDX_SERIALIZABLE_MEMBERS(FuzzType, a, b, c);
51 };
52
53 // Fuzzer for Serialization operations, this is mostly just lifted from the
54 // existing test cases to use fuzzed values as inputs.
FuzzSerializeDeserialize(const uint8_t * data,size_t size)55 void FuzzSerializeDeserialize(const uint8_t* data, size_t size) {
56 FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
57 Payload result;
58
59 // Currently, only fuzzing subset of types. In the future, may want
60 // to add more difficult to generate types like array, map, enum, etc...
61 bool b_val = fdp.ConsumeBool();
62 uint8_t u8_val = fdp.ConsumeIntegral<uint8_t>();
63 uint16_t u16_val = fdp.ConsumeIntegral<uint16_t>();
64 uint32_t u32_val = fdp.ConsumeIntegral<uint32_t>();
65 uint64_t u64_val = fdp.ConsumeIntegral<uint64_t>();
66 int8_t i8_val = fdp.ConsumeIntegral<int8_t>();
67 int16_t i16_val = fdp.ConsumeIntegral<uint16_t>();
68 int32_t i32_val = fdp.ConsumeIntegral<uint32_t>();
69 int64_t i64_val = fdp.ConsumeIntegral<uint64_t>();
70 float f_val = fdp.ConsumeFloatingPoint<float>();
71 double d_val = fdp.ConsumeFloatingPoint<double>();
72 std::string s_val = fdp.ConsumeRandomLengthString(fdp.remaining_bytes());
73 std::vector<uint8_t> vec_val =
74 fdp.ConsumeBytes<uint8_t>(fdp.remaining_bytes());
75 FuzzType t1_val{reinterpret_cast<int>(i32_val), f_val, s_val};
76
77 // Types need to be individually fuzzed because code path changes depending
78 // on which type is being serialized/deserialized.
79 Serialize(b_val, &result);
80 Deserialize(&b_val, &result);
81 Serialize(u8_val, &result);
82 Deserialize(&u8_val, &result);
83 Serialize(u16_val, &result);
84 Deserialize(&u16_val, &result);
85 Serialize(u32_val, &result);
86 Deserialize(&u32_val, &result);
87 Serialize(u64_val, &result);
88 Deserialize(&u64_val, &result);
89 Serialize(i8_val, &result);
90 Deserialize(&i8_val, &result);
91 Serialize(i16_val, &result);
92 Deserialize(&i16_val, &result);
93 Serialize(i32_val, &result);
94 Deserialize(&i32_val, &result);
95 Serialize(i64_val, &result);
96 Deserialize(&i64_val, &result);
97 Serialize(f_val, &result);
98 Deserialize(&f_val, &result);
99 Serialize(d_val, &result);
100 Deserialize(&d_val, &result);
101 Serialize(s_val, &result);
102 Deserialize(&s_val, &result);
103 Serialize(WrapString(s_val), &result);
104 Deserialize(&s_val, &result);
105 Serialize(vec_val, &result);
106 Deserialize(&vec_val, &result);
107 Serialize(t1_val, &result);
108 Deserialize(&t1_val, &result);
109 }
110
FuzzDeserializeUint8(const uint8_t * data,size_t size)111 void FuzzDeserializeUint8(const uint8_t* data, size_t size) {
112 FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
113 Payload buffer = {ENCODING_TYPE_UINT8, fdp.ConsumeIntegral<uint8_t>()};
114 std::uint8_t result;
115 Deserialize(&result, &buffer);
116 }
117
FuzzDeserializeUint16(const uint8_t * data,size_t size)118 void FuzzDeserializeUint16(const uint8_t* data, size_t size) {
119 FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
120 Payload buffer = {ENCODING_TYPE_UINT16, fdp.ConsumeIntegral<uint8_t>(),
121 fdp.ConsumeIntegral<uint8_t>()};
122 std::uint16_t result;
123 Deserialize(&result, &buffer);
124 }
125
FuzzDeserializeUint32(const uint8_t * data,size_t size)126 void FuzzDeserializeUint32(const uint8_t* data, size_t size) {
127 FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
128 Payload buffer = {ENCODING_TYPE_UINT32, fdp.ConsumeIntegral<uint8_t>(),
129 fdp.ConsumeIntegral<uint8_t>(),
130 fdp.ConsumeIntegral<uint8_t>(),
131 fdp.ConsumeIntegral<uint8_t>()};
132 std::uint32_t result;
133 Deserialize(&result, &buffer);
134 }
135
FuzzDeserializeUint64(const uint8_t * data,size_t size)136 void FuzzDeserializeUint64(const uint8_t* data, size_t size) {
137 FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
138 Payload buffer = {
139 ENCODING_TYPE_UINT64, fdp.ConsumeIntegral<uint8_t>(),
140 fdp.ConsumeIntegral<uint8_t>(), fdp.ConsumeIntegral<uint8_t>(),
141 fdp.ConsumeIntegral<uint8_t>(), fdp.ConsumeIntegral<uint8_t>(),
142 fdp.ConsumeIntegral<uint8_t>(), fdp.ConsumeIntegral<uint8_t>(),
143 fdp.ConsumeIntegral<uint8_t>()};
144 std::uint64_t result;
145 Deserialize(&result, &buffer);
146 }
147
FuzzDeserializeInt8(const uint8_t * data,size_t size)148 void FuzzDeserializeInt8(const uint8_t* data, size_t size) {
149 FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
150 Payload buffer = {ENCODING_TYPE_INT8, fdp.ConsumeIntegral<uint8_t>()};
151 std::int8_t result;
152 Deserialize(&result, &buffer);
153 }
154
FuzzDeserializeInt16(const uint8_t * data,size_t size)155 void FuzzDeserializeInt16(const uint8_t* data, size_t size) {
156 FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
157 Payload buffer = {ENCODING_TYPE_INT16, fdp.ConsumeIntegral<uint8_t>(),
158 fdp.ConsumeIntegral<uint8_t>()};
159 std::int16_t result;
160 Deserialize(&result, &buffer);
161 }
162
FuzzDeserializeInt32(const uint8_t * data,size_t size)163 void FuzzDeserializeInt32(const uint8_t* data, size_t size) {
164 FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
165 Payload buffer = {ENCODING_TYPE_INT32, fdp.ConsumeIntegral<uint8_t>(),
166 fdp.ConsumeIntegral<uint8_t>(),
167 fdp.ConsumeIntegral<uint8_t>(),
168 fdp.ConsumeIntegral<uint8_t>()};
169 std::int32_t result;
170 Deserialize(&result, &buffer);
171 }
172
FuzzDeserializeInt64(const uint8_t * data,size_t size)173 void FuzzDeserializeInt64(const uint8_t* data, size_t size) {
174 FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
175 Payload buffer = {ENCODING_TYPE_INT64,
176 fdp.ConsumeIntegral<uint8_t>(),
177 fdp.ConsumeIntegral<uint8_t>(),
178 fdp.ConsumeIntegral<uint8_t>(),
179 fdp.ConsumeIntegral<uint8_t>(),
180 fdp.ConsumeIntegral<uint8_t>(),
181 fdp.ConsumeIntegral<uint8_t>(),
182 fdp.ConsumeIntegral<uint8_t>(),
183 fdp.ConsumeIntegral<uint8_t>()};
184 std::int64_t result;
185 Deserialize(&result, &buffer);
186 }
187
FuzzDeserializeFloat32(const uint8_t * data,size_t size)188 void FuzzDeserializeFloat32(const uint8_t* data, size_t size) {
189 FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
190 Payload buffer = {ENCODING_TYPE_FLOAT32, fdp.ConsumeIntegral<uint8_t>(),
191 fdp.ConsumeIntegral<uint8_t>(),
192 fdp.ConsumeIntegral<uint8_t>(),
193 fdp.ConsumeIntegral<uint8_t>()};
194 float floatResult;
195 Deserialize(&floatResult, &buffer);
196
197 buffer.Rewind();
198 double doubleResult;
199 Deserialize(&doubleResult, &buffer);
200 }
201
FuzzDeserializeFloat64(const uint8_t * data,size_t size)202 void FuzzDeserializeFloat64(const uint8_t* data, size_t size) {
203 FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
204 Payload buffer = {
205 ENCODING_TYPE_FLOAT64, fdp.ConsumeIntegral<uint8_t>(),
206 fdp.ConsumeIntegral<uint8_t>(), fdp.ConsumeIntegral<uint8_t>(),
207 fdp.ConsumeIntegral<uint8_t>(), fdp.ConsumeIntegral<uint8_t>(),
208 fdp.ConsumeIntegral<uint8_t>(), fdp.ConsumeIntegral<uint8_t>(),
209 fdp.ConsumeIntegral<uint8_t>()};
210 double result;
211 Deserialize(&result, &buffer);
212 }
213
FuzzDeserializeFixstr(const uint8_t * data,size_t size)214 void FuzzDeserializeFixstr(const uint8_t* data, size_t size) {
215 FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
216 std::string s_val = fdp.ConsumeRemainingBytesAsString();
217 Payload buffer = {ENCODING_TYPE_FIXSTR_MAX};
218 for (std::string::iterator iter = s_val.begin(); iter != s_val.end();
219 iter++) {
220 buffer.Append(1, *iter);
221 }
222 std::string result;
223 Deserialize(&result, &buffer);
224 }
225
FuzzDeserializeFixmap(const uint8_t * data,size_t size)226 void FuzzDeserializeFixmap(const uint8_t* data, size_t size) {
227 FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
228 Payload buffer = {ENCODING_TYPE_FIXMAP_MAX};
229 // Fill the map with the fuzzed data, not attempting to
230 // make a valid map
231 while (fdp.remaining_bytes() > 0) {
232 buffer.Append(1, fdp.ConsumeIntegral<uint8_t>());
233 }
234
235 std::map<std::uint32_t, std::uint32_t> result;
236 Deserialize(&result, &buffer);
237
238 buffer.Rewind();
239 std::unordered_map<std::uint32_t, std::uint32_t> unorderedResult;
240 Deserialize(&unorderedResult, &buffer);
241 }
242
FuzzDeserializeVariant(const uint8_t * data,size_t size)243 void FuzzDeserializeVariant(const uint8_t* data, size_t size) {
244 FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
245 Payload buffer = {ENCODING_TYPE_INT16,
246 ENCODING_TYPE_FLOAT32,
247 ENCODING_TYPE_FIXSTR_MAX,
248 fdp.ConsumeIntegral<uint8_t>(),
249 fdp.ConsumeIntegral<uint8_t>(),
250 fdp.ConsumeIntegral<uint8_t>(),
251 fdp.ConsumeIntegral<uint8_t>(),
252 fdp.ConsumeIntegral<uint8_t>(),
253 fdp.ConsumeIntegral<uint8_t>(),
254 fdp.ConsumeIntegral<uint8_t>(),
255 fdp.ConsumeIntegral<uint8_t>()};
256 // Add the rest of the data as a string
257 std::string s_val = fdp.ConsumeRemainingBytesAsString();
258 for (std::string::iterator iter = s_val.begin(); iter != s_val.end();
259 iter++) {
260 buffer.Append(1, *iter);
261 }
262 Variant<int, float, std::string> result;
263 Deserialize(&result, &buffer);
264 }
265
266 // Attempts to deserialize fuzzed data as various types
FuzzDeserialize(const uint8_t * data,size_t size)267 void FuzzDeserialize(const uint8_t* data, size_t size) {
268 FuzzDeserializeUint8(data, size);
269 FuzzDeserializeUint16(data, size);
270 FuzzDeserializeUint32(data, size);
271 FuzzDeserializeUint64(data, size);
272 FuzzDeserializeInt8(data, size);
273 FuzzDeserializeInt16(data, size);
274 FuzzDeserializeInt32(data, size);
275 FuzzDeserializeInt64(data, size);
276 FuzzDeserializeFloat32(data, size);
277 FuzzDeserializeFloat64(data, size);
278 FuzzDeserializeFixstr(data, size);
279 FuzzDeserializeFixmap(data, size);
280 FuzzDeserializeVariant(data, size);
281 }
282
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)283 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
284 FuzzSerializeDeserialize(data, size);
285 FuzzDeserialize(data, size);
286
287 return 0;
288 }
289