1 /*
2 * Copyright (c) 2021 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 "ExtractAndExecuteScript_fuzzer.h"
17
18 #include <array>
19 #include <cstddef>
20 #include <cstdint>
21 #include <fcntl.h>
22 #include <iostream>
23 #include <string>
24 #include <sys/mman.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include <vector>
28 #include "pkg_algorithm.h"
29 #include "pkg_algo_digest.h"
30 #include "pkg_utils.h"
31 #include "script_instructionhelper.h"
32 #include "script_manager_impl.h"
33 #include "script_utils.h"
34
35
36 using namespace hpackage;
37 using namespace uscript;
38 using namespace updater;
39
40 const static std::string TEST_PATH_TO = "/data/fuzz/test/";
41 const static int32_t SCRIPT_TEST_PRIORITY_NUM = 3;
42 const static int32_t SCRIPT_TEST_LAST_PRIORITY = 2;
43
GetTestCertName()44 static inline std::string GetTestCertName()
45 {
46 std::string name = TEST_PATH_TO;
47 name += "signing_cert.crt";
48 return name;
49 }
50
GetTestPrivateKeyName()51 static inline std::string GetTestPrivateKeyName()
52 {
53 std::string name = TEST_PATH_TO;
54 name += "rsa_private_key2048.pem";
55 return name;
56 }
57
58 class TestScriptInstructionSparseImageWrite : public uscript::UScriptInstruction {
59 public:
TestScriptInstructionSparseImageWrite()60 TestScriptInstructionSparseImageWrite() {}
~TestScriptInstructionSparseImageWrite()61 virtual ~TestScriptInstructionSparseImageWrite() {}
Execute(uscript::UScriptEnv & env,uscript::UScriptContext & context)62 int32_t Execute(uscript::UScriptEnv &env, uscript::UScriptContext &context) override
63 {
64 /* 从参数中获取分区信息 */
65 std::string partitionName;
66 int32_t ret = context.GetParam(0, partitionName);
67 if (ret != USCRIPT_SUCCESS) {
68 return ret;
69 }
70 if (env.GetPkgManager() == nullptr) {
71 return USCRIPT_ERROR_EXECUTE;
72 }
73 return ret;
74 }
75 };
76
77 class TestScriptInstructionFactory : public UScriptInstructionFactory {
78 public:
CreateInstructionInstance(UScriptInstructionPtr & instr,const std::string & name)79 virtual int32_t CreateInstructionInstance(UScriptInstructionPtr& instr, const std::string& name)
80 {
81 if (name == "sparse_image_write") {
82 instr = new TestScriptInstructionSparseImageWrite();
83 }
84 return USCRIPT_SUCCESS;
85 }
DestoryInstructionInstance(UScriptInstructionPtr & instr)86 virtual void DestoryInstructionInstance(UScriptInstructionPtr& instr)
87 {
88 delete instr;
89 }
TestScriptInstructionFactory()90 TestScriptInstructionFactory() {}
~TestScriptInstructionFactory()91 virtual ~TestScriptInstructionFactory() {}
92 };
93
94 class UTestScriptEnv : public UScriptEnv {
95 public:
96 UScriptInstructionFactory *factory_ = nullptr;
UTestScriptEnv(hpackage::PkgManager::PkgManagerPtr pkgManager)97 explicit UTestScriptEnv(hpackage::PkgManager::PkgManagerPtr pkgManager) : UScriptEnv(pkgManager) {}
~UTestScriptEnv()98 ~UTestScriptEnv()
99 {
100 if (factory_ != nullptr) {
101 delete factory_;
102 factory_ = nullptr;
103 }
104 }
105
PostMessage(const std::string & cmd,std::string content)106 virtual void PostMessage(const std::string &cmd, std::string content) {}
107
GetInstructionFactory()108 virtual UScriptInstructionFactoryPtr GetInstructionFactory()
109 {
110 if (factory_ == nullptr) {
111 factory_ = new TestScriptInstructionFactory();
112 }
113 return factory_;
114 }
115
GetInstructionNames() const116 virtual const std::vector<std::string> GetInstructionNames() const
117 {
118 static std::vector<std::string> updaterCmds = {"sparse_image_write"};
119 return updaterCmds;
120 }
121
IsRetry() const122 virtual bool IsRetry() const
123 {
124 return isRetry;
125 }
126 private:
127 bool isRetry = false;
128 };
129
130 class UScriptTest {
131 public:
UScriptTest()132 UScriptTest()
133 {
134 packageManager = PkgManager::GetPackageInstance();
135 }
136
~UScriptTest()137 ~UScriptTest()
138 {
139 packageManager = PkgManager::GetPackageInstance();
140 PkgManager::ReleasePackageInstance(packageManager);
141 ScriptManager::ReleaseScriptManager();
142 }
143
TestUscriptExecute(const std::vector<std::string> & inputFile)144 int TestUscriptExecute(const std::vector<std::string> &inputFile)
145 {
146 CreatePackageBin(inputFile);
147 packageManager = PkgManager::GetPackageInstance();
148 if (packageManager == nullptr) {
149 return PKG_SUCCESS;
150 }
151 std::vector<std::string> components;
152 int32_t ret = packageManager->LoadPackage(TEST_PATH_TO + testPackageName, GetTestCertName(), components);
153 if (ret != USCRIPT_SUCCESS) {
154 USCRIPT_LOGI("LoadPackage fail ret:%d", ret);
155 return USCRIPT_INVALID_SCRIPT;
156 }
157
158 UTestScriptEnv* env = new UTestScriptEnv(packageManager);
159 ScriptManager* manager = ScriptManager::GetScriptManager(env);
160 if (manager == nullptr) {
161 USCRIPT_LOGI("create manager fail ret:%d", ret);
162 delete env;
163 return USCRIPT_INVALID_SCRIPT;
164 }
165 int32_t priority = SCRIPT_TEST_PRIORITY_NUM;
166 ret = manager->ExecuteScript(priority);
167 USCRIPT_LOGI("ExecuteScript ret:%d", ret);
168 priority = 0;
169 ret = manager->ExecuteScript(priority);
170 USCRIPT_LOGI("ExecuteScript ret:%d", ret);
171 priority = 1;
172 ret = manager->ExecuteScript(priority);
173 priority = SCRIPT_TEST_LAST_PRIORITY;
174 ret = manager->ExecuteScript(priority);
175 delete env;
176 ScriptManager::ReleaseScriptManager();
177 return ret;
178 }
179
180 protected:
BuildFileDigest(uint8_t & digest,size_t size,const std::string & packagePath)181 int32_t BuildFileDigest(uint8_t &digest, size_t size, const std::string &packagePath)
182 {
183 PkgManager::StreamPtr stream = nullptr;
184 int32_t ret = packageManager->CreatePkgStream(stream, packagePath, 0, PkgStream::PkgStreamType_Read);
185 PKG_CHECK(ret == PKG_SUCCESS, packageManager->ClosePkgStream(stream);
186 return ret, "Create input stream fail %s", packagePath.c_str());
187 size_t fileLen = stream->GetFileLength();
188 PKG_CHECK(fileLen > 0, packageManager->ClosePkgStream(stream); return PKG_INVALID_FILE, "invalid file to load");
189 PKG_CHECK(fileLen <= SIZE_MAX, packageManager->ClosePkgStream(stream); return PKG_INVALID_FILE,
190 "Invalid file len %zu to load %s", fileLen, stream->GetFileName().c_str());
191
192 size_t buffSize = 4096;
193 PkgBuffer buff(buffSize);
194 // 整包检查
195 DigestAlgorithm::DigestAlgorithmPtr algorithm = PkgAlgorithmFactory::GetDigestAlgorithm(PKG_DIGEST_TYPE_SHA256);
196 PKG_CHECK(algorithm != nullptr, packageManager->ClosePkgStream(stream); return PKG_NOT_EXIST_ALGORITHM,
197 "Invalid file %s", stream->GetFileName().c_str());
198 algorithm->Init();
199
200 size_t offset = 0;
201 size_t readLen = 0;
202 while (offset < fileLen) {
203 ret = stream->Read(buff, offset, buffSize, readLen);
204 PKG_CHECK(ret == PKG_SUCCESS,
205 packageManager->ClosePkgStream(stream); return ret,
206 "read buffer fail %s", stream->GetFileName().c_str());
207 algorithm->Update(buff, readLen);
208
209 offset += readLen;
210 readLen = 0;
211 }
212 PkgBuffer signBuffer(&digest, size);
213 algorithm->Final(signBuffer);
214 packageManager->ClosePkgStream(stream);
215 return PKG_SUCCESS;
216 }
217
CreatePackageBin(const std::vector<std::string> & inputFile)218 int CreatePackageBin(const std::vector<std::string> &inputFile)
219 {
220 int32_t ret = PKG_SUCCESS;
221 uint32_t updateFileVersion = 1000;
222 uint32_t componentInfoIdBase = 100;
223 uint8_t componentInfoFlags = 22;
224 PKG_LOGI("\n\n ************* CreatePackageBin %s \r\n", testPackageName.c_str());
225 UpgradePkgInfoExt pkgInfo;
226 pkgInfo.softwareVersion = strdup("100.100.100.100");
227 pkgInfo.date = strdup("2021-02-02");
228 pkgInfo.time = strdup("21:23:49");
229 pkgInfo.productUpdateId = strdup("555.555.100.555");
230 pkgInfo.entryCount = inputFile.size();
231 pkgInfo.updateFileVersion = updateFileVersion;
232 pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA256;
233 pkgInfo.signMethod = PKG_SIGN_METHOD_RSA;
234 pkgInfo.pkgType = PKG_PACK_TYPE_UPGRADE;
235 std::string filePath;
236 ComponentInfoExt comp[inputFile.size()];
237 for (size_t i = 0; i < inputFile.size(); i++) {
238 comp[i].componentAddr = strdup(inputFile[i].c_str());
239 filePath = TEST_PATH_TO;
240 filePath += inputFile[i].c_str();
241 comp[i].filePath = strdup(filePath.c_str());
242 comp[i].version = strdup("55555555");
243
244 ret = BuildFileDigest(*comp[i].digest, sizeof(comp[i].digest), filePath);
245 comp[i].size = GetFileSize(filePath);
246 comp[i].originalSize = comp[i].size;
247 comp[i].id = componentInfoIdBase;
248 comp[i].resType = 1;
249 comp[i].type = 1;
250 comp[i].flags = componentInfoFlags;
251 filePath.clear();
252 }
253
254 std::string packagePath = TEST_PATH_TO;
255 packagePath += testPackageName;
256 ret = CreatePackage(&pkgInfo, comp, packagePath.c_str(), GetTestPrivateKeyName().c_str());
257 if (ret == 0) {
258 PKG_LOGI("CreatePackage success offset");
259 }
260 for (size_t i = 0; i < inputFile.size(); i++) {
261 free(comp[i].componentAddr);
262 free(comp[i].filePath);
263 free(comp[i].version);
264 }
265 free(pkgInfo.productUpdateId);
266 free(pkgInfo.softwareVersion);
267 free(pkgInfo.date);
268 free(pkgInfo.time);
269 return ret;
270 }
271
272 private:
273 PkgManager::PkgManagerPtr packageManager = nullptr;
274 std::string testPackageName = "test_package.bin";
275 };
276
ExtractAndExecuteScriptFun(const std::vector<std::string> & inputFile)277 static void ExtractAndExecuteScriptFun(const std::vector<std::string> &inputFile)
278 {
279 UScriptTest test;
280 test.TestUscriptExecute(inputFile);
281 }
282
283 namespace OHOS {
FuzzExtractAndExecuteScript(const uint8_t * data,size_t size)284 bool FuzzExtractAndExecuteScript(const uint8_t* data, size_t size)
285 {
286 FILE *pFile;
287 std::vector<std::string> inputFile = {
288 "loadScript.us",
289 "registerCmd.us",
290 "test_function.us",
291 "test_if.us",
292 "test_logic.us",
293 "test_math.us",
294 "test_native.us",
295 "testscript.us",
296 "Verse-script.us",
297 "test_script.us"
298 };
299
300 pFile = fopen("test_script.us", "w+");
301 if (pFile == nullptr) {
302 LOG(ERROR) << "[fuzz]open file failed";
303 return -1;
304 }
305
306 fwrite(data, 1, size, pFile);
307 fclose(pFile);
308
309 ExtractAndExecuteScriptFun(inputFile);
310 remove("test_script.us");
311 return 0;
312 }
313 }
314
315 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)316 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
317 {
318 /* Run your code on data */
319 OHOS::FuzzExtractAndExecuteScript(data, size);
320 return 0;
321 }
322
323