1 /*
2  * Copyright 2019 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 "ProtoFuzzerUtils.h"
18 
19 #include <android-base/file.h>
20 #include <android-base/macros.h>
21 #include <android-base/strings.h>
22 #include <hidl/ServiceManagement.h>
23 
24 #define STRINGIFY(x) STRINGIFY_INTERNAL(x)
25 #define STRINGIFY_INTERNAL(x) #x
26 
27 using android::FQName;
28 using android::base::GetExecutableDirectory;
29 using android::base::Join;
30 using android::base::Split;
31 using android::hardware::getAllHalInstanceNames;
32 using std::cerr;
33 using std::cout;
34 using std::string;
35 
36 namespace android {
37 namespace vts {
38 namespace fuzzer {
39 
40 // TODO(b/145220086): fuzzer should attempt to fuzz all interfaces and instances
41 // it can find.
FindAnyIfaceFQName(const FQName & package_and_version,const vector<CompSpec> & comp_specs)42 static FQName FindAnyIfaceFQName(const FQName &package_and_version,
43                                  const vector<CompSpec> &comp_specs) {
44   for (const auto &spec : comp_specs) {
45     auto package = package_and_version.package();
46     auto major_version = package_and_version.getPackageMajorVersion();
47     auto minor_version = package_and_version.getPackageMinorVersion();
48 
49     if (package == spec.package() &&
50         major_version == spec.component_type_version_major() &&
51         minor_version == spec.component_type_version_minor()) {
52       auto iface_name = spec.component_name();
53       auto descriptor = package_and_version.string() + "::" + iface_name;
54       auto instance_names = getAllHalInstanceNames(descriptor);
55 
56       if (!instance_names.empty()) {
57         auto version =
58             std::to_string(major_version) + "." + std::to_string(minor_version);
59         return FQName{package, version, iface_name};
60       }
61     }
62   }
63   return FQName{};
64 }
65 
66 // Returns path to base directory where fuzzer specs are installed.
GetSpecBaseDir()67 static inline const string &GetSpecBaseDir() {
68   static const string spec_base_dir = GetExecutableDirectory() + "/data/";
69   return spec_base_dir;
70 }
71 
72 // Parses a column-separated list of packages into a list of corresponding
73 // directories.
ParseDirs(const string & packages)74 static vector<string> ParseDirs(const string &packages) {
75   vector<string> result{};
76 
77   for (const auto &package : Split(packages, ":")) {
78     FQName fq_name;
79     if (!FQName::parse(package, &fq_name)) {
80       cerr << "package list is malformed" << endl;
81       std::abort();
82     }
83 
84     vector<string> components = fq_name.getPackageAndVersionComponents(false);
85     string spec_dir = GetSpecBaseDir() + Join(components, '/');
86     result.emplace_back(std::move(spec_dir));
87   }
88   return result;
89 }
90 
ExtractProtoFuzzerStaticParams(int argc,char ** argv)91 ProtoFuzzerParams ExtractProtoFuzzerStaticParams(int argc, char **argv) {
92   FQName package_and_version;
93   if (!FQName::parse(STRINGIFY(STATIC_TARGET_FQ_NAME), &package_and_version)) {
94     cerr << "STATIC_TARGET_FQ_NAME is malformed" << endl;
95     std::abort();
96   }
97 
98   string spec_data_list = STRINGIFY(STATIC_SPEC_DATA);
99   if (spec_data_list.empty()) {
100     cerr << "STATIC_SPEC_DATA is malformed" << endl;
101     std::abort();
102   }
103 
104   ProtoFuzzerParams params;
105   params.comp_specs_ = ExtractCompSpecs(ParseDirs(spec_data_list));
106 
107   // Find first interface in the given package that fits the bill.
108   params.target_fq_name_ =
109       FindAnyIfaceFQName(package_and_version, params.comp_specs_);
110   if (!params.target_fq_name_.isFullyQualified()) {
111     cerr << "HAL service name not available in VINTF." << endl;
112     std::exit(0);
113   }
114 
115   // Hard-coded values
116   params.exec_size_ = 16;
117   return params;
118 }
119 
120 }  // namespace fuzzer
121 }  // namespace vts
122 }  // namespace android
123