1 /* 2 * Copyright 2017 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 "ProtoFuzzerRunner.h" 18 19 #include <dlfcn.h> 20 #include <sstream> 21 22 #include "utils/InterfaceSpecUtil.h" 23 #include "vintf/HalManifest.h" 24 #include "vintf/VintfObject.h" 25 26 using android::vintf::HalManifest; 27 28 using std::cout; 29 using std::cerr; 30 using std::string; 31 using std::vector; 32 using std::unordered_map; 33 34 namespace android { 35 namespace vts { 36 namespace fuzzer { 37 38 static string GetDriverName(const CompSpec &comp_spec) { 39 stringstream version; 40 version.precision(1); 41 version << fixed << comp_spec.component_type_version(); 42 string driver_name = 43 comp_spec.package() + "@" + version.str() + "-vts.driver.so"; 44 return driver_name; 45 } 46 47 static string GetServiceName(const CompSpec &comp_spec) { 48 static const HalManifest *vendor_manifest = 49 ::android::vintf::VintfObject::GetDeviceHalManifest(); 50 string hal_name = comp_spec.package(); 51 string iface_name = comp_spec.component_name(); 52 53 auto instance_names = vendor_manifest->getInstances(hal_name, iface_name); 54 if (instance_names.empty()) { 55 cerr << "HAL service name not available in VINTF." << endl; 56 exit(1); 57 } 58 59 // For fuzzing we don't care which instance of the HAL is targeted. 60 string service_name = *instance_names.begin(); 61 cout << "Available HAL instances: " << endl; 62 for (const string &instance_name : instance_names) { 63 cout << instance_name << endl; 64 } 65 cout << "Using HAL instance: " << service_name << endl; 66 67 return service_name; 68 } 69 70 static void *Dlopen(string lib_name) { 71 const char *error; 72 // Clear dlerror(). 73 dlerror(); 74 void *handle = dlopen(lib_name.c_str(), RTLD_LAZY); 75 if (!handle) { 76 cerr << __func__ << ": " << dlerror() << endl; 77 cerr << __func__ << ": Can't load shared library: " << lib_name << endl; 78 exit(1); 79 } 80 return handle; 81 } 82 83 static void *Dlsym(void *handle, string function_name) { 84 const char *error; 85 // Clear dlerror(). 86 dlerror(); 87 void *function = dlsym(handle, function_name.c_str()); 88 if ((error = dlerror()) != NULL) { 89 cerr << __func__ << ": Can't find: " << function_name << endl; 90 cerr << error << endl; 91 exit(1); 92 } 93 return function; 94 } 95 96 static void GetService(DriverBase *hal, string service_name, bool binder_mode) { 97 // For fuzzing, only passthrough mode provides coverage. 98 // If binder mode is not requested, attempt to open HAL in passthrough mode. 99 // If the attempt fails, fall back to binder mode. 100 if (!binder_mode) { 101 if (!hal->GetService(true, service_name.c_str())) { 102 cerr << __func__ << ": Failed to open HAL in passthrough mode. " 103 << "Falling back to binder mode." << endl; 104 } else { 105 cerr << "HAL opened in passthrough mode." << endl; 106 return; 107 } 108 } 109 110 if (!hal->GetService(false, service_name.c_str())) { 111 cerr << __func__ << ": Failed to open HAL in binder mode." << endl; 112 exit(1); 113 } else { 114 cerr << "HAL opened in binder mode." << endl; 115 return; 116 } 117 } 118 119 DriverBase *ProtoFuzzerRunner::LoadInterface(const CompSpec &comp_spec, 120 uint64_t hidl_service = 0) { 121 DriverBase *hal; 122 const char *error; 123 // Clear dlerror(). 124 dlerror(); 125 126 // DriverBase can be constructed with or without an argument. 127 // Using different DriverBase constructors requires dlsym'ing different 128 // symbols from the driver library. 129 string function_name = GetFunctionNamePrefix(comp_spec); 130 if (hidl_service) { 131 function_name += "with_arg"; 132 using loader_func = DriverBase *(*)(uint64_t); 133 auto hal_loader = (loader_func)Dlsym(driver_handle_, function_name.c_str()); 134 hal = hal_loader(hidl_service); 135 } else { 136 using loader_func = DriverBase *(*)(); 137 auto hal_loader = (loader_func)Dlsym(driver_handle_, function_name.c_str()); 138 hal = hal_loader(); 139 } 140 return hal; 141 } 142 143 ProtoFuzzerRunner::ProtoFuzzerRunner(const vector<CompSpec> &comp_specs) { 144 for (const auto &comp_spec : comp_specs) { 145 if (comp_spec.has_interface()) { 146 string name = comp_spec.component_name(); 147 comp_specs_[name] = comp_spec; 148 } 149 } 150 } 151 152 void ProtoFuzzerRunner::Init(const string &iface_name, bool binder_mode) { 153 const CompSpec *comp_spec = FindCompSpec(iface_name); 154 // dlopen VTS driver library. 155 string driver_name = GetDriverName(*comp_spec); 156 driver_handle_ = Dlopen(driver_name); 157 158 std::shared_ptr<DriverBase> hal{LoadInterface(*comp_spec)}; 159 string service_name = GetServiceName(*comp_spec); 160 cerr << "HAL name: " << comp_spec->package() << endl 161 << "Interface name: " << comp_spec->component_name() << endl 162 << "Service name: " << service_name << endl; 163 164 // This should only be done for top-level interfaces. 165 GetService(hal.get(), service_name, binder_mode); 166 167 // Register this interface as opened by the runner. 168 opened_ifaces_[iface_name] = { 169 .comp_spec_ = comp_spec, .hal_ = hal, 170 }; 171 } 172 173 void ProtoFuzzerRunner::Execute(const ExecSpec &exec_spec) { 174 for (const auto &func_call : exec_spec.function_call()) { 175 cout << func_call.DebugString() << endl; 176 Execute(func_call); 177 } 178 } 179 180 void ProtoFuzzerRunner::Execute(const FuncCall &func_call) { 181 string iface_name = func_call.hidl_interface_name(); 182 const FuncSpec &func_spec = func_call.api(); 183 184 auto iface_desc = opened_ifaces_.find(iface_name); 185 if (iface_desc == opened_ifaces_.end()) { 186 cerr << "Interface is not open: " << iface_name << endl; 187 exit(1); 188 } 189 190 FuncSpec result{}; 191 iface_desc->second.hal_->CallFunction(func_spec, "", &result); 192 193 ProcessReturnValue(result); 194 } 195 196 static string StripNamespace(const string &type) { 197 size_t idx = type.find_last_of(':'); 198 if (idx == string::npos) { 199 return ""; 200 } 201 return type.substr(idx + 1); 202 } 203 204 void ProtoFuzzerRunner::ProcessReturnValue(const FuncSpec &result) { 205 for (const auto &var : result.return_type_hidl()) { 206 if (var.has_hidl_interface_pointer() && var.has_predefined_type()) { 207 uint64_t hidl_service = var.hidl_interface_pointer(); 208 string type = var.predefined_type(); 209 string iface_name = StripNamespace(type); 210 211 const CompSpec *comp_spec = FindCompSpec(iface_name); 212 std::shared_ptr<DriverBase> hal{LoadInterface(*comp_spec, hidl_service)}; 213 214 // Register this interface as opened by the runner. 215 opened_ifaces_[iface_name] = { 216 .comp_spec_ = comp_spec, .hal_ = hal, 217 }; 218 } 219 } 220 } 221 222 const CompSpec *ProtoFuzzerRunner::FindCompSpec(std::string name) { 223 auto comp_spec = comp_specs_.find(name); 224 if (comp_spec == comp_specs_.end()) { 225 cerr << "VTS spec not found: " << name << endl; 226 exit(1); 227 } 228 return &comp_spec->second; 229 } 230 231 } // namespace fuzzer 232 } // namespace vts 233 } // namespace android 234