Home | History | Annotate | Download | only in fuzz_tester
      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