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