/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "VtsHalDriverLoader" #include "component_loader/HalDriverLoader.h" #include #include #include #include #include "utils/InterfaceSpecUtil.h" #include "utils/StringUtil.h" static constexpr const char* kSpecFileExt = ".vts"; static constexpr const char* kDefaultHwbinderServiceName = "default"; namespace android { namespace vts { HalDriverLoader::HalDriverLoader(const string dir_path, int epoch_count, const string& callback_socket_name) : dir_path_(dir_path), epoch_count_(epoch_count), callback_socket_name_(callback_socket_name) {} bool HalDriverLoader::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) { DIR* dir; struct dirent* ent; // Derive the package-specific dir which contains .vts files string driver_lib_dir = dir_path_; if (!endsWith(driver_lib_dir, "/")) { driver_lib_dir += "/"; } string package_path = package_name; ReplaceSubString(package_path, ".", "/"); driver_lib_dir += package_path + "/"; driver_lib_dir += GetVersionString(version_major, version_minor); if (!(dir = opendir(driver_lib_dir.c_str()))) { LOG(ERROR) << "Can't open dir " << driver_lib_dir; return false; } while ((ent = readdir(dir))) { if (ent->d_type == DT_REG && string(ent->d_name).find(kSpecFileExt) != std::string::npos) { LOG(DEBUG) << "Checking a file " << ent->d_name; const string file_path = driver_lib_dir + "/" + string(ent->d_name); if (ParseInterfaceSpec(file_path.c_str(), spec_msg)) { if (spec_msg->component_class() != component_class) { continue; } if (spec_msg->component_class() != HAL_HIDL) { if (spec_msg->component_type() != component_type || spec_msg->component_type_version_major() != version_major || spec_msg->component_type_version_minor() != version_minor) { continue; } closedir(dir); return true; } else { if (spec_msg->package() != package_name || spec_msg->component_type_version_major() != version_major || spec_msg->component_type_version_minor() != version_minor) { continue; } if (!component_name.empty()) { if (spec_msg->component_name() != component_name) { continue; } } closedir(dir); return true; } } } } closedir(dir); return false; } DriverBase* HalDriverLoader::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) { DriverBase* driver = nullptr; if (spec_msg.component_class() == HAL_HIDL) { driver = GetHidlHalDriver(driver_lib_path, spec_msg, hw_binder_service_name, interface_pt, with_interface_pointer); } else { driver = GetLibDriver(driver_lib_path, spec_msg, dll_file_name); } LOG(DEBUG) << "Loaded target comp"; return driver; } DriverBase* HalDriverLoader::GetLibDriver( const string& driver_lib_path, const ComponentSpecificationMessage& spec_msg, const string& dll_file_name) { DriverBase* driver = LoadDriver(driver_lib_path, spec_msg); if (!driver) { LOG(ERROR) << "Couldn't get a driver base class"; return nullptr; } if (!driver->LoadTargetComponent(dll_file_name.c_str())) { LOG(ERROR) << "Couldn't load target component file, " << dll_file_name; return nullptr; } return driver; } DriverBase* HalDriverLoader::GetFuzzerBaseAndAddAllFunctionsToQueue( const char* driver_lib_path, const ComponentSpecificationMessage& iface_spec_msg, const char* dll_file_name, const char* hw_service_name) { DriverBase* driver = GetDriver(driver_lib_path, iface_spec_msg, hw_service_name, 0, false, dll_file_name); if (!driver) { LOG(ERROR) << "Couldn't get a driver base class"; return NULL; } for (const FunctionSpecificationMessage& func_msg : iface_spec_msg.interface().api()) { LOG(DEBUG) << "Add a job " << func_msg.name(); FunctionSpecificationMessage* func_msg_copy = func_msg.New(); func_msg_copy->CopyFrom(func_msg); job_queue_.push(make_pair(func_msg_copy, driver)); } return driver; } DriverBase* HalDriverLoader::GetHidlHalDriver( const string& driver_lib_path, const ComponentSpecificationMessage& spec_msg, const string& hal_service_name, const uint64_t interface_pt, bool with_interface_pt) { string package_name = spec_msg.package(); DriverBase* driver = nullptr; if (with_interface_pt) { driver = LoadDriverWithInterfacePointer(driver_lib_path, spec_msg, interface_pt); } else { driver = LoadDriver(driver_lib_path, spec_msg); } if (!driver) { LOG(ERROR) << "Couldn't get a driver base class"; return nullptr; } LOG(DEBUG) << "Got Hidl Hal driver"; if (!with_interface_pt) { string service_name; if (!hal_service_name.empty()) { service_name = hal_service_name; } else { service_name = kDefaultHwbinderServiceName; } char get_sub_property[PROPERTY_VALUE_MAX]; bool get_stub = false; /* default is binderized */ if (property_get("vts.hidl.get_stub", get_sub_property, "") > 0) { if (!strcmp(get_sub_property, "true") || !strcmp(get_sub_property, "True") || !strcmp(get_sub_property, "1")) { get_stub = true; } } if (!driver->GetService(get_stub, service_name.c_str())) { LOG(ERROR) << "Couldn't get hal service"; return nullptr; } } else { LOG(INFO) << "Created DriverBase with interface pointer:" << interface_pt; } LOG(DEBUG) << "Loaded target comp"; return driver; } DriverBase* HalDriverLoader::LoadDriver( const string& driver_lib_path, const ComponentSpecificationMessage& spec_msg) { if (!dll_loader_.Load(driver_lib_path.c_str())) { LOG(ERROR) << "Failed to load " << driver_lib_path; return nullptr; } LOG(DEBUG) << "DLL loaded " << driver_lib_path; string function_name_prefix = GetFunctionNamePrefix(spec_msg); loader_function func = dll_loader_.GetLoaderFunction(function_name_prefix.c_str()); if (!func) { LOG(ERROR) << "Function not found."; return nullptr; } LOG(DEBUG) << "Function found; trying to call."; DriverBase* driver = func(); return driver; } DriverBase* HalDriverLoader::LoadDriverWithInterfacePointer( const string& driver_lib_path, const ComponentSpecificationMessage& spec_msg, const uint64_t interface_pt) { // Assumption: no shared library lookup is needed because that is handled // the by the driver's linking dependency. // Example: name (android::hardware::gnss::V1_0::IAGnssRil) converted to // function name (vts_func_4_android_hardware_tests_bar_V1_0_IBar_with_arg) if (!dll_loader_.Load(driver_lib_path.c_str())) { LOG(ERROR) << "Failed to load " << driver_lib_path; return nullptr; } LOG(DEBUG) << "DLL loaded " << driver_lib_path; string function_name_prefix = GetFunctionNamePrefix(spec_msg); function_name_prefix += "with_arg"; loader_function_with_arg func = dll_loader_.GetLoaderFunctionWithArg(function_name_prefix.c_str()); if (!func) { LOG(ERROR) << "Function not found."; return nullptr; } return func(interface_pt); } bool HalDriverLoader::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) { ComponentSpecificationMessage interface_specification_message; if (!FindComponentSpecification(target_class, target_package, target_version_major, target_version_minor, target_component_name, target_type, &interface_specification_message)) { LOG(ERROR) << "No interface specification file found for class " << target_class << " type " << target_type << " version " << GetVersionString(target_version_major, target_version_minor); return false; } if (!GetFuzzerBaseAndAddAllFunctionsToQueue( spec_lib_file_path, interface_specification_message, dll_file_name, hal_service_name)) { return false; } for (int i = 0; i < epoch_count_; i++) { // by default, breath-first-searching is used. if (job_queue_.empty()) { LOG(ERROR) << "No more job to process; stopping after epoch " << i; break; } pair curr_job = job_queue_.front(); job_queue_.pop(); vts::FunctionSpecificationMessage* func_msg = curr_job.first; DriverBase* func_fuzzer = curr_job.second; void* result; FunctionSpecificationMessage result_msg; LOG(INFO) << "Iteration " << (i + 1) << " Function " << func_msg->name(); // For Hidl HAL, use CallFunction method. if (interface_specification_message.component_class() == HAL_HIDL) { func_fuzzer->CallFunction(*func_msg, callback_socket_name_, &result_msg); } else { func_fuzzer->Fuzz(func_msg, &result, callback_socket_name_); } } return true; } } // namespace vts } // namespace android