blob: e8772733e6b849da6c5a496fcbca7f8875fcc761 [file] [log] [blame]
Aditya Wazir55fec452021-08-27 17:47:41 +05301/*
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 <update_engine/common/download_action.h>
18#include <update_engine/common/boot_control_stub.h>
19#include <update_engine/common/hardware_interface.h>
20#include <update_engine/common/http_fetcher.h>
21#include <update_engine/common/error_code.h>
22#include <update_engine/common/proxy_resolver.h>
23#include <update_engine/common/action_processor.h>
24#include <string.h>
25#include <utils/Log.h>
26#include <fuzzer/FuzzedDataProvider.h>
27
28using namespace chromeos_update_engine;
29using namespace std;
30
31constexpr size_t kSizeMin = 1;
32constexpr size_t kSizeMax = 1000;
33constexpr size_t kHashSize = 32;
34constexpr size_t kStringMaxLength = 20;
35const string kDownloadUrl = "http://fake_url.invalid";
36const string kSourcePath = "/dev/zero";
37const string kTargetPath = "/dev/null";
38
39class TestPrefsInterface : public PrefsInterface {
40 public:
41 TestPrefsInterface(FuzzedDataProvider* fdp) : mFdp(fdp) {
42 mMetadataSize = mFdp->ConsumeIntegralInRange<int64_t>(kSizeMin, kSizeMax);
43 mSignatureSize = mFdp->ConsumeIntegralInRange<int64_t>(kSizeMin, kSizeMax);
44 };
45
46 bool GetString(std::string_view key, std::string* value) const {
47 if (key == "manifest-bytes") {
48 *value = mFdp->ConsumeRandomLengthString(mMetadataSize + mSignatureSize);
49 return true;
50 }
51 *value = "";
52 return false;
53 };
54
55 bool SetString(std::string_view /*key*/, std::string_view /*value*/) {
56 return true;
57 };
58
59 bool GetInt64(std::string_view key, int64_t* value) const {
60 if (key == "manifest-metadata-size") {
61 *value = mMetadataSize;
62 return true;
63 }
64 if (key == "manifest-signature-size") {
65 *value = mSignatureSize;
66 return true;
67 }
68 *value = 0;
69 return false;
70 }
71
72 bool SetInt64(std::string_view /*key*/, const int64_t /*value*/) {
73 return true;
74 }
75
76 bool GetBoolean(std::string_view /*key*/, bool* value) const {
77 *value = true;
78 return true;
79 }
80
81 bool SetBoolean(std::string_view /*key*/, const bool /*value*/) {
82 return true;
83 }
84
85 bool Exists(std::string_view /*key*/) const { return true; }
86
87 bool Delete(std::string_view /*key*/) { return true; }
88
89 bool Delete(std::string_view /*pref_key*/,
90 const std::vector<std::string>& /*nss*/) {
91 return true;
92 }
93
94 bool GetSubKeys(std::string_view /*ns*/,
95 std::vector<std::string>* keys) const {
96 keys->push_back("");
97 return true;
98 }
99
100 void AddObserver(std::string_view /*key*/, ObserverInterface* /*observer*/) {}
101
102 void RemoveObserver(std::string_view /*key*/,
103 ObserverInterface* /*observer*/) {}
104
105 private:
106 FuzzedDataProvider* mFdp;
107 int64_t mMetadataSize;
108 int64_t mSignatureSize;
109};
110
111class TestHardwareInterface : public HardwareInterface {
112 public:
113 bool IsOfficialBuild() const { return true; };
114
115 bool IsNormalBootMode() const { return true; };
116
117 bool AreDevFeaturesEnabled() const { return true; };
118
119 bool IsOOBEEnabled() const { return true; };
120
121 bool IsOOBEComplete(base::Time* /*out_time_of_oobe*/) const { return true; };
122
123 string GetHardwareClass() const { return ""; };
124
125 string GetDeviceRequisition() const { return ""; };
126
127 int32_t GetMinKernelKeyVersion() const { return 0; };
128
129 int32_t GetMinFirmwareKeyVersion() const { return 0; };
130
131 int32_t GetMaxFirmwareKeyRollforward() const { return 0; };
132
133 bool SetMaxFirmwareKeyRollforward(int32_t /*firmware_max_rollforward*/) {
134 return true;
135 };
136
137 bool SetMaxKernelKeyRollforward(int32_t /*kernel_max_rollforward*/) {
138 return true;
139 };
140
141 int32_t GetPowerwashCount() const { return 0; };
142
143 bool SchedulePowerwash(bool /*save_rollback_data*/) { return true; };
144
145 bool CancelPowerwash() { return true; };
146
147 bool GetNonVolatileDirectory(base::FilePath* path) const {
148 base::FilePath local_path(constants::kNonVolatileDirectory);
149 *path = local_path;
150 return true;
151 };
152
153 bool GetPowerwashSafeDirectory(base::FilePath* /*path*/) const {
154 return false;
155 };
156
157 int64_t GetBuildTimestamp() const { return 0; };
158
159 bool AllowDowngrade() const { return true; };
160
161 bool GetFirstActiveOmahaPingSent() const { return true; };
162
163 bool SetFirstActiveOmahaPingSent() { return true; };
164
165 void SetWarmReset(bool /*warm_reset*/){};
166
167 void SetVbmetaDigestForInactiveSlot(bool /*reset*/){};
168
169 string GetVersionForLogging(const string& /*partition_name*/) const {
170 return "";
171 };
172
173 ErrorCode IsPartitionUpdateValid(const string& /*partition_name*/,
174 const string& /*new_version*/) const {
175 return ErrorCode::kSuccess;
176 };
177
178 const char* GetPartitionMountOptions(const string& /*partition_name*/) const {
179 return "";
180 };
181};
182
183class TestProxyResolver : public ProxyResolver {
184 public:
185 virtual ~TestProxyResolver() {}
186
187 ProxyRequestId GetProxiesForUrl(const string& /*url*/,
188 const ProxiesResolvedFn& /*callback*/) {
189 return 0;
190 };
191
192 bool CancelProxyRequest(ProxyRequestId /*request*/) { return true; };
193};
194
195class TestHttpFetcher : public HttpFetcher {
196 public:
197 TestHttpFetcher(ProxyResolver* proxy_resolver, FuzzedDataProvider* fdp)
198 : HttpFetcher(proxy_resolver), mFdp(fdp){};
199 virtual ~TestHttpFetcher() {}
200
201 void SetOffset(off_t /*offset*/) {}
202
203 void SetLength(size_t /*length*/) {}
204 void UnsetLength() {}
205
206 void BeginTransfer(const string& /*url*/) {
207 if (mFdp->remaining_bytes() > 0) {
208 size_t maxSize = mFdp->ConsumeIntegralInRange<size_t>(kSizeMin, kSizeMax);
209 vector<uint8_t> data = mFdp->ConsumeBytes<uint8_t>(maxSize);
210 delegate()->ReceivedBytes(this, data.data(), data.size());
211 }
212 }
213
214 void TerminateTransfer() {}
215
216 void SetHeader(const string& /*header_name*/,
217 const string& /*header_value*/) {}
218
219 bool GetHeader(const string& /*header_name*/, string* header_value) const {
220 *header_value = "";
221 return true;
222 }
223
224 void Pause() {}
225
226 void Unpause() {}
227
228 void set_idle_seconds(int32_t /*seconds*/) {}
229 void set_retry_seconds(int32_t /*seconds*/) {}
230
231 void set_low_speed_limit(int32_t /*low_speed_bps*/,
232 int32_t /*low_speed_sec*/) {}
233
234 void set_connect_timeout(int32_t /*connect_timeout_seconds*/) {}
235
236 void set_max_retry_count(int32_t /*max_retry_count*/) {}
237
238 size_t GetBytesDownloaded() { return 0; }
239
240 private:
241 FuzzedDataProvider* mFdp;
242};
243
244class TestActionProcessor : public ActionProcessor {
245 public:
246 void StartProcessing() {}
247
248 void EnqueueAction(unique_ptr<AbstractAction> /*action*/){};
249
250 void ActionComplete(AbstractAction* /*actionptr*/, ErrorCode /*code*/){};
251};
252
253class chromeos_update_engine::DownloadActionTest {
254 public:
255 DownloadActionTest() : mActionPipe(new ActionPipe<InstallPlan>()) {}
256 ~DownloadActionTest() { mActionPipe = nullptr; }
257
258 void fuzzDownloadAction(const uint8_t* data, size_t size);
259
260 private:
261 shared_ptr<ActionPipe<InstallPlan>> mActionPipe = nullptr;
262};
263
264void DownloadActionTest::fuzzDownloadAction(const uint8_t* data, size_t size) {
265 FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
266
267 InstallPlan install_plan;
268 install_plan.download_url = kDownloadUrl;
269 install_plan.version = fdp.ConsumeRandomLengthString(kStringMaxLength);
270 install_plan.target_slot = fdp.ConsumeBool() ? 0 : 1;
271 install_plan.hash_checks_mandatory = fdp.ConsumeBool();
272 InstallPlan::Partition partition;
273 partition.name = fdp.ConsumeRandomLengthString(kStringMaxLength);
274 partition.source_path = kSourcePath;
275 partition.source_size = fdp.ConsumeIntegralInRange(kSizeMin, kSizeMax);
276 partition.target_path = kTargetPath;
277 partition.target_size = fdp.ConsumeIntegralInRange(kSizeMin, kSizeMax);
278 install_plan.partitions.push_back(partition);
279 InstallPlan::Payload payload;
280 payload.payload_urls.emplace_back(kDownloadUrl);
281 payload.size = fdp.ConsumeIntegralInRange(kSizeMin, kSizeMax);
282 payload.metadata_size =
283 fdp.ConsumeIntegralInRange<uint64_t>(kSizeMin, kSizeMax),
284 payload.hash = fdp.ConsumeBytes<uint8_t>(kHashSize),
285 payload.already_applied = fdp.ConsumeBool();
286 install_plan.payloads.push_back(payload);
287 install_plan.is_resume = fdp.ConsumeBool();
288 mActionPipe->set_contents(install_plan);
289
290 TestPrefsInterface prefs(&fdp);
291 BootControlStub boot_control;
292 TestHardwareInterface hardwareInterface;
293 TestProxyResolver proxyResolver;
294 TestHttpFetcher* httpFetcher = new TestHttpFetcher(&proxyResolver, &fdp);
295 bool interactive = fdp.ConsumeBool();
296 unique_ptr<DownloadAction> downloadAction = make_unique<DownloadAction>(
297 &prefs, &boot_control, &hardwareInterface, httpFetcher, interactive);
298
299 downloadAction->set_in_pipe(mActionPipe);
300 TestActionProcessor actionProcessor;
301 downloadAction->SetProcessor(&actionProcessor);
302
303 downloadAction->PerformAction();
304}
305extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
306 DownloadActionTest downloadActionFuzzer;
307 downloadActionFuzzer.fuzzDownloadAction(data, size);
308 return 0;
309}