• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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