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