• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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