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 /*
18 * Example usage (for angler 64-bit devices):
19 * $ fuzzer --class=hal_conventional --type=light --version=1.0
20 * /system/lib64/hw/lights.angler.so
21 * $ fuzzer --class=hal_conventional --type=gps --version=1.0
22 * /system/lib64/hw/gps.msm8994.so
23 *
24 * $ LD_LIBRARY_PATH=/data/local/tmp/64 ./fuzzer64 --class=hal --type=light \
25 * --version=1.0 --spec_dir=/data/local/tmp/spec \
26 * /data/local/tmp/64/hal/lights.vts.so
27 *
28 * Example usage (for GCE virtual devices):
29 * $ fuzzer --class=hal_conventional --type=light --version=1.0
30 * /system/lib/hw/lights.gce_x86.so
31 * $ fuzzer --class=hal_conventional --type=gps --version=1.0
32 * /system/lib/hw/gps.gce_x86.so
33 */
34
35 #include <getopt.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40
41 #include <algorithm>
42 #include <iostream>
43 #include <string>
44
45 #include "binder/VtsFuzzerBinderService.h"
46 #include "specification_parser/InterfaceSpecificationParser.h"
47 #include "specification_parser/SpecificationBuilder.h"
48 #include "replayer/VtsHidlHalReplayer.h"
49
50 #include "BinderServer.h"
51 #include "SocketServer.h"
52
53 using namespace std;
54 using namespace android;
55
56 #define INTERFACE_SPEC_LIB_FILENAME "libvts_interfacespecification.so"
57 #define PASSED_MARKER "[ PASSED ]"
58
59 // the default epoch count where an epoch is the time for a fuzz test run
60 // (e.g., a function call).
61 static const int kDefaultEpochCount = 100;
62
63 // Dumps usage on stderr.
usage()64 static void usage() {
65 // TODO(zhuoyao): update the usage message.
66 fprintf(
67 stderr,
68 "Usage: fuzzer [options] <target HAL file path>\n"
69 "\n"
70 "Android fuzzer v0.1. To fuzz Android system.\n"
71 "\n"
72 "Options:\n"
73 "--help\n"
74 " Show this message.\n"
75 "\n"
76 "Recording continues until Ctrl-C is hit or the time limit is reached.\n"
77 "\n");
78 }
79
80 // Parses command args and kicks things off.
main(int argc,char * const argv[])81 int main(int argc, char* const argv[]) {
82 static const struct option longOptions[] = {
83 {"help", no_argument, NULL, 'h'},
84 {"class", required_argument, NULL, 'c'},
85 {"type", required_argument, NULL, 't'},
86 {"version", required_argument, NULL, 'v'},
87 {"epoch_count", required_argument, NULL, 'e'},
88 {"spec_dir", required_argument, NULL, 's'},
89 {"target_package", optional_argument, NULL, 'k'},
90 {"target_component_name", optional_argument, NULL, 'n'},
91 #ifndef VTS_AGENT_DRIVER_COMM_BINDER // socket
92 {"server_socket_path", optional_argument, NULL, 'f'},
93 #else // binder
94 {"service_name", required_argument, NULL, 'n'},
95 #endif
96 {"server", optional_argument, NULL, 'd'},
97 {"callback_socket_name", optional_argument, NULL, 'p'},
98 // TODO(zhuoyao):make mode a required_argument to support different
99 // execution mode. e.g.: fuzzer/driver/replayer.
100 {"mode", optional_argument, NULL, 'm'},
101 {"trace_path", optional_argument, NULL, 'r'},
102 {"spec_path", optional_argument, NULL, 'a'},
103 {"hal_service_name", optional_argument, NULL, 'j'},
104 {NULL, 0, NULL, 0}};
105 int target_class;
106 int target_type;
107 float target_version = 1.0;
108 int epoch_count = kDefaultEpochCount;
109 string spec_dir_path(DEFAULT_SPEC_DIR_PATH);
110 bool server = false;
111 #ifndef VTS_AGENT_DRIVER_COMM_BINDER // socket
112 string server_socket_path;
113 #else // binder
114 string service_name(VTS_FUZZER_BINDER_SERVICE_NAME);
115 #endif
116 string target_package;
117 string target_component_name;
118 string callback_socket_name;
119 string mode;
120 string trace_path;
121 string spec_path;
122 string hal_service_name = "default";
123
124 while (true) {
125 int optionIndex = 0;
126 int ic = getopt_long(argc, argv, "", longOptions, &optionIndex);
127 if (ic == -1) {
128 break;
129 }
130
131 switch (ic) {
132 case 'h':
133 usage();
134 return 0;
135 case 'c': {
136 string target_class_str = string(optarg);
137 transform(target_class_str.begin(), target_class_str.end(),
138 target_class_str.begin(), ::tolower);
139 if (!strcmp(target_class_str.c_str(), "hal_conventional")) {
140 target_class = vts::HAL_CONVENTIONAL;
141 } else if (!strcmp(target_class_str.c_str(), "hal_hidl")) {
142 target_class = vts::HAL_HIDL;
143 } else {
144 target_class = 0;
145 }
146 break;
147 }
148 case 't': {
149 string target_type_str = string(optarg);
150 transform(target_type_str.begin(), target_type_str.end(),
151 target_type_str.begin(), ::tolower);
152 if (!strcmp(target_type_str.c_str(), "camera")) {
153 target_type = vts::CAMERA;
154 } else if (!strcmp(target_type_str.c_str(), "gps")) {
155 target_type = vts::GPS;
156 } else if (!strcmp(target_type_str.c_str(), "audio")) {
157 target_type = vts::AUDIO;
158 } else if (!strcmp(target_type_str.c_str(), "light")) {
159 target_type = vts::LIGHT;
160 } else {
161 target_type = 0;
162 }
163 break;
164 }
165 case 'v':
166 target_version = atof(optarg);
167 break;
168 case 'p':
169 callback_socket_name = string(optarg);
170 break;
171 case 'e':
172 epoch_count = atoi(optarg);
173 if (epoch_count <= 0) {
174 fprintf(stderr, "epoch_count must be > 0");
175 return 2;
176 }
177 break;
178 case 's':
179 spec_dir_path = string(optarg);
180 break;
181 #ifndef VTS_AGENT_DRIVER_COMM_BINDER // socket
182 case 'f':
183 server_socket_path = string(optarg);
184 break;
185 #else // binder
186 case 'n':
187 service_name = string(optarg);
188 break;
189 #endif
190 case 'd':
191 server = true;
192 break;
193 case 'k':
194 target_package = string(optarg);
195 break;
196 case 'n':
197 target_component_name = string(optarg);
198 break;
199 case 'm':
200 mode = string(optarg);
201 break;
202 case 'r':
203 trace_path = string(optarg);
204 break;
205 case 'a':
206 spec_path = string(optarg);
207 break;
208 case 'j':
209 hal_service_name = string(optarg);
210 break;
211 default:
212 if (ic != '?') {
213 fprintf(stderr, "getopt_long returned unexpected value 0x%x\n", ic);
214 }
215 return 2;
216 }
217 }
218
219 android::vts::SpecificationBuilder spec_builder(spec_dir_path, epoch_count,
220 callback_socket_name);
221 if (!server) {
222 if (optind != argc - 1) {
223 fprintf(stderr, "Must specify output file (see --help).\n");
224 return 2;
225 }
226 bool success;
227 if (mode == "replay") {
228 android::vts::VtsHidlHalReplayer replayer(spec_path,
229 callback_socket_name);
230 success = replayer.ReplayTrace(argv[optind], trace_path,
231 hal_service_name);
232 } else {
233 success = spec_builder.Process(argv[optind],INTERFACE_SPEC_LIB_FILENAME,
234 target_class, target_type, target_version,
235 target_package.c_str(),
236 target_component_name.c_str());
237 }
238 cout << "Result: " << success << endl;
239 if (success) {
240 cout << endl << PASSED_MARKER << endl;
241 }
242 } else {
243 #ifndef VTS_AGENT_DRIVER_COMM_BINDER // socket
244 android::vts::StartSocketServer(server_socket_path, spec_builder,
245 INTERFACE_SPEC_LIB_FILENAME);
246 #else // binder
247 android::vts::StartBinderServer(service_name, spec_builder,
248 INTERFACE_SPEC_LIB_FILENAME);
249 #endif
250 }
251 return 0;
252 }
253