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 #define LOG_TAG "VtsHalDriverLoader"
17 
18 #include "component_loader/HalDriverLoader.h"
19 
20 #include <dirent.h>
21 
22 #include <android-base/logging.h>
23 #include <cutils/properties.h>
24 #include <google/protobuf/text_format.h>
25 
26 #include "utils/InterfaceSpecUtil.h"
27 #include "utils/StringUtil.h"
28 
29 static constexpr const char* kSpecFileExt = ".vts";
30 static constexpr const char* kDefaultHwbinderServiceName = "default";
31 
32 namespace android {
33 namespace vts {
34 
HalDriverLoader(const string dir_path,int epoch_count,const string & callback_socket_name)35 HalDriverLoader::HalDriverLoader(const string dir_path, int epoch_count,
36                                  const string& callback_socket_name)
37     : dir_path_(dir_path),
38       epoch_count_(epoch_count),
39       callback_socket_name_(callback_socket_name) {}
40 
FindComponentSpecification(const int component_class,const string & package_name,const int version_major,const int version_minor,const string & component_name,const int component_type,ComponentSpecificationMessage * spec_msg)41 bool HalDriverLoader::FindComponentSpecification(
42     const int component_class, const string& package_name,
43     const int version_major, const int version_minor,
44     const string& component_name, const int component_type,
45     ComponentSpecificationMessage* spec_msg) {
46   DIR* dir;
47   struct dirent* ent;
48 
49   // Derive the package-specific dir which contains .vts files
50   string driver_lib_dir = dir_path_;
51   if (!endsWith(driver_lib_dir, "/")) {
52     driver_lib_dir += "/";
53   }
54   string package_path = package_name;
55   ReplaceSubString(package_path, ".", "/");
56   driver_lib_dir += package_path + "/";
57   driver_lib_dir += GetVersionString(version_major, version_minor);
58 
59   if (!(dir = opendir(driver_lib_dir.c_str()))) {
60     LOG(ERROR) << "Can't open dir " << driver_lib_dir;
61     return false;
62   }
63 
64   while ((ent = readdir(dir))) {
65     if (ent->d_type == DT_REG &&
66         string(ent->d_name).find(kSpecFileExt) != std::string::npos) {
67       LOG(DEBUG) << "Checking a file " << ent->d_name;
68       const string file_path = driver_lib_dir + "/" + string(ent->d_name);
69       if (ParseInterfaceSpec(file_path.c_str(), spec_msg)) {
70         if (spec_msg->component_class() != component_class) {
71           continue;
72         }
73         if (spec_msg->component_class() != HAL_HIDL) {
74           if (spec_msg->component_type() != component_type ||
75               spec_msg->component_type_version_major() != version_major ||
76               spec_msg->component_type_version_minor() != version_minor) {
77             continue;
78           }
79           closedir(dir);
80           return true;
81         } else {
82           if (spec_msg->package() != package_name ||
83               spec_msg->component_type_version_major() != version_major ||
84               spec_msg->component_type_version_minor() != version_minor) {
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)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   DriverBase* driver = nullptr;
108   if (spec_msg.component_class() == HAL_HIDL) {
109     driver = GetHidlHalDriver(driver_lib_path, spec_msg, hw_binder_service_name,
110                               interface_pt, with_interface_pointer);
111   } else {
112     driver = GetLibDriver(driver_lib_path, spec_msg, dll_file_name);
113   }
114   LOG(DEBUG) << "Loaded target comp";
115 
116   return driver;
117 }
118 
GetLibDriver(const string & driver_lib_path,const ComponentSpecificationMessage & spec_msg,const string & dll_file_name)119 DriverBase* HalDriverLoader::GetLibDriver(
120     const string& driver_lib_path,
121     const ComponentSpecificationMessage& spec_msg,
122     const string& dll_file_name) {
123   DriverBase* driver = LoadDriver(driver_lib_path, spec_msg);
124   if (!driver) {
125     LOG(ERROR) << "Couldn't get a driver base class";
126     return nullptr;
127   }
128   if (!driver->LoadTargetComponent(dll_file_name.c_str())) {
129     LOG(ERROR) << "Couldn't load target component file, " << dll_file_name;
130     return nullptr;
131   }
132   return driver;
133 }
134 
GetFuzzerBaseAndAddAllFunctionsToQueue(const char * driver_lib_path,const ComponentSpecificationMessage & iface_spec_msg,const char * dll_file_name,const char * hw_service_name)135 DriverBase* HalDriverLoader::GetFuzzerBaseAndAddAllFunctionsToQueue(
136     const char* driver_lib_path,
137     const ComponentSpecificationMessage& iface_spec_msg,
138     const char* dll_file_name, const char* hw_service_name) {
139   DriverBase* driver = GetDriver(driver_lib_path, iface_spec_msg,
140                                  hw_service_name, 0, false, dll_file_name);
141   if (!driver) {
142     LOG(ERROR) << "Couldn't get a driver base class";
143     return NULL;
144   }
145 
146   for (const FunctionSpecificationMessage& func_msg :
147        iface_spec_msg.interface().api()) {
148     LOG(DEBUG) << "Add a job " << func_msg.name();
149     FunctionSpecificationMessage* func_msg_copy = func_msg.New();
150     func_msg_copy->CopyFrom(func_msg);
151     job_queue_.push(make_pair(func_msg_copy, driver));
152   }
153   return driver;
154 }
155 
GetHidlHalDriver(const string & driver_lib_path,const ComponentSpecificationMessage & spec_msg,const string & hal_service_name,const uint64_t interface_pt,bool with_interface_pt)156 DriverBase* HalDriverLoader::GetHidlHalDriver(
157     const string& driver_lib_path,
158     const ComponentSpecificationMessage& spec_msg,
159     const string& hal_service_name, const uint64_t interface_pt,
160     bool with_interface_pt) {
161   string package_name = spec_msg.package();
162 
163   DriverBase* driver = nullptr;
164   if (with_interface_pt) {
165     driver =
166         LoadDriverWithInterfacePointer(driver_lib_path, spec_msg, interface_pt);
167   } else {
168     driver = LoadDriver(driver_lib_path, spec_msg);
169   }
170   if (!driver) {
171     LOG(ERROR) << "Couldn't get a driver base class";
172     return nullptr;
173   }
174   LOG(DEBUG) << "Got Hidl Hal driver";
175 
176   if (!with_interface_pt) {
177     string service_name;
178     if (!hal_service_name.empty()) {
179       service_name = hal_service_name;
180     } else {
181       service_name = kDefaultHwbinderServiceName;
182     }
183 
184     char get_sub_property[PROPERTY_VALUE_MAX];
185     bool get_stub = false; /* default is binderized */
186     if (property_get("vts.hidl.get_stub", get_sub_property, "") > 0) {
187       if (!strcmp(get_sub_property, "true") ||
188           !strcmp(get_sub_property, "True") || !strcmp(get_sub_property, "1")) {
189         get_stub = true;
190       }
191     }
192     if (!driver->GetService(get_stub, service_name.c_str())) {
193       LOG(ERROR) << "Couldn't get hal service";
194       return nullptr;
195     }
196   } else {
197     LOG(INFO) << "Created DriverBase with interface pointer:" << interface_pt;
198   }
199   LOG(DEBUG) << "Loaded target comp";
200   return driver;
201 }
202 
LoadDriver(const string & driver_lib_path,const ComponentSpecificationMessage & spec_msg)203 DriverBase* HalDriverLoader::LoadDriver(
204     const string& driver_lib_path,
205     const ComponentSpecificationMessage& spec_msg) {
206   if (!dll_loader_.Load(driver_lib_path.c_str())) {
207     LOG(ERROR) << "Failed to load  " << driver_lib_path;
208     return nullptr;
209   }
210   LOG(DEBUG) << "DLL loaded " << driver_lib_path;
211   string function_name_prefix = GetFunctionNamePrefix(spec_msg);
212   loader_function func =
213       dll_loader_.GetLoaderFunction(function_name_prefix.c_str());
214   if (!func) {
215     LOG(ERROR) << "Function not found.";
216     return nullptr;
217   }
218   LOG(DEBUG) << "Function found; trying to call.";
219   DriverBase* driver = func();
220   return driver;
221 }
222 
LoadDriverWithInterfacePointer(const string & driver_lib_path,const ComponentSpecificationMessage & spec_msg,const uint64_t interface_pt)223 DriverBase* HalDriverLoader::LoadDriverWithInterfacePointer(
224     const string& driver_lib_path,
225     const ComponentSpecificationMessage& spec_msg,
226     const uint64_t interface_pt) {
227   // Assumption: no shared library lookup is needed because that is handled
228   // the by the driver's linking dependency.
229   // Example: name (android::hardware::gnss::V1_0::IAGnssRil) converted to
230   // function name (vts_func_4_android_hardware_tests_bar_V1_0_IBar_with_arg)
231   if (!dll_loader_.Load(driver_lib_path.c_str())) {
232     LOG(ERROR) << "Failed to load  " << driver_lib_path;
233     return nullptr;
234   }
235   LOG(DEBUG) << "DLL loaded " << driver_lib_path;
236   string function_name_prefix = GetFunctionNamePrefix(spec_msg);
237   function_name_prefix += "with_arg";
238   loader_function_with_arg func =
239       dll_loader_.GetLoaderFunctionWithArg(function_name_prefix.c_str());
240   if (!func) {
241     LOG(ERROR) << "Function not found.";
242     return nullptr;
243   }
244   return func(interface_pt);
245 }
246 
Process(const char * dll_file_name,const char * spec_lib_file_path,int target_class,int target_type,int target_version_major,int target_version_minor,const char * target_package,const char * target_component_name,const char * hal_service_name)247 bool HalDriverLoader::Process(const char* dll_file_name,
248                               const char* spec_lib_file_path, int target_class,
249                               int target_type, int target_version_major,
250                               int target_version_minor,
251                               const char* target_package,
252                               const char* target_component_name,
253                               const char* hal_service_name) {
254   ComponentSpecificationMessage interface_specification_message;
255   if (!FindComponentSpecification(target_class, target_package,
256                                   target_version_major, target_version_minor,
257                                   target_component_name, target_type,
258                                   &interface_specification_message)) {
259     LOG(ERROR) << "No interface specification file found for class "
260                << target_class << " type " << target_type << " version "
261                << GetVersionString(target_version_major, target_version_minor);
262     return false;
263   }
264 
265   if (!GetFuzzerBaseAndAddAllFunctionsToQueue(
266           spec_lib_file_path, interface_specification_message, dll_file_name,
267           hal_service_name)) {
268     return false;
269   }
270 
271   for (int i = 0; i < epoch_count_; i++) {
272     // by default, breath-first-searching is used.
273     if (job_queue_.empty()) {
274       LOG(ERROR) << "No more job to process; stopping after epoch " << i;
275       break;
276     }
277 
278     pair<vts::FunctionSpecificationMessage*, DriverBase*> curr_job =
279         job_queue_.front();
280     job_queue_.pop();
281 
282     vts::FunctionSpecificationMessage* func_msg = curr_job.first;
283     DriverBase* func_fuzzer = curr_job.second;
284 
285     void* result;
286     FunctionSpecificationMessage result_msg;
287     LOG(INFO) << "Iteration " << (i + 1) << " Function " << func_msg->name();
288     // For Hidl HAL, use CallFunction method.
289     if (interface_specification_message.component_class() == HAL_HIDL) {
290       func_fuzzer->CallFunction(*func_msg, callback_socket_name_, &result_msg);
291     } else {
292       func_fuzzer->Fuzz(func_msg, &result, callback_socket_name_);
293     }
294   }
295 
296   return true;
297 }
298 
299 }  // namespace vts
300 }  // namespace android
301