1 /*
2  * Copyright (c) 2022-2024 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 "external_file_access_fuzzer.h"
17 
18 #include <cstdio>
19 #include <thread>
20 #include <unistd.h>
21 
22 #include "accesstoken_kit.h"
23 #include "token_setproc.h"
24 #include "nativetoken_kit.h"
25 #include "file_access_framework_errno.h"
26 #include "file_access_helper.h"
27 #include "file_info_shared_memory.h"
28 #include "iservice_registry.h"
29 #include "hilog_wrapper.h"
30 
31 namespace OHOS {
32 using namespace std;
33 using namespace OHOS;
34 using namespace FileAccessFwk;
35 
36 const int ABILITY_ID = 5003;
37 shared_ptr<FileAccessHelper> g_fah = nullptr;
38 const int UID_TRANSFORM_TMP = 20000000;
39 const int UID_DEFAULT = 0;
40 
SetNativeToken()41 void SetNativeToken()
42 {
43     uint64_t tokenId;
44     const char *perms[] = {
45         "ohos.permission.FILE_ACCESS_MANAGER",
46         "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED",
47         "ohos.permission.CONNECT_FILE_ACCESS_EXTENSION"
48     };
49     NativeTokenInfoParams infoInstance = {
50         .dcapsNum = 0,
51         .permsNum = 3,
52         .aclsNum = 0,
53         .dcaps = nullptr,
54         .perms = perms,
55         .acls = nullptr,
56         .aplStr = "system_core",
57     };
58 
59     infoInstance.processName = "SetUpTestCase";
60     tokenId = GetAccessTokenId(&infoInstance);
61     const uint64_t systemAppMask = (static_cast<uint64_t>(1) << 32);
62     tokenId |= systemAppMask;
63     SetSelfTokenID(tokenId);
64     OHOS::Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo();
65 }
66 
GetFileAccessHelper()67 shared_ptr<FileAccessHelper> GetFileAccessHelper()
68 {
69     if (g_fah != nullptr) {
70         return g_fah;
71     }
72     SetNativeToken();
73     auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
74     if (saManager == nullptr) {
75         return nullptr;
76     }
77     auto remoteObj = saManager->GetSystemAbility(ABILITY_ID);
78     AAFwk::Want want;
79     vector<AAFwk::Want> wantVec;
80     setuid(UID_TRANSFORM_TMP);
81     int ret = FileAccessHelper::GetRegisteredFileAccessExtAbilityInfo(wantVec);
82     if (ret != OHOS::FileAccessFwk::ERR_OK) {
83         HILOG_ERROR("GetRegisteredFileAccessExtAbilityInfo failed.");
84         return nullptr;
85     }
86     bool sus = false;
87     for (size_t i = 0; i < wantVec.size(); i++) {
88         auto element = wantVec[i].GetElement();
89         if (element.GetBundleName() == "com.ohos.UserFile.ExternalFileManager" &&
90             element.GetAbilityName() == "FileExtensionAbility") {
91             want = wantVec[i];
92             sus = true;
93             break;
94         }
95     }
96     if (!sus) {
97         HILOG_ERROR("not found bundleName.");
98         return nullptr;
99     }
100     vector<AAFwk::Want> wants {want};
101     g_fah = FileAccessHelper::Creator(remoteObj, wants);
102     setuid(UID_DEFAULT);
103     if (g_fah == nullptr) {
104         HILOG_ERROR("creator fileAccessHelper return nullptr.");
105         return nullptr;
106     }
107     return g_fah;
108 }
109 
CreatorFuzzTest(const uint8_t * data,size_t size)110 bool CreatorFuzzTest(const uint8_t* data, size_t size)
111 {
112     SetNativeToken();
113     if ((data == nullptr) || (size <= 0)) {
114         HILOG_ERROR("parameter data is nullptr or parameter size <= 0.");
115         return false;
116     }
117     std::string bundleName(reinterpret_cast<const char*>(data), size);
118     auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
119     if (saManager == nullptr) {
120         return false;
121     }
122     auto remoteObj = saManager->GetSystemAbility(ABILITY_ID);
123     AAFwk::Want want;
124     want.SetElementName(bundleName, "FileExtensionAbility");
125     vector<AAFwk::Want> wants {want};
126     setuid(UID_TRANSFORM_TMP);
127     shared_ptr<FileAccessHelper> helper = nullptr;
128     helper = FileAccessHelper::Creator(remoteObj, wants);
129     setuid(UID_DEFAULT);
130     if (helper == nullptr) {
131         HILOG_ERROR("creator return nullptr.");
132         return false;
133     }
134     helper->Release();
135     return true;
136 }
137 
CheckDataAndHelper(const uint8_t * data,size_t size,shared_ptr<FileAccessHelper> & helper)138 bool CheckDataAndHelper(const uint8_t* data, size_t size, shared_ptr<FileAccessHelper>& helper)
139 {
140     if ((data == nullptr) || (size <= 0)) {
141         HILOG_ERROR("parameter data is nullptr or parameter size <= 0.");
142         return false;
143     }
144     helper = GetFileAccessHelper();
145     if (helper == nullptr) {
146         HILOG_ERROR("GetFileAccessHelper return nullptr.");
147         return false;
148     }
149     return true;
150 }
151 
AccessFuzzTest(const uint8_t * data,size_t size)152 bool AccessFuzzTest(const uint8_t* data, size_t size)
153 {
154     shared_ptr<FileAccessHelper> helper;
155     if (!CheckDataAndHelper(data, size, helper)) {
156         return false;
157     }
158     Uri uri(std::string(reinterpret_cast<const char*>(data), size));
159     bool isExist = false;
160     int result = helper->Access(uri, isExist);
161     if (isExist != true || result != OHOS::FileAccessFwk::ERR_OK) {
162         return false;
163     }
164     return true;
165 }
166 
OpenFileFuzzTest(const uint8_t * data,size_t size)167 bool OpenFileFuzzTest(const uint8_t* data, size_t size)
168 {
169     shared_ptr<FileAccessHelper> helper;
170     if (!CheckDataAndHelper(data, size, helper)) {
171         return false;
172     }
173     Uri uri(std::string(reinterpret_cast<const char*>(data), size));
174     int fd = -1;
175     int result = 0;
176     result = helper->OpenFile(uri, WRITE_READ, fd);
177     if (result != OHOS::FileAccessFwk::ERR_OK) {
178         HILOG_ERROR("OpenFile failed. ret : %{public}d", result);
179         return false;
180     }
181     close(fd);
182     return true;
183 }
184 
CreateFileFuzzTest(const uint8_t * data,size_t size)185 bool CreateFileFuzzTest(const uint8_t* data, size_t size)
186 {
187     shared_ptr<FileAccessHelper> helper;
188     if (!CheckDataAndHelper(data, size, helper)) {
189         return false;
190     }
191 
192     vector<RootInfo> info;
193     int result = helper->GetRoots(info);
194     if (result != OHOS::FileAccessFwk::ERR_OK) {
195         HILOG_ERROR("GetRoots failed. ret : %{public}d", result);
196         return false;
197     }
198     for (size_t i = 0; i < info.size(); i++) {
199         Uri parentUri(info[i].uri);
200         Uri newFileUri("");
201         result = helper->CreateFile(parentUri, "CreateFileFuzzTest", newFileUri);
202         if (result != OHOS::FileAccessFwk::ERR_OK) {
203             HILOG_ERROR("CreateFile failed. ret : %{public}d", result);
204             return false;
205         }
206         result = helper->Delete(newFileUri);
207         if (result != OHOS::FileAccessFwk::ERR_OK) {
208             HILOG_ERROR("Delete failed. ret : %{public}d", result);
209             return false;
210         }
211     }
212     return true;
213 }
214 
MkdirFuzzTest(const uint8_t * data,size_t size)215 bool MkdirFuzzTest(const uint8_t* data, size_t size)
216 {
217     shared_ptr<FileAccessHelper> helper;
218     if (!CheckDataAndHelper(data, size, helper)) {
219         return false;
220     }
221 
222     vector<RootInfo> info;
223     int result = helper->GetRoots(info);
224     if (result != OHOS::FileAccessFwk::ERR_OK) {
225         HILOG_ERROR("GetRoots failed. ret : %{public}d", result);
226         return false;
227     }
228     for (size_t i = 0; i < info.size(); i++) {
229         Uri parentUri(info[i].uri);
230         Uri newDirUri("");
231         result = helper->Mkdir(parentUri, "MkdirFuzzTest", newDirUri);
232         if (result != OHOS::FileAccessFwk::ERR_OK) {
233             HILOG_ERROR("Mkdir failed. ret : %{public}d", result);
234             return false;
235         }
236         result = helper->Delete(newDirUri);
237         if (result != OHOS::FileAccessFwk::ERR_OK) {
238             HILOG_ERROR("Delete failed. ret : %{public}d", result);
239             return false;
240         }
241     }
242     return true;
243 }
244 
DeleteFuzzTest(const uint8_t * data,size_t size)245 bool DeleteFuzzTest(const uint8_t* data, size_t size)
246 {
247     shared_ptr<FileAccessHelper> helper;
248     if (!CheckDataAndHelper(data, size, helper)) {
249         return false;
250     }
251     Uri uri(std::string(reinterpret_cast<const char*>(data), size));
252     int result = helper->Delete(uri);
253     if (result != OHOS::FileAccessFwk::ERR_OK) {
254         HILOG_ERROR("Delete failed. ret : %{public}d", result);
255         return false;
256     }
257     return true;
258 }
259 
MoveFuzzTest(const uint8_t * data,size_t size)260 bool MoveFuzzTest(const uint8_t* data, size_t size)
261 {
262     shared_ptr<FileAccessHelper> helper;
263     if (!CheckDataAndHelper(data, size, helper)) {
264         return false;
265     }
266     vector<RootInfo> info;
267     int result = helper->GetRoots(info);
268     if (result != OHOS::FileAccessFwk::ERR_OK) {
269         return false;
270     }
271     for (size_t i = 0; i < info.size(); i++) {
272         Uri parentUri(info[i].uri);
273         Uri newDirUriTest1("");
274         Uri newDirUriTest2("");
275         int result1 = helper->Mkdir(parentUri, "test1", newDirUriTest1);
276         int result2 = helper->Mkdir(parentUri, "test2", newDirUriTest2);
277         if (result1 != OHOS::FileAccessFwk::ERR_OK || result2 != OHOS::FileAccessFwk::ERR_OK) {
278             HILOG_ERROR("Mkdir failed. ret : %{public}d, %{public}d", result1, result2);
279             return false;
280         }
281         Uri testUri("");
282         result = helper->CreateFile(newDirUriTest1, "test.txt", testUri);
283         if (result != OHOS::FileAccessFwk::ERR_OK) {
284             HILOG_ERROR("CreateFile failed. ret : %{public}d", result);
285             return false;
286         }
287         Uri testUri2("");
288         result = helper->Move(testUri, newDirUriTest2, testUri2);
289         if (result != OHOS::FileAccessFwk::ERR_OK) {
290             HILOG_ERROR("Move failed. ret : %{public}d", result);
291             return false;
292         }
293         result1 = helper->Delete(newDirUriTest1);
294         result2 = helper->Delete(newDirUriTest2);
295         if (result1 != OHOS::FileAccessFwk::ERR_OK || result2 != OHOS::FileAccessFwk::ERR_OK) {
296             HILOG_ERROR("Delete failed. ret : %{public}d, %{public}d", result1, result2);
297             return false;
298         }
299     }
300     return true;
301 }
302 
RenameFuzzTest(const uint8_t * data,size_t size)303 bool RenameFuzzTest(const uint8_t* data, size_t size)
304 {
305     shared_ptr<FileAccessHelper> helper;
306     if (!CheckDataAndHelper(data, size, helper)) {
307         return false;
308     }
309     vector<RootInfo> info;
310     int result = helper->GetRoots(info);
311     if (result != OHOS::FileAccessFwk::ERR_OK) {
312         HILOG_ERROR("GetRoots failed. ret : %{public}d", result);
313         return false;
314     }
315     for (size_t i = 0; i < info.size(); i++) {
316         Uri parentUri(info[i].uri);
317         Uri newDirUriTest("");
318         result = helper->Mkdir(parentUri, "test", newDirUriTest);
319         if (result != OHOS::FileAccessFwk::ERR_OK) {
320             HILOG_ERROR("Mkdir failed. ret : %{public}d", result);
321             return false;
322         }
323         Uri renameUri("");
324         result = helper->Rename(newDirUriTest, "testRename", renameUri);
325         if (result != OHOS::FileAccessFwk::ERR_OK) {
326             HILOG_ERROR("Rename failed. ret : %{public}d", result);
327             return false;
328         }
329         result = helper->Delete(renameUri);
330         if (result != OHOS::FileAccessFwk::ERR_OK) {
331             HILOG_ERROR("Delete failed. ret : %{public}d", result);
332             return false;
333         }
334     }
335     return true;
336 }
337 
ListFileFuzzTest(const uint8_t * data,size_t size)338 bool ListFileFuzzTest(const uint8_t* data, size_t size)
339 {
340     if ((data == nullptr) || (size == 0)) {
341         HILOG_ERROR("parameter data is nullptr or parameter size <= 0.");
342         return false;
343     }
344     shared_ptr<FileAccessHelper> helper = GetFileAccessHelper();
345     if (helper == nullptr) {
346         HILOG_ERROR("GetFileAccessHelper return nullptr.");
347         return false;
348     }
349 
350     FileInfo fileInfo;
351     fileInfo.uri = std::string(reinterpret_cast<const char*>(data), size);
352     int64_t offset = 0;
353     SharedMemoryInfo memInfo;
354     int result = SharedMemoryOperation::CreateSharedMemory("FileInfo List", DEFAULT_CAPACITY_200KB,
355         memInfo);
356     if (result != OHOS::FileAccessFwk::ERR_OK) {
357         HILOG_ERROR("CreateSharedMemory failed. ret : %{public}d", result);
358         return false;
359     }
360     FileFilter filter;
361     result = helper->ListFile(fileInfo, offset, filter, memInfo);
362     SharedMemoryOperation::DestroySharedMemory(memInfo);
363     if (result != OHOS::FileAccessFwk::ERR_OK) {
364         HILOG_ERROR("ListFile failed. ret : %{public}d", result);
365         return false;
366     }
367     return true;
368 }
369 
ScanFileFuzzTest(const uint8_t * data,size_t size)370 bool ScanFileFuzzTest(const uint8_t* data, size_t size)
371 {
372     if ((data == nullptr) || (size == 0)) {
373         HILOG_ERROR("parameter data is nullptr or parameter size <= 0.");
374         return false;
375     }
376     shared_ptr<FileAccessHelper> helper = GetFileAccessHelper();
377     if (helper == nullptr) {
378         HILOG_ERROR("GetFileAccessHelper return nullptr.");
379         return false;
380     }
381 
382     FileInfo fileInfo;
383     fileInfo.uri = std::string(reinterpret_cast<const char*>(data), size);
384     int64_t offset = 0;
385     int64_t maxCount = 1000;
386     std::vector<FileInfo> fileInfoVec;
387     FileFilter filter;
388     int result = helper->ScanFile(fileInfo, offset, maxCount, filter, fileInfoVec);
389     if (result != OHOS::FileAccessFwk::ERR_OK) {
390         HILOG_ERROR("ScanFile failed. ret : %{public}d", result);
391         return false;
392     }
393     return true;
394 }
395 
GetFileInfoFromUriFuzzTest(const uint8_t * data,size_t size)396 bool GetFileInfoFromUriFuzzTest(const uint8_t* data, size_t size)
397 {
398     if ((data == nullptr) || (size == 0)) {
399         HILOG_ERROR("parameter data is nullptr or parameter size <= 0.");
400         return false;
401     }
402     Uri uri(std::string(reinterpret_cast<const char*>(data), size));
403     shared_ptr<FileAccessHelper> helper = GetFileAccessHelper();
404     if (helper == nullptr) {
405         HILOG_ERROR("GetFileAccessHelper return nullptr.");
406         return false;
407     }
408     FileInfo fileinfo;
409     int result = helper->GetFileInfoFromUri(uri, fileinfo);
410     if (result != OHOS::FileAccessFwk::ERR_OK) {
411         HILOG_ERROR("GetFileInfoFromUri failed. ret : %{public}d", result);
412         return false;
413     }
414     return true;
415 }
416 
417 }
418 
419 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)420 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
421 {
422     /* Run your code on data */
423     OHOS::CreatorFuzzTest(data, size);
424     OHOS::AccessFuzzTest(data, size);
425     OHOS::OpenFileFuzzTest(data, size);
426     OHOS::MkdirFuzzTest(data, size);
427     OHOS::CreateFileFuzzTest(data, size);
428     OHOS::DeleteFuzzTest(data, size);
429     OHOS::MoveFuzzTest(data, size);
430     OHOS::RenameFuzzTest(data, size);
431     OHOS::ListFileFuzzTest(data, size);
432     OHOS::ScanFileFuzzTest(data, size);
433     OHOS::GetFileInfoFromUriFuzzTest(data, size);
434     return 0;
435 }
436