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