• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 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 #include "FuzzerInternal.h"
18 #include "ProtoFuzzerMutator.h"
19 
20 #include "test/vts/proto/ComponentSpecificationMessage.pb.h"
21 
22 #include <signal.h>
23 #include <unistd.h>
24 
25 #include <cstdlib>
26 #include <iostream>
27 #include <memory>
28 #include <string>
29 #include <vector>
30 
31 using std::cout;
32 using std::endl;
33 using std::make_unique;
34 using std::string;
35 using std::unique_ptr;
36 using std::vector;
37 
38 // Executed when fuzzer raises SIGABRT signal. This function calls
39 // the signal handler from the libfuzzer library.
sig_handler(int signo)40 extern "C" void sig_handler(int signo) {
41   if (signo == SIGABRT) {
42     cerr << "SIGABRT noticed, please refer to device logcat for the root cause."
43          << endl;
44     fuzzer::Fuzzer::StaticCrashSignalCallback();
45     exit(1);
46   }
47 }
48 
49 namespace android {
50 namespace vts {
51 namespace fuzzer {
52 
53 // 64-bit random number generator.
54 static unique_ptr<Random> random;
55 // Parameters that were passed in to fuzzer.
56 static ProtoFuzzerParams params;
57 // Used to mutate inputs to hal driver.
58 static unique_ptr<ProtoFuzzerMutator> mutator;
59 // Used to exercise HIDL HAL's API.
60 static unique_ptr<ProtoFuzzerRunner> runner;
61 
62 static ProtoFuzzerMutatorConfig mutator_config{
63     // Heuristic: values close to 0 are likely to be meaningful scalar input
64     // values.
__anone18d0ee60102() 65     [](Random &rand) {
66       size_t dice_roll = rand(10);
67       if (dice_roll < 3) {
68         // With probability of 30% return an integer in range [0, 10).
69         return rand(10);
70       } else if (dice_roll >= 3 && dice_roll < 6) {
71         // With probability of 30% return an integer in range [0, 100).
72         return rand(100);
73       } else if (dice_roll >= 6 && dice_roll < 9) {
74         // With probability of 30% return an integer in range [0, 100).
75         return rand(1000);
76       }
77       if (rand(10) == 0) {
78         // With probability of 1% return 0xffffffffffffffff.
79         return 0xffffffffffffffff;
80       }
81       // With probability 9% result is uniformly random.
82       return rand.Rand();
83     },
84     // Odds of an enum being treated like a scalar are 1:1000.
__anone18d0ee60202() 85     {1, 1000}};
86 
87 // Executed when fuzzer process exits. We use this to print out useful
88 // information about the state of the fuzzer.
AtExit()89 static void AtExit() {
90   // Print currently opened interfaces.
91   cerr << "Currently opened interfaces: " << endl;
92   for (const auto &iface_desc : runner->GetOpenedIfaces()) {
93     cerr << iface_desc.first << endl;
94   }
95   cerr << endl;
96   cerr << runner->GetStats().StatsString();
97 }
98 
LLVMFuzzerInitialize(int * argc,char *** argv)99 extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
100   params = ExtractProtoFuzzerParams(*argc, *argv);
101   cerr << params.DebugString() << endl;
102 
103   random = make_unique<Random>(params.seed_);
104   mutator = make_unique<ProtoFuzzerMutator>(
105       *random.get(), ExtractPredefinedTypes(params.comp_specs_),
106       mutator_config);
107   runner = make_unique<ProtoFuzzerRunner>(params.comp_specs_);
108 
109   runner->Init(params.target_iface_, params.binder_mode_);
110   // Register atexit handler after all static objects' initialization.
111   std::atexit(AtExit);
112   // Register signal handler for SIGABRT.
113   signal(SIGABRT, sig_handler);
114 
115   return 0;
116 }
117 
LLVMFuzzerCustomMutator(uint8_t * data,size_t size,size_t max_size,unsigned int seed)118 extern "C" size_t LLVMFuzzerCustomMutator(uint8_t *data, size_t size,
119                                           size_t max_size, unsigned int seed) {
120   ExecSpec exec_spec{};
121   // An Execution is randomly generated if:
122   // 1. It can't be serialized from the given buffer OR
123   // 2. The runner has opened interfaces that have not been touched.
124   // Otherwise, the Execution is mutated.
125   if (!FromArray(data, size, &exec_spec) || runner->UntouchedIfaces()) {
126     exec_spec =
127         mutator->RandomGen(runner->GetOpenedIfaces(), params.exec_size_);
128   } else {
129     mutator->Mutate(runner->GetOpenedIfaces(), &exec_spec);
130   }
131 
132   if (static_cast<size_t>(exec_spec.ByteSize()) > max_size) {
133     cerr << "execution specification message exceeded maximum size." << endl;
134     cerr << max_size << endl;
135     cerr << static_cast<size_t>(exec_spec.ByteSize()) << endl;
136     std::abort();
137   }
138   return ToArray(data, max_size, &exec_spec);
139 }
140 
LLVMFuzzerCustomCrossOver(const uint8_t * data1,size_t size1,const uint8_t * data2,size_t size2,uint8_t * out,size_t max_out_size,unsigned int seed)141 extern "C" size_t LLVMFuzzerCustomCrossOver(const uint8_t *data1, size_t size1,
142                                             const uint8_t *data2, size_t size2,
143                                             uint8_t *out, size_t max_out_size,
144                                             unsigned int seed) {
145   ExecSpec exec_spec1{};
146   FromArray(data1, size1, &exec_spec1);
147   int function_call_size1 = exec_spec1.function_call_size();
148 
149   ExecSpec exec_spec2{};
150   FromArray(data2, size2, &exec_spec2);
151   int function_call_size2 = exec_spec2.function_call_size();
152 
153   if (function_call_size1 != static_cast<int>(params.exec_size_)) {
154     if (function_call_size2 != static_cast<int>(params.exec_size_)) {
155       cerr << "Both messages were invalid, aborting." << endl;
156       std::abort();
157     } else {
158       cerr << "Message 1 was invalid, copying message 2." << endl;
159       memcpy(out, data2, size2);
160       return size2;
161     }
162   } else if (function_call_size2 != static_cast<int>(params.exec_size_)) {
163     cerr << "Message 2 was invalid, copying message 1." << endl;
164     memcpy(out, data1, size1);
165     return size1;
166   }
167 
168   ExecSpec exec_spec_out{};
169   for (int i = 0; i < static_cast<int>(params.exec_size_); i++) {
170     FuncCall temp;
171     int dice = rand() % 2;
172     if (dice == 0) {
173       temp = exec_spec1.function_call(i);
174     } else {
175       temp = exec_spec2.function_call(i);
176     }
177     exec_spec_out.add_function_call()->CopyFrom(temp);
178   }
179 
180   if (static_cast<size_t>(exec_spec_out.ByteSize()) > max_out_size) {
181     cerr << "execution specification message exceeded maximum size." << endl;
182     cerr << max_out_size << endl;
183     cerr << static_cast<size_t>(exec_spec_out.ByteSize()) << endl;
184     std::abort();
185   }
186   return ToArray(out, max_out_size, &exec_spec_out);
187 }
188 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)189 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
190   ExecSpec exec_spec{};
191   if (!FromArray(data, size, &exec_spec)) {
192     cerr << "Failed to deserialize an ExecSpec." << endl;
193     return 0;
194   }
195   runner->Execute(exec_spec);
196   return 0;
197 }
198 
199 }  // namespace fuzzer
200 }  // namespace vts
201 }  // namespace android
202