1 /*
2 * Copyright (C) 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 #include "component_loader/HalDriverLoader.h"
17
18 #include <cutils/properties.h>
19 #include <dirent.h>
20 #include <google/protobuf/text_format.h>
21 #include <iostream>
22
23 #include "utils/InterfaceSpecUtil.h"
24 #include "utils/StringUtil.h"
25
26 static constexpr const char* kSpecFileExt = ".vts";
27 static constexpr const char* kDefaultHwbinderServiceName = "default";
28
29 namespace android {
30 namespace vts {
31
HalDriverLoader(const string dir_path,int epoch_count,const string & callback_socket_name)32 HalDriverLoader::HalDriverLoader(const string dir_path, int epoch_count,
33 const string& callback_socket_name)
34 : dir_path_(dir_path),
35 epoch_count_(epoch_count),
36 callback_socket_name_(callback_socket_name) {}
37
FindComponentSpecification(const int component_class,const string & package_name,const float version,const string & component_name,const int component_type,const string & submodule_name,ComponentSpecificationMessage * spec_msg)38 bool HalDriverLoader::FindComponentSpecification(
39 const int component_class, const string& package_name, const float version,
40 const string& component_name, const int component_type,
41 const string& submodule_name, ComponentSpecificationMessage* spec_msg) {
42 DIR* dir;
43 struct dirent* ent;
44
45 // Derive the package-specific dir which contains .vts files
46 string driver_lib_dir = dir_path_;
47 if (!endsWith(driver_lib_dir, "/")) {
48 driver_lib_dir += "/";
49 }
50 string package_path = package_name;
51 ReplaceSubString(package_path, ".", "/");
52 driver_lib_dir += package_path + "/";
53 driver_lib_dir += GetVersionString(version);
54
55 if (!(dir = opendir(driver_lib_dir.c_str()))) {
56 cerr << __func__ << ": Can't open dir " << driver_lib_dir << endl;
57 return false;
58 }
59
60 while ((ent = readdir(dir))) {
61 if (ent->d_type == DT_REG &&
62 string(ent->d_name).find(kSpecFileExt) != std::string::npos) {
63 cout << __func__ << ": Checking a file " << ent->d_name << endl;
64 const string file_path = driver_lib_dir + "/" + string(ent->d_name);
65 if (ParseInterfaceSpec(file_path.c_str(), spec_msg)) {
66 if (spec_msg->component_class() != component_class) {
67 continue;
68 }
69 if (spec_msg->component_class() != HAL_HIDL) {
70 if (spec_msg->component_type() != component_type ||
71 spec_msg->component_type_version() != version) {
72 continue;
73 }
74 if (!submodule_name.empty()) {
75 if (spec_msg->component_class() != HAL_CONVENTIONAL_SUBMODULE ||
76 spec_msg->original_data_structure_name() != submodule_name) {
77 continue;
78 }
79 }
80 closedir(dir);
81 return true;
82 } else {
83 if (spec_msg->package() != package_name ||
84 spec_msg->component_type_version() != version) {
85 continue;
86 }
87 if (!component_name.empty()) {
88 if (spec_msg->component_name() != component_name) {
89 continue;
90 }
91 }
92 closedir(dir);
93 return true;
94 }
95 }
96 }
97 }
98 closedir(dir);
99 return false;
100 }
101
GetDriver(const string & driver_lib_path,const ComponentSpecificationMessage & spec_msg,const string & hw_binder_service_name,const uint64_t interface_pt,bool with_interface_pointer,const string & dll_file_name,const string & target_func_name)102 DriverBase* HalDriverLoader::GetDriver(
103 const string& driver_lib_path,
104 const ComponentSpecificationMessage& spec_msg,
105 const string& hw_binder_service_name, const uint64_t interface_pt,
106 bool with_interface_pointer, const string& dll_file_name,
107 const string& target_func_name) {
108 DriverBase* driver = nullptr;
109 if (spec_msg.component_class() == HAL_HIDL) {
110 driver = GetHidlHalDriver(driver_lib_path, spec_msg, hw_binder_service_name,
111 interface_pt, with_interface_pointer);
112 } else {
113 driver = GetConventionalHalDriver(driver_lib_path, spec_msg, dll_file_name,
114 target_func_name);
115 }
116 cout << __func__ << ":" << __LINE__ << " loaded target comp" << endl;
117
118 return driver;
119 }
120
GetConventionalHalDriver(const string & driver_lib_path,const ComponentSpecificationMessage & spec_msg,const string & dll_file_name,const string &)121 DriverBase* HalDriverLoader::GetConventionalHalDriver(
122 const string& driver_lib_path,
123 const ComponentSpecificationMessage& spec_msg, const string& dll_file_name,
124 const string& /*target_func_name*/) {
125 DriverBase* driver = LoadDriver(driver_lib_path, spec_msg);
126 if (!driver) {
127 cerr << __func__ << ": couldn't get a driver base class" << endl;
128 return nullptr;
129 }
130 if (!driver->LoadTargetComponent(dll_file_name.c_str())) {
131 cerr << __FUNCTION__ << ": couldn't load target component file, "
132 << dll_file_name << endl;
133 return nullptr;
134 }
135 return driver;
136 /*
137 * TODO: now always return the fuzzer. this change is due to the difficulty
138 * in checking nested apis although that's possible. need to check whether
139 * Fuzz() found the function, while still distinguishing the difference
140 * between that and defined but non-set api.
141 if (!strcmp(target_func_name, "#Open")) return driver;
142
143 for (const vts::FunctionSpecificationMessage& func_msg : spec_msg.api())
144 {
145 cout << "checking " << func_msg.name() << endl;
146 if (!strcmp(target_func_name, func_msg.name().c_str())) {
147 return driver;
148 }
149 }
150 return NULL;
151 */
152 }
153
GetDriverForSubModule(const string & spec_lib_file_path,const ComponentSpecificationMessage & spec_msg,void * object_pointer)154 DriverBase* HalDriverLoader::GetDriverForSubModule(
155 const string& spec_lib_file_path,
156 const ComponentSpecificationMessage& spec_msg, void* object_pointer) {
157 cout << __func__ << ":" << __LINE__ << " "
158 << "entry object_pointer " << ((uint64_t)object_pointer) << endl;
159 DriverBase* driver = LoadDriver(spec_lib_file_path, spec_msg);
160 if (!driver) {
161 cerr << __FUNCTION__ << ": couldn't get a driver base class" << endl;
162 return nullptr;
163 }
164
165 cout << __func__ << ":" << __LINE__ << " "
166 << "got fuzzer" << endl;
167 if (spec_msg.component_class() == HAL_HIDL) {
168 cerr << __func__ << " HIDL not supported" << endl;
169 return nullptr;
170 } else {
171 if (!driver->SetTargetObject(object_pointer)) {
172 cerr << __FUNCTION__ << ": couldn't set target object" << endl;
173 return nullptr;
174 }
175 }
176 cout << __func__ << ":" << __LINE__ << " "
177 << "loaded target comp" << endl;
178 return driver;
179 }
180
GetFuzzerBaseAndAddAllFunctionsToQueue(const char * driver_lib_path,const ComponentSpecificationMessage & iface_spec_msg,const char * dll_file_name,const char * hw_service_name)181 DriverBase* HalDriverLoader::GetFuzzerBaseAndAddAllFunctionsToQueue(
182 const char* driver_lib_path,
183 const ComponentSpecificationMessage& iface_spec_msg,
184 const char* dll_file_name, const char* hw_service_name) {
185 DriverBase* driver = GetDriver(driver_lib_path, iface_spec_msg,
186 hw_service_name, 0, false, dll_file_name, "");
187 if (!driver) {
188 cerr << __FUNCTION__ << ": couldn't get a driver base class" << endl;
189 return NULL;
190 }
191
192 for (const FunctionSpecificationMessage& func_msg :
193 iface_spec_msg.interface().api()) {
194 cout << "Add a job " << func_msg.name() << endl;
195 FunctionSpecificationMessage* func_msg_copy = func_msg.New();
196 func_msg_copy->CopyFrom(func_msg);
197 job_queue_.push(make_pair(func_msg_copy, driver));
198 }
199 return driver;
200 }
201
GetHidlHalDriver(const string & driver_lib_path,const ComponentSpecificationMessage & spec_msg,const string & hal_service_name,const uint64_t interface_pt,bool with_interface_pt)202 DriverBase* HalDriverLoader::GetHidlHalDriver(
203 const string& driver_lib_path,
204 const ComponentSpecificationMessage& spec_msg,
205 const string& hal_service_name, const uint64_t interface_pt,
206 bool with_interface_pt) {
207 string package_name = spec_msg.package();
208
209 DriverBase* driver = nullptr;
210 if (with_interface_pt) {
211 driver =
212 LoadDriverWithInterfacePointer(driver_lib_path, spec_msg, interface_pt);
213 } else {
214 driver = LoadDriver(driver_lib_path, spec_msg);
215 }
216 if (!driver) {
217 cerr << __func__ << ": couldn't get a driver base class" << endl;
218 return nullptr;
219 }
220 cout << __func__ << ":" << __LINE__ << " "
221 << "got driver" << endl;
222
223 if (!with_interface_pt) {
224 string service_name;
225 if (!hal_service_name.empty()) {
226 service_name = hal_service_name;
227 } else {
228 service_name = kDefaultHwbinderServiceName;
229 }
230
231 char get_sub_property[PROPERTY_VALUE_MAX];
232 bool get_stub = false; /* default is binderized */
233 if (property_get("vts.hidl.get_stub", get_sub_property, "") > 0) {
234 if (!strcmp(get_sub_property, "true") ||
235 !strcmp(get_sub_property, "True") || !strcmp(get_sub_property, "1")) {
236 get_stub = true;
237 }
238 }
239 if (!driver->GetService(get_stub, service_name.c_str())) {
240 cerr << __FUNCTION__ << ": couldn't get service" << endl;
241 return nullptr;
242 }
243 } else {
244 cout << __func__ << ":" << __LINE__
245 << " created DriverBase with interface pointer:" << interface_pt
246 << endl;
247 }
248 cout << __func__ << ":" << __LINE__ << " loaded target comp" << endl;
249 return driver;
250 }
251
LoadDriver(const string & driver_lib_path,const ComponentSpecificationMessage & spec_msg)252 DriverBase* HalDriverLoader::LoadDriver(
253 const string& driver_lib_path,
254 const ComponentSpecificationMessage& spec_msg) {
255 if (!dll_loader_.Load(driver_lib_path.c_str(), false)) {
256 cerr << __func__ << ": failed to load " << driver_lib_path << endl;
257 return nullptr;
258 }
259 cout << "DLL loaded " << driver_lib_path << endl;
260 string function_name_prefix = GetFunctionNamePrefix(spec_msg);
261 loader_function func =
262 dll_loader_.GetLoaderFunction(function_name_prefix.c_str());
263 if (!func) {
264 cerr << __func__ << ": function not found." << endl;
265 return nullptr;
266 }
267 cout << __func__ << ": function found; trying to call." << endl;
268 DriverBase* driver = func();
269 return driver;
270 }
271
LoadDriverWithInterfacePointer(const string & driver_lib_path,const ComponentSpecificationMessage & spec_msg,const uint64_t interface_pt)272 DriverBase* HalDriverLoader::LoadDriverWithInterfacePointer(
273 const string& driver_lib_path,
274 const ComponentSpecificationMessage& spec_msg,
275 const uint64_t interface_pt) {
276 // Assumption: no shared library lookup is needed because that is handled
277 // the by the driver's linking dependency.
278 // Example: name (android::hardware::gnss::V1_0::IAGnssRil) converted to
279 // function name (vts_func_4_android_hardware_tests_bar_V1_0_IBar_with_arg)
280 if (!dll_loader_.Load(driver_lib_path.c_str(), false)) {
281 cerr << __func__ << ": failed to load " << driver_lib_path << endl;
282 return nullptr;
283 }
284 cout << "DLL loaded " << driver_lib_path << endl;
285 string function_name_prefix = GetFunctionNamePrefix(spec_msg);
286 function_name_prefix += "with_arg";
287 loader_function_with_arg func =
288 dll_loader_.GetLoaderFunctionWithArg(function_name_prefix.c_str());
289 if (!func) {
290 cerr << __func__ << ": function not found." << endl;
291 return nullptr;
292 }
293 return func(interface_pt);
294 }
295
Process(const char * dll_file_name,const char * spec_lib_file_path,int target_class,int target_type,float target_version,const char * target_package,const char * target_component_name,const char * hal_service_name)296 bool HalDriverLoader::Process(const char* dll_file_name,
297 const char* spec_lib_file_path, int target_class,
298 int target_type, float target_version,
299 const char* target_package,
300 const char* target_component_name,
301 const char* hal_service_name) {
302 ComponentSpecificationMessage interface_specification_message;
303 if (!FindComponentSpecification(target_class, target_package, target_version,
304 target_component_name, target_type, "",
305 &interface_specification_message)) {
306 cerr << __func__ << ": no interface specification file found for class "
307 << target_class << " type " << target_type << " version "
308 << target_version << endl;
309 return false;
310 }
311
312 if (!GetFuzzerBaseAndAddAllFunctionsToQueue(
313 spec_lib_file_path, interface_specification_message, dll_file_name,
314 hal_service_name)) {
315 return false;
316 }
317
318 for (int i = 0; i < epoch_count_; i++) {
319 // by default, breath-first-searching is used.
320 if (job_queue_.empty()) {
321 cerr << "no more job to process; stopping after epoch " << i << endl;
322 break;
323 }
324
325 pair<vts::FunctionSpecificationMessage*, DriverBase*> curr_job =
326 job_queue_.front();
327 job_queue_.pop();
328
329 vts::FunctionSpecificationMessage* func_msg = curr_job.first;
330 DriverBase* func_fuzzer = curr_job.second;
331
332 void* result;
333 FunctionSpecificationMessage result_msg;
334 cout << "Iteration " << (i + 1) << " Function " << func_msg->name() << endl;
335 // For Hidl HAL, use CallFunction method.
336 if (interface_specification_message.component_class() == HAL_HIDL) {
337 func_fuzzer->CallFunction(*func_msg, callback_socket_name_, &result_msg);
338 } else {
339 func_fuzzer->Fuzz(func_msg, &result, callback_socket_name_);
340 }
341 if (func_msg->return_type().type() == TYPE_PREDEFINED) {
342 if (result != NULL) {
343 // loads that interface spec and enqueues all functions.
344 cout << __FUNCTION__
345 << " return type: " << func_msg->return_type().predefined_type()
346 << endl;
347 // TODO: handle the case when size > 1
348 string submodule_name = func_msg->return_type().predefined_type();
349 while (!submodule_name.empty() &&
350 (std::isspace(submodule_name.back()) ||
351 submodule_name.back() == '*')) {
352 submodule_name.pop_back();
353 }
354 ComponentSpecificationMessage iface_spec_msg;
355 if (FindComponentSpecification(target_class, "", target_version, "",
356 target_type, submodule_name,
357 &iface_spec_msg)) {
358 cout << __FUNCTION__ << " submodule found - " << submodule_name
359 << endl;
360 if (!GetFuzzerBaseAndAddAllFunctionsToQueue(
361 spec_lib_file_path, iface_spec_msg, dll_file_name,
362 hal_service_name)) {
363 return false;
364 }
365 } else {
366 cout << __FUNCTION__ << " submodule not found - " << submodule_name
367 << endl;
368 }
369 } else {
370 cout << __FUNCTION__ << " return value = NULL" << endl;
371 }
372 }
373 }
374
375 return true;
376 }
377
378 } // namespace vts
379 } // namespace android
380