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 #ifdef STATIC_TARGET_FQ_NAME
54 // Returns parameters used for static fuzzer executables.
55 extern ProtoFuzzerParams ExtractProtoFuzzerStaticParams(int argc, char **argv);
56 #endif
57 
58 // 64-bit random number generator.
59 static unique_ptr<Random> random;
60 // Parameters that were passed in to fuzzer.
61 static ProtoFuzzerParams params;
62 // Used to mutate inputs to hal driver.
63 static unique_ptr<ProtoFuzzerMutator> mutator;
64 // Used to exercise HIDL HAL's API.
65 static unique_ptr<ProtoFuzzerRunner> runner;
66 
67 static ProtoFuzzerMutatorConfig mutator_config{
68     // Heuristic: values close to 0 are likely to be meaningful scalar input
69     // values.
__anon605a8dbd0102() 70     [](Random &rand) {
71       size_t dice_roll = rand(10);
72       if (dice_roll < 3) {
73         // With probability of 30% return an integer in range [0, 10).
74         return rand(10);
75       } else if (dice_roll >= 3 && dice_roll < 6) {
76         // With probability of 30% return an integer in range [0, 100).
77         return rand(100);
78       } else if (dice_roll >= 6 && dice_roll < 9) {
79         // With probability of 30% return an integer in range [0, 100).
80         return rand(1000);
81       }
82       if (rand(10) == 0) {
83         // With probability of 1% return 0xffffffffffffffff.
84         return 0xffffffffffffffff;
85       }
86       // With probability 9% result is uniformly random.
87       return rand.Rand();
88     },
89     // Odds of an enum being treated like a scalar are 1:1000.
__anon605a8dbd0202() 90     {1, 1000}};
91 
92 // Executed when fuzzer process exits. We use this to print out useful
93 // information about the state of the fuzzer.
AtExit()94 static void AtExit() {
95   // Print currently opened interfaces.
96   cerr << "Currently opened interfaces: " << endl;
97   for (const auto &iface_desc : runner->GetOpenedIfaces()) {
98     cerr << iface_desc.first << endl;
99   }
100   cerr << endl;
101   cerr << runner->GetStats().StatsString();
102 }
103 
LLVMFuzzerInitialize(int * argc,char *** argv)104 extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
105 #ifdef STATIC_TARGET_FQ_NAME
106   params = ExtractProtoFuzzerStaticParams(*argc, *argv);
107 #else
108   params = ExtractProtoFuzzerParams(*argc, *argv);
109 #endif
110 
111   cerr << params.DebugString() << endl;
112 
113   random = make_unique<Random>(params.seed_);
114   mutator = make_unique<ProtoFuzzerMutator>(
115       *random.get(), ExtractPredefinedTypes(params.comp_specs_),
116       mutator_config);
117   runner = make_unique<ProtoFuzzerRunner>(params.comp_specs_,
118                                           params.target_fq_name_.version());
119 
120   runner->Init(params.target_fq_name_.name(), params.binder_mode_);
121   // Register atexit handler after all static objects' initialization.
122   std::atexit(AtExit);
123   // Register signal handler for SIGABRT.
124   signal(SIGABRT, sig_handler);
125 
126   return 0;
127 }
128 
LLVMFuzzerCustomMutator(uint8_t * data,size_t size,size_t max_size,unsigned int seed)129 extern "C" size_t LLVMFuzzerCustomMutator(uint8_t *data, size_t size,
130                                           size_t max_size, unsigned int seed) {
131   ExecSpec exec_spec{};
132   // An Execution is randomly generated if:
133   // 1. It can't be serialized from the given buffer OR
134   // 2. The runner has opened interfaces that have not been touched.
135   // Otherwise, the Execution is mutated.
136   if (!FromArray(data, size, &exec_spec) || runner->UntouchedIfaces()) {
137     exec_spec =
138         mutator->RandomGen(runner->GetOpenedIfaces(), params.exec_size_);
139   } else {
140     mutator->Mutate(runner->GetOpenedIfaces(), &exec_spec);
141   }
142 
143   if (static_cast<size_t>(exec_spec.ByteSize()) > max_size) {
144     cerr << "execution specification message exceeded maximum size." << endl;
145     cerr << max_size << endl;
146     cerr << static_cast<size_t>(exec_spec.ByteSize()) << endl;
147     std::abort();
148   }
149   return ToArray(data, max_size, &exec_spec);
150 }
151 
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)152 extern "C" size_t LLVMFuzzerCustomCrossOver(const uint8_t *data1, size_t size1,
153                                             const uint8_t *data2, size_t size2,
154                                             uint8_t *out, size_t max_out_size,
155                                             unsigned int seed) {
156   ExecSpec exec_spec1{};
157   if (!FromArray(data1, size1, &exec_spec1)) {
158     cerr << "Message 1 was invalid." << endl;
159     exec_spec1 =
160         mutator->RandomGen(runner->GetOpenedIfaces(), params.exec_size_);
161   }
162 
163   ExecSpec exec_spec2{};
164   if (!FromArray(data2, size2, &exec_spec2)) {
165     cerr << "Message 2 was invalid." << endl;
166     exec_spec2 =
167         mutator->RandomGen(runner->GetOpenedIfaces(), params.exec_size_);
168   }
169 
170   ExecSpec exec_spec_out{};
171   for (int i = 0; i < static_cast<int>(params.exec_size_); i++) {
172     FuncCall temp;
173     int dice = rand() % 2;
174     if (dice == 0) {
175       temp = exec_spec1.function_call(i);
176     } else {
177       temp = exec_spec2.function_call(i);
178     }
179     exec_spec_out.add_function_call()->CopyFrom(temp);
180   }
181 
182   if (static_cast<size_t>(exec_spec_out.ByteSize()) > max_out_size) {
183     cerr << "execution specification message exceeded maximum size." << endl;
184     cerr << max_out_size << endl;
185     cerr << static_cast<size_t>(exec_spec_out.ByteSize()) << endl;
186     std::abort();
187   }
188   return ToArray(out, max_out_size, &exec_spec_out);
189 }
190 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)191 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
192   ExecSpec exec_spec{};
193   if (!FromArray(data, size, &exec_spec)) {
194     cerr << "Failed to deserialize an ExecSpec." << endl;
195     // Don't generate an ExecSpec here so that libFuzzer knows that the provided
196     // buffer doesn't provide any coverage.
197     return 0;
198   }
199   runner->Execute(exec_spec);
200   return 0;
201 }
202 
203 }  // namespace fuzzer
204 }  // namespace vts
205 }  // namespace android
206