1 /* 2 * Copyright 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 17 #include "fuzz_tester/FuzzerBase.h" 18 19 #include <dirent.h> 20 #include <stdio.h> 21 #include <stdlib.h> 22 #include <sys/mman.h> 23 #include <sys/stat.h> 24 #include <sys/types.h> 25 #include <unistd.h> 26 27 #include <fstream> 28 #include <iostream> 29 #include <sstream> 30 #include <string> 31 #include <vector> 32 33 #include "test/vts/proto/ComponentSpecificationMessage.pb.h" 34 35 #include "component_loader/DllLoader.h" 36 #include "utils/InterfaceSpecUtil.h" 37 38 #include "GcdaParser.h" 39 40 using namespace std; 41 using namespace android; 42 43 #define USE_GCOV 1 44 45 #if SANCOV 46 extern "C" { 47 typedef unsigned long uptr; 48 49 #define SANITIZER_INTERFACE_ATTRIBUTE __attribute__((visibility("default"))) 50 SANITIZER_INTERFACE_ATTRIBUTE 51 void __sanitizer_cov(uint32_t* guard) { 52 printf("sancov\n"); 53 coverage_data.Add(StackTrace::GetPreviousInstructionPc(GET_CALLER_PC()), 54 guard); 55 } 56 57 SANITIZER_INTERFACE_ATTRIBUTE 58 void* __asan_memset(void* block, int c, uptr size) { 59 ASAN_MEMSET_IMPL(nullptr, block, c, size); 60 return block; 61 } 62 63 SANITIZER_INTERFACE_ATTRIBUTE 64 void __asan_register_globals() {} 65 SANITIZER_INTERFACE_ATTRIBUTE 66 void __asan_unregister_globals() {} 67 SANITIZER_INTERFACE_ATTRIBUTE 68 void __asan_handle_no_return() {} 69 SANITIZER_INTERFACE_ATTRIBUTE 70 void __asan_report_load1() {} 71 SANITIZER_INTERFACE_ATTRIBUTE 72 void __asan_report_load2() {} 73 SANITIZER_INTERFACE_ATTRIBUTE 74 void __asan_report_load4() {} 75 SANITIZER_INTERFACE_ATTRIBUTE 76 void __asan_report_load8() {} 77 SANITIZER_INTERFACE_ATTRIBUTE 78 void __asan_report_load16() {} 79 SANITIZER_INTERFACE_ATTRIBUTE 80 void __asan_report_store1() {} 81 SANITIZER_INTERFACE_ATTRIBUTE 82 void __asan_report_store2() {} 83 SANITIZER_INTERFACE_ATTRIBUTE 84 void __asan_report_store4() {} 85 SANITIZER_INTERFACE_ATTRIBUTE 86 void __asan_report_store8() {} 87 SANITIZER_INTERFACE_ATTRIBUTE 88 void __asan_report_store16() {} 89 SANITIZER_INTERFACE_ATTRIBUTE 90 void __asan_set_error_report_callback() {} 91 92 SANITIZER_INTERFACE_ATTRIBUTE 93 uptr __asan_stack_malloc_1(uptr size, uptr real_stack) { 94 return (uptr)malloc(size); 95 } 96 97 SANITIZER_INTERFACE_ATTRIBUTE 98 uptr __asan_stack_malloc_2(uptr size, uptr real_stack) { 99 return (uptr)malloc(size); 100 } 101 102 SANITIZER_INTERFACE_ATTRIBUTE 103 uptr __asan_stack_malloc_3(uptr size, uptr real_stack) { 104 return (uptr)malloc(size); 105 } 106 107 SANITIZER_INTERFACE_ATTRIBUTE 108 uptr __asan_stack_malloc_4(uptr size, uptr real_stack) { 109 return (uptr)malloc(size); 110 } 111 112 SANITIZER_INTERFACE_ATTRIBUTE 113 uptr __asan_stack_malloc_5(uptr size, uptr real_stack) { 114 return (uptr)malloc(size); 115 } 116 117 SANITIZER_INTERFACE_ATTRIBUTE 118 uptr __asan_stack_malloc_6(uptr size, uptr real_stack) { 119 return (uptr)malloc(size); 120 } 121 122 SANITIZER_INTERFACE_ATTRIBUTE 123 uptr __asan_stack_malloc_7(uptr size, uptr real_stack) { 124 return (uptr)malloc(size); 125 } 126 127 SANITIZER_INTERFACE_ATTRIBUTE 128 uptr __asan_stack_malloc_8(uptr size, uptr real_stack) { 129 return (uptr)malloc(size); 130 } 131 132 SANITIZER_INTERFACE_ATTRIBUTE 133 uptr __asan_stack_malloc_9(uptr size, uptr real_stack) { 134 return (uptr)malloc(size); 135 } 136 137 SANITIZER_INTERFACE_ATTRIBUTE 138 uptr __asan_stack_malloc_10(uptr size, uptr real_stack) { 139 return (uptr)malloc(size); 140 } 141 142 SANITIZER_INTERFACE_ATTRIBUTE 143 void __asan_stack_free_1(uptr ptr, uptr size, uptr real_stack) { 144 free((void*)ptr); 145 } 146 147 SANITIZER_INTERFACE_ATTRIBUTE 148 void __asan_stack_free_2(uptr ptr, uptr size, uptr real_stack) { 149 free((void*)ptr); 150 } 151 152 SANITIZER_INTERFACE_ATTRIBUTE 153 void __asan_stack_free_3(uptr ptr, uptr size, uptr real_stack) { 154 free((void*)ptr); 155 } 156 157 SANITIZER_INTERFACE_ATTRIBUTE 158 void __asan_stack_free_4(uptr ptr, uptr size, uptr real_stack) { 159 free((void*)ptr); 160 } 161 162 SANITIZER_INTERFACE_ATTRIBUTE 163 void __asan_stack_free_5(uptr ptr, uptr size, uptr real_stack) { 164 free((void*)ptr); 165 } 166 167 SANITIZER_INTERFACE_ATTRIBUTE 168 void __asan_stack_free_6(uptr ptr, uptr size, uptr real_stack) { 169 free((void*)ptr); 170 } 171 172 SANITIZER_INTERFACE_ATTRIBUTE 173 void __asan_stack_free_7(uptr ptr, uptr size, uptr real_stack) { 174 free((void*)ptr); 175 } 176 177 SANITIZER_INTERFACE_ATTRIBUTE 178 void __asan_stack_free_8(uptr ptr, uptr size, uptr real_stack) { 179 free((void*)ptr); 180 } 181 182 SANITIZER_INTERFACE_ATTRIBUTE 183 void __asan_stack_free_9(uptr ptr, uptr size, uptr real_stack) { 184 free((void*)ptr); 185 } 186 187 SANITIZER_INTERFACE_ATTRIBUTE 188 void __asan_stack_free_10(uptr ptr, uptr size, uptr real_stack) { 189 free((void*)ptr); 190 } 191 192 SANITIZER_INTERFACE_ATTRIBUTE 193 void __asan_version_mismatch_check_v6() { 194 // Do nothing. 195 } 196 197 SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_module_init( 198 int32_t* guards, uptr npcs, uint8_t* counters, const char* comp_unit_name) { 199 } 200 201 SANITIZER_INTERFACE_ATTRIBUTE 202 void __asan_init() { 203 static int inited = 0; 204 if (inited) return; 205 inited = 1; 206 #if __WORDSIZE == 64 207 unsigned long start = 0x100000000000; 208 unsigned long size = 0x100000000000; 209 #else 210 unsigned long start = 0x20000000; 211 unsigned long size = 0x20000000; 212 #endif 213 void* res = mmap((void*)start, size, PROT_READ | PROT_WRITE, 214 MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, 0, 0); 215 if (res == (void*)start) { 216 fprintf(stderr, "Fake AddressSanitizer run-time initialized ok at %p\n", 217 res); 218 } else { 219 fprintf(stderr, 220 "Fake AddressSanitizer run-time failed to initialize.\n" 221 "You have been warned. Aborting."); 222 abort(); 223 } 224 } 225 } 226 #endif 227 228 namespace android { 229 namespace vts { 230 231 const string default_gcov_output_basepath = "/data/misc/gcov"; 232 233 static void RemoveDir(char* path) { 234 struct dirent* entry = NULL; 235 DIR* dir = opendir(path); 236 237 while ((entry = readdir(dir)) != NULL) { 238 DIR* sub_dir = NULL; 239 FILE* file = NULL; 240 char abs_path[4096] = {0}; 241 242 if (*(entry->d_name) != '.') { 243 sprintf(abs_path, "%s/%s", path, entry->d_name); 244 if ((sub_dir = opendir(abs_path)) != NULL) { 245 closedir(sub_dir); 246 RemoveDir(abs_path); 247 } else if ((file = fopen(abs_path, "r")) != NULL) { 248 fclose(file); 249 remove(abs_path); 250 } 251 } 252 } 253 remove(path); 254 } 255 256 FuzzerBase::FuzzerBase(int target_class) 257 : device_(NULL), 258 hmi_(NULL), 259 target_dll_path_(NULL), 260 target_class_(target_class), 261 component_filename_(NULL), 262 gcov_output_basepath_(NULL) {} 263 264 FuzzerBase::~FuzzerBase() { free(component_filename_); } 265 266 void wfn() { 267 cout << __func__ << endl; 268 } 269 270 void ffn() { 271 cout << __func__ << endl; 272 } 273 274 bool FuzzerBase::LoadTargetComponent(const char* target_dll_path) { 275 cout << __func__ << ":" << __LINE__ << " entry" << endl; 276 if (target_dll_path && target_dll_path_ && 277 !strcmp(target_dll_path, target_dll_path_)) { 278 cout << __func__ << " skip loading" << endl; 279 return true; 280 } 281 282 if (!target_loader_.Load(target_dll_path)) return false; 283 target_dll_path_ = (char*)malloc(strlen(target_dll_path) + 1); 284 strcpy(target_dll_path_, target_dll_path); 285 cout << __FUNCTION__ << ":" << __LINE__ << " loaded the target" << endl; 286 if (target_class_ == HAL_LEGACY) return true; 287 cout << __FUNCTION__ << ":" << __LINE__ << " loaded a non-legacy HAL file." 288 << endl; 289 if (target_class_ == HAL_CONVENTIONAL) { 290 hmi_ = target_loader_.InitConventionalHal(); 291 if (!hmi_) { 292 free(target_dll_path_); 293 target_dll_path_ = NULL; 294 return false; 295 } 296 } 297 #if SANCOV 298 cout << __FUNCTION__ << "sancov reset " 299 << target_loader_.SancovResetCoverage() << endl; 300 #endif 301 302 if (target_dll_path_) { 303 cout << __func__ << ":" << __LINE__ << " target DLL path " 304 << target_dll_path_ << endl; 305 string target_path(target_dll_path_); 306 307 size_t offset = target_path.rfind("/", target_path.length()); 308 if (offset != string::npos) { 309 string filename = 310 target_path.substr(offset + 1, target_path.length() - offset); 311 filename = filename.substr(0, filename.length() - 3 /* for .so */); 312 component_filename_ = (char*)malloc(filename.length() + 1); 313 strcpy(component_filename_, filename.c_str()); 314 cout << __FUNCTION__ << ":" << __LINE__ 315 << " module file name: " << component_filename_ << endl; 316 } 317 cout << __FUNCTION__ << ":" << __LINE__ << " target_dll_path " 318 << target_dll_path_ << endl; 319 } 320 321 #if USE_GCOV 322 cout << __FUNCTION__ << ": gcov init " << target_loader_.GcovInit(wfn, ffn) 323 << endl; 324 #endif 325 return true; 326 } 327 328 bool FuzzerBase::SetTargetObject(void* object_pointer) { 329 device_ = NULL; 330 hmi_ = reinterpret_cast<struct hw_module_t*>(object_pointer); 331 return true; 332 } 333 334 bool FuzzerBase::GetService(bool /*get_stub*/, const char* /*service_name*/) { 335 cerr << __func__ << " not impl" << endl; 336 return false; 337 } 338 339 int FuzzerBase::OpenConventionalHal(const char* module_name) { 340 cout << __func__ << endl; 341 if (module_name) cout << __func__ << " " << module_name << endl; 342 device_ = target_loader_.OpenConventionalHal(module_name); 343 if (!device_) return -1; 344 cout << __func__ << " device_" << device_ << endl; 345 return 0; 346 } 347 348 bool FuzzerBase::Fuzz(vts::ComponentSpecificationMessage* message, 349 void** result) { 350 cout << __func__ << " Fuzzing target component: " 351 << "class " << message->component_class() << " type " 352 << message->component_type() << " version " 353 << message->component_type_version() << endl; 354 355 string function_name_prefix = GetFunctionNamePrefix(*message); 356 function_name_prefix_ = function_name_prefix.c_str(); 357 for (vts::FunctionSpecificationMessage func_msg : 358 *message->mutable_interface()->mutable_api()) { 359 Fuzz(&func_msg, result, ""); 360 } 361 return true; 362 } 363 364 void FuzzerBase::FunctionCallBegin() { 365 char product_path[4096]; 366 char product[128]; 367 char module_basepath[4096]; 368 369 cout << __func__ << ":" << __LINE__ << " begin" << endl; 370 snprintf(product_path, 4096, "%s/%s", default_gcov_output_basepath.c_str(), 371 "proc/self/cwd/out/target/product"); 372 DIR* srcdir = opendir(product_path); 373 if (!srcdir) { 374 cerr << __func__ << " couldn't open " << product_path << endl; 375 return; 376 } 377 378 int dir_count = 0; 379 struct dirent* dent; 380 while ((dent = readdir(srcdir)) != NULL) { 381 struct stat st; 382 if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) { 383 continue; 384 } 385 if (fstatat(dirfd(srcdir), dent->d_name, &st, 0) < 0) { 386 cerr << __func__ << " error " << dent->d_name << endl; 387 continue; 388 } 389 if (S_ISDIR(st.st_mode)) { 390 cout << __func__ << ":" << __LINE__ << " dir " << dent->d_name << endl; 391 strcpy(product, dent->d_name); 392 dir_count++; 393 } 394 } 395 closedir(srcdir); 396 if (dir_count != 1) { 397 cerr << __func__ << " more than one product dir found." << endl; 398 return; 399 } 400 401 int n = snprintf(module_basepath, 4096, "%s/%s/obj/SHARED_LIBRARIES", 402 product_path, product); 403 if (n <= 0 || n >= 4096) { 404 cerr << __func__ << " couln't get module_basepath" << endl; 405 return; 406 } 407 srcdir = opendir(module_basepath); 408 if (!srcdir) { 409 cerr << __func__ << " couln't open " << module_basepath << endl; 410 return; 411 } 412 413 if (component_filename_ != NULL) { 414 dir_count = 0; 415 string target = string(component_filename_) + "_intermediates"; 416 bool hit = false; 417 cout << __func__ << ":" << __LINE__ << endl; 418 while ((dent = readdir(srcdir)) != NULL) { 419 struct stat st; 420 if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) { 421 continue; 422 } 423 if (fstatat(dirfd(srcdir), dent->d_name, &st, 0) < 0) { 424 cerr << __func__ << " error " << dent->d_name << endl; 425 continue; 426 } 427 if (S_ISDIR(st.st_mode)) { 428 cout << "module_basepath " << string(dent->d_name) << endl; 429 if (string(dent->d_name) == target) { 430 cout << "hit" << endl; 431 hit = true; 432 } 433 dir_count++; 434 } 435 } 436 if (hit) { 437 free(gcov_output_basepath_); 438 gcov_output_basepath_ = 439 (char*)malloc(strlen(module_basepath) + target.length() + 2); 440 if (!gcov_output_basepath_) { 441 cerr << __FUNCTION__ << ": couldn't alloc memory" << endl; 442 return; 443 } 444 sprintf(gcov_output_basepath_, "%s/%s", module_basepath, target.c_str()); 445 RemoveDir(gcov_output_basepath_); 446 } 447 } else { 448 cerr << __func__ << ":" << __LINE__ << " component_filename_ is NULL" 449 << endl; 450 } 451 // TODO: check how it works when there already is a file. 452 closedir(srcdir); 453 cout << __func__ << ":" << __LINE__ << " end" << endl; 454 } 455 456 bool FuzzerBase::ReadGcdaFile( 457 const string& basepath, const string& filename, 458 FunctionSpecificationMessage* msg) { 459 #if VTS_GCOV_DEBUG 460 cout << __func__ << ":" << __LINE__ 461 << " file = " << dent->d_name << endl; 462 #endif 463 if (string(filename).rfind(".gcda") != string::npos) { 464 string buffer = basepath + "/" + filename; 465 vector<unsigned> processed_data = 466 android::vts::GcdaRawCoverageParser(buffer.c_str()).Parse(); 467 for (const auto& data : processed_data) { 468 msg->mutable_processed_coverage_data()->Add(data); 469 } 470 471 FILE* gcda_file = fopen(buffer.c_str(), "rb"); 472 if (!gcda_file) { 473 cerr << __func__ << ":" << __LINE__ 474 << " Unable to open a gcda file. " << buffer << endl; 475 } else { 476 cout << __func__ << ":" << __LINE__ 477 << " Opened a gcda file. " << buffer << endl; 478 fseek(gcda_file, 0, SEEK_END); 479 long gcda_file_size = ftell(gcda_file); 480 #if VTS_GCOV_DEBUG 481 cout << __func__ << ":" << __LINE__ 482 << " File size " << gcda_file_size << " bytes" << endl; 483 #endif 484 fseek(gcda_file, 0, SEEK_SET); 485 486 char* gcda_file_buffer = (char*)malloc(gcda_file_size + 1); 487 if (!gcda_file_buffer) { 488 cerr << __func__ << ":" << __LINE__ 489 << "Unable to allocate memory to read a gcda file. " << endl; 490 } else { 491 if (fread(gcda_file_buffer, gcda_file_size, 1, gcda_file) != 1) { 492 cerr << __func__ << ":" << __LINE__ 493 << "File read error" << endl; 494 } else { 495 #if VTS_GCOV_DEBUG 496 cout << __func__ << ":" << __LINE__ 497 << " GCDA field populated." << endl; 498 #endif 499 gcda_file_buffer[gcda_file_size] = '\0'; 500 NativeCodeCoverageRawDataMessage* raw_msg = 501 msg->mutable_raw_coverage_data()->Add(); 502 raw_msg->set_file_path(filename.c_str()); 503 string gcda_file_buffer_string(gcda_file_buffer, gcda_file_size); 504 raw_msg->set_gcda(gcda_file_buffer_string); 505 free(gcda_file_buffer); 506 } 507 } 508 fclose(gcda_file); 509 } 510 #if USE_GCOV_DEBUG 511 if (result) { 512 for (unsigned int index = 0; index < result->size(); index++) { 513 cout << result->at(index) << endl; 514 } 515 } 516 #endif 517 return true; 518 } 519 return false; 520 } 521 522 bool FuzzerBase::ScanAllGcdaFiles( 523 const string& basepath, FunctionSpecificationMessage* msg) { 524 DIR* srcdir = opendir(basepath.c_str()); 525 if (!srcdir) { 526 cerr << __func__ << ":" << __LINE__ 527 << " couln't open " << basepath << endl; 528 return false; 529 } 530 531 struct dirent* dent; 532 while ((dent = readdir(srcdir)) != NULL) { 533 #if VTS_GCOV_DEBUG 534 cout << __func__ << ":" << __LINE__ 535 << " readdir(" << basepath << ") for " << dent->d_name << endl; 536 #endif 537 struct stat st; 538 if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) { 539 continue; 540 } 541 if (fstatat(dirfd(srcdir), dent->d_name, &st, 0) < 0) { 542 cerr << "error " << dent->d_name << endl; 543 continue; 544 } 545 if (S_ISDIR(st.st_mode)) { 546 ScanAllGcdaFiles(basepath + "/" + dent->d_name, msg); 547 } else { 548 ReadGcdaFile(basepath, dent->d_name, msg); 549 } 550 } 551 #if VTS_GCOV_DEBUG 552 cout << __func__ << ":" << __LINE__ 553 << " closedir(" << srcdir << ")" << endl; 554 #endif 555 closedir(srcdir); 556 return true; 557 } 558 559 bool FuzzerBase::FunctionCallEnd(FunctionSpecificationMessage* msg) { 560 cout << __func__ << ": gcov flush " << endl; 561 #if USE_GCOV 562 target_loader_.GcovFlush(); 563 // find the file. 564 if (!gcov_output_basepath_) { 565 cerr << __FUNCTION__ << ": no gcov basepath set" << endl; 566 return ScanAllGcdaFiles(default_gcov_output_basepath, msg); 567 } 568 DIR* srcdir = opendir(gcov_output_basepath_); 569 if (!srcdir) { 570 cerr << __func__ << " couln't open " << gcov_output_basepath_ << endl; 571 return false; 572 } 573 574 struct dirent* dent; 575 while ((dent = readdir(srcdir)) != NULL) { 576 cout << __func__ << ": readdir(" << srcdir << ") for " << dent->d_name 577 << endl; 578 579 struct stat st; 580 if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) { 581 continue; 582 } 583 if (fstatat(dirfd(srcdir), dent->d_name, &st, 0) < 0) { 584 cerr << "error " << dent->d_name << endl; 585 continue; 586 } 587 if (!S_ISDIR(st.st_mode) 588 && ReadGcdaFile(gcov_output_basepath_, dent->d_name, msg)) { 589 break; 590 } 591 } 592 cout << __func__ << ": closedir(" << srcdir << ")" << endl; 593 closedir(srcdir); 594 #endif 595 return true; 596 } 597 598 } // namespace vts 599 } // namespace android 600