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