• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 <android-base/result.h>
18 #include <fuzzer/FuzzedDataProvider.h>
19 #include <stdlib.h>
20 #include <trusty/coverage/coverage.h>
21 #include <trusty/coverage/uuid.h>
22 #include <trusty/fuzz/counters.h>
23 #include <trusty/fuzz/utils.h>
24 #include <unistd.h>
25 #include <iostream>
26 #include <memory>
27 
28 using android::base::Result;
29 using android::trusty::coverage::CoverageRecord;
30 using android::trusty::fuzz::ExtraCounters;
31 using android::trusty::fuzz::TrustyApp;
32 
33 #define TIPC_DEV "/dev/trusty-ipc-dev0"
34 
35 #ifndef TRUSTY_APP_PORT
36 #error "Port name must be parameterized using -DTRUSTY_APP_PORT."
37 #endif
38 
39 #ifndef TRUSTY_APP_UUID
40 #error "UUID must be parameterized using -DTRUSTY_APP_UUID."
41 #endif
42 
43 #ifndef TRUSTY_APP_FILENAME
44 #error "Binary file name must be parameterized using -DTRUSTY_APP_FILENAME."
45 #endif
46 
47 #ifdef TRUSTY_APP_MAX_CONNECTIONS
48 constexpr size_t MAX_CONNECTIONS = TRUSTY_APP_MAX_CONNECTIONS;
49 #else
50 constexpr size_t MAX_CONNECTIONS = 1;
51 #endif
52 
53 static std::unique_ptr<CoverageRecord> record;
54 
LLVMFuzzerInitialize(int *,char ***)55 extern "C" int LLVMFuzzerInitialize(int* /* argc */, char*** /* argv */) {
56     uuid module_uuid;
57 
58     if (!str_to_uuid(TRUSTY_APP_UUID, &module_uuid)) {
59         std::cerr << "Failed to parse UUID: " << TRUSTY_APP_UUID << std::endl;
60         exit(-1);
61     }
62 
63     /* Make sure lazy-loaded TAs have started and connected to coverage service. */
64     TrustyApp ta(TIPC_DEV, TRUSTY_APP_PORT);
65     auto ret = ta.Connect();
66     if (!ret.ok()) {
67         std::cerr << ret.error() << std::endl;
68         exit(-1);
69     }
70 
71     record = std::make_unique<CoverageRecord>(TIPC_DEV, &module_uuid, TRUSTY_APP_FILENAME);
72     if (!record) {
73         std::cerr << "Failed to allocate coverage record" << std::endl;
74         exit(-1);
75     }
76 
77     ret = record->Open();
78     if (!ret.ok()) {
79         std::cerr << ret.error() << std::endl;
80         exit(-1);
81     }
82     return 0;
83 }
84 
abortResult(Result<void> result)85 void abortResult(Result<void> result) {
86     if (result.ok()) {
87         return;
88     }
89     std::cerr << result.error() << std::endl;
90     android::trusty::fuzz::Abort();
91 }
92 
testOneInput(FuzzedDataProvider & provider)93 void testOneInput(FuzzedDataProvider& provider) {
94     std::vector<TrustyApp> trustyApps;
95 
96     while (provider.remaining_bytes() > 0) {
97         static_assert(MAX_CONNECTIONS >= 1);
98 
99         // Either
100         // 1. (20%) Add a new TA and connect.
101         // 2. (20%) Remove a TA.
102         // 3. (60%) Send a random message to a random TA.
103         auto add_ta = [&]() {
104             if (trustyApps.size() >= MAX_CONNECTIONS) {
105                 return;
106             }
107             auto& ta = trustyApps.emplace_back(TIPC_DEV, TRUSTY_APP_PORT);
108             abortResult(ta.Connect());
109         };
110         auto remove_ta = [&]() {
111             if (trustyApps.empty()) {
112                 return;
113             }
114             trustyApps.pop_back();
115         };
116         auto send_message = [&]() {
117             if (trustyApps.empty()) {
118                 return;
119             }
120 
121             // Choose a random TA.
122             const auto i = provider.ConsumeIntegralInRange<size_t>(0, trustyApps.size() - 1);
123             std::swap(trustyApps[i], trustyApps.back());
124             auto& ta = trustyApps.back();
125 
126             // Send a random message.
127             const auto data = provider.ConsumeRandomLengthString();
128             abortResult(ta.Write(data.data(), data.size()));
129 
130             std::array<uint8_t, TIPC_MAX_MSG_SIZE> buf;
131             abortResult(ta.Read(buf.data(), buf.size()));
132 
133             // Reconnect to ensure that the service is still up.
134             ta.Disconnect();
135             abortResult(ta.Connect());
136         };
137         const std::function<void()> options[] = {
138                 add_ta,                                    // 1x: 20%
139                 remove_ta,                                 // 1x: 20%
140                 send_message, send_message, send_message,  // 3x: 60%
141         };
142 
143         provider.PickValueInArray(options)();
144     }
145 }
146 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)147 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
148     ExtraCounters counters(record.get());
149     counters.Reset();
150 
151     FuzzedDataProvider provider(data, size);
152     testOneInput(provider);
153     return 0;
154 }
155