1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "updatermain_fuzzer.h"
17 
18 #include <array>
19 #include <cstddef>
20 #include <cstdint>
21 #include <iostream>
22 #include <string>
23 #include <vector>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include "log/log.h"
27 #include "updater_main.h"
28 #include "misc_info/misc_info.h"
29 #include "updater/updater_const.h"
30 #include "securec.h"
31 #include "utils.h"
32 #include "updater/updater.h"
33 #include "updater_ui_stub.h"
34 
35 using namespace Updater;
36 using namespace std;
37 constexpr uint32_t MAX_ARG_SIZE = 10;
38 
ParseParamsFuzzTest()39 static void ParseParamsFuzzTest()
40 {
41     UpdateMessage boot {};
42     const std::string commandFile = "/data/updater/command";
43     auto fp = std::unique_ptr<FILE, decltype(&fclose)>(fopen(commandFile.c_str(), "wb"), fclose);
44     if (fp == nullptr) {
45         return;
46     }
47     const std::string commandMsg = "boot_updater";
48     if (strncpy_s(boot.command, sizeof(boot.command) - 1, commandMsg.c_str(), commandMsg.size()) != 0) {
49         return;
50     }
51     if (strncpy_s(boot.update, sizeof(boot.update), "", sizeof(boot.update)) != 0) {
52         return;
53     }
54     WriteUpdaterMessage(commandFile, boot);
55     char **argv = new char *[1];
56     argv[0] = new char[MAX_ARG_SIZE];
57     if (strncpy_s(argv[0], MAX_ARG_SIZE, "./main", MAX_ARG_SIZE) != 0) {
58         return;
59     }
60     int argc = 1;
61     Utils::ParseParams(argc, argv);
62     PostUpdater(true);
63     delete argv[0];
64     delete []argv;
65 }
66 
MianUpdaterFuzzTest()67 static void MianUpdaterFuzzTest()
68 {
69     int argsSize = 24;
70     UpdateMessage boot {};
71     if (access("/data/updater/", 0)) {
72         int ret = mkdir("/data/updater/", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
73         if (ret != 0) {
74             return;
75         }
76     }
77     const std::string commandFile = "/data/updater/command";
78     auto fp = std::unique_ptr<FILE, decltype(&fclose)>(fopen(commandFile.c_str(), "wb"), fclose);
79     if (fp == nullptr) {
80         return;
81     }
82 
83     const std::string commandMsg = "boot_updater";
84     const std::string updateMsg = "--update_package=/data/updater/updater/updater_full.zip";
85     if (strncpy_s(boot.command, sizeof(boot.command) - 1, commandMsg.c_str(), commandMsg.size()) != 0) {
86         return;
87     }
88     if (strncpy_s(boot.update, sizeof(boot.update) - 1, updateMsg.c_str(), updateMsg.size()) != 0) {
89         return;
90     }
91     bool bRet = WriteUpdaterMessage(commandFile, boot);
92     if (!bRet) {
93         return;
94     }
95     char **argv = new char* [1];
96     argv[0] = new char[argsSize];
97     if (strncpy_s(argv[0], argsSize, "./UpdaterMain", argsSize) != 0) {
98         return;
99     }
100     int argc = 1;
101 
102     int ret = UpdaterMain(argc, argv);
103     if (!ret) {
104         return;
105     }
106     delete argv[0];
107     delete []argv;
108 }
109 
SdCardUpdateFuzzTest()110 static void SdCardUpdateFuzzTest()
111 {
112     int argsSize = 24;
113     UpdateMessage boot {};
114     if (access("/data/updater/", 0)) {
115         int ret = mkdir("/data/updater/", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
116         if (ret != 0) {
117             return;
118         }
119     }
120     const std::string commandFile = "/data/updater/command";
121     auto fp = std::unique_ptr<FILE, decltype(&fclose)>(fopen(commandFile.c_str(), "wb"), fclose);
122     if (fp == nullptr) {
123         return;
124     }
125     const std::string commandMsg = "boot_updater";
126     const std::string updateMsg = "--sdcard_update";
127     if (strncpy_s(boot.command, sizeof(boot.command) - 1, commandMsg.c_str(), commandMsg.size()) != 0) {
128         return;
129     }
130     if (strncpy_s(boot.update, sizeof(boot.update) - 1, updateMsg.c_str(), updateMsg.size()) != 0) {
131         return;
132     }
133     bool bRet = WriteUpdaterMessage(commandFile, boot);
134     if (!bRet) {
135         return;
136     }
137     char **argv = new char* [1];
138     argv[0] = new char[argsSize];
139     if (strncpy_s(argv[0], argsSize, "./UpdaterMain", argsSize) != 0) {
140         return;
141     }
142     int argc = 1;
143     if (UpdaterMain(argc, argv) != 0) {
144         return;
145     }
146     delete argv[0];
147     delete []argv;
148 }
149 
InstallUpdaterPackageFuzzTest()150 static void InstallUpdaterPackageFuzzTest()
151 {
152     UpdaterParams upParams;
153     upParams.retryCount = 0;
154     upParams.callbackProgress = [] (float value) { UPDATER_UI_INSTANCE.ShowProgress(value); };
155     upParams.updatePackage.push_back("/data/updater/updater/updater_full.zip");
156     Hpackage::PkgManager::PkgManagerPtr pkgManager = Hpackage::PkgManager::CreatePackageInstance();
157     if (InstallUpdaterPackage(upParams, pkgManager) != UPDATE_ERROR) {
158         return;
159     }
160 }
161 
DoUpdatePackagesFuzzTest()162 static void DoUpdatePackagesFuzzTest()
163 {
164     UpdaterParams upParams;
165     if (DoUpdatePackages(upParams) != UPDATE_CORRUPT) {
166         return;
167     }
168     upParams.updatePackage.push_back("/data/updater/updater/updater_full.zip");
169     if (DoUpdatePackages(upParams) != UPDATE_CORRUPT) {
170         return;
171     }
172 }
173 
StartUpdaterEntryFuzzTest()174 static void StartUpdaterEntryFuzzTest()
175 {
176     UpdaterParams upParams;
177     upParams.factoryResetMode = "factory_wipe_data";
178     if (DoUpdatePackages(upParams) != UPDATE_CORRUPT) {
179         return;
180     }
181     upParams.factoryResetMode = "user_wipe_data";
182     if (DoUpdatePackages(upParams) != UPDATE_CORRUPT) {
183         return;
184     }
185     upParams.factoryResetMode = "menu_wipe_data";
186     if (DoUpdatePackages(upParams) != UPDATE_CORRUPT) {
187         return;
188     }
189     upParams.factoryResetMode = "";
190     if (DoUpdatePackages(upParams) != UPDATE_CORRUPT) {
191         return;
192     }
193 }
194 
ExtractUpdaterBinaryFuzzTest()195 static void ExtractUpdaterBinaryFuzzTest()
196 {
197     Hpackage::PkgManager::PkgManagerPtr pkgManager = Hpackage::PkgManager::CreatePackageInstance();
198     std::string path = "xxx";
199     int32_t ret = ExtractUpdaterBinary(pkgManager, path, UPDATER_BINARY);
200     if (ret != 1) {
201         return;
202     }
203     path = "/data/updater/updater/updater_full.zip";
204     ret = ExtractUpdaterBinary(pkgManager, path, UPDATER_BINARY);
205     Hpackage::PkgManager::ReleasePackageInstance(pkgManager);
206     if (ret != 1) {
207         return;
208     }
209 }
210 
IsSpaceCapacitySufficientFuzzTest()211 static void IsSpaceCapacitySufficientFuzzTest()
212 {
213     UpdaterParams upParams {};
214     UpdaterStatus status = IsSpaceCapacitySufficient(upParams);
215     if (status != UPDATE_ERROR) {
216         return;
217     }
218     if (CheckStatvfs(0) != 0) {
219         return;
220     }
221     if (IsBatteryCapacitySufficient()) {
222         return;
223     }
224     upParams.updatePackage.push_back("/data/updater/updater/updater_full.zip");
225     status = IsSpaceCapacitySufficient(upParams);
226     if (status != UPDATE_SUCCESS) {
227         return;
228     }
229 }
230 
ProgressFuzzTest()231 static void ProgressFuzzTest()
232 {
233     int progress = 0;
234     SetTmpProgressValue(progress);
235     if (GetTmpProgressValue() != 0) {
236         return;
237     }
238     ProgressSmoothHandler(0, 1);
239 }
240 
UtilsFuzzTest(const uint8_t * data,size_t size)241 static void UtilsFuzzTest(const uint8_t* data, size_t size)
242 {
243     if (!Utils::IsDirExist(std::string(reinterpret_cast<const char*>(data), size))) {
244         return;
245     }
246     std::vector<std::string> files {};
247     if (Utils::GetFilesFromDirectory(std::string(reinterpret_cast<const char*>(data), size), files, false) < 0) {
248         return;
249     }
250     std::string filePath = std::string(reinterpret_cast<const char*>(data), size) + "MountForPath_fuzzer.fstable";
251     if (!Utils::IsFileExist(filePath)) {
252         return;
253     }
254 }
255 
256 namespace OHOS {
FuzzUpdater(const uint8_t * data,size_t size)257     void FuzzUpdater(const uint8_t* data, size_t size)
258     {
259         ParseParamsFuzzTest();
260         MianUpdaterFuzzTest();
261         SdCardUpdateFuzzTest();
262         InstallUpdaterPackageFuzzTest();
263         DoUpdatePackagesFuzzTest();
264         StartUpdaterEntryFuzzTest();
265         ExtractUpdaterBinaryFuzzTest();
266         IsSpaceCapacitySufficientFuzzTest();
267         ProgressFuzzTest();
268         UtilsFuzzTest(data, size);
269     }
270 }
271 
272 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)273 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
274 {
275     /* Run your code on data */
276     OHOS::FuzzUpdater(data, size);
277     return 0;
278 }
279 
280