1 /*
2  * Copyright (c) 2022 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 "medialibrary_file_access_fuzzer.h"
17 
18 #include <cstdio>
19 #include <thread>
20 #include <unistd.h>
21 #include <tuple>
22 
23 #include "accesstoken_kit.h"
24 #include "token_setproc.h"
25 #include "nativetoken_kit.h"
26 #include "file_access_framework_errno.h"
27 #include "file_access_helper.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.medialibrary.medialibrarydata" &&
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     if (g_fah == nullptr) {
103         HILOG_ERROR("creator fileAccessHelper return nullptr.");
104         return nullptr;
105     }
106     setuid(UID_DEFAULT);
107     return g_fah;
108 }
109 
CheckDataAndGetDownloadUri(const uint8_t * data,size_t size,shared_ptr<FileAccessHelper> & helper,Uri & downloadUri)110 bool CheckDataAndGetDownloadUri(const uint8_t* data, size_t size, shared_ptr<FileAccessHelper>& helper,
111     Uri& downloadUri)
112 {
113     if ((data == nullptr) || (size <= 0)) {
114         HILOG_ERROR("parameter data is nullptr or parameter size <= 0.");
115         return false;
116     }
117     std::tie(helper, downloadUri) = GetDownloadUri();
118     if (helper == nullptr || downloadUri.ToString() == "") {
119         HILOG_ERROR("helper is nullptr or downloadUri is empty");
120         return false;
121     }
122     return true;
123 }
124 
CreatorFuzzTest(const uint8_t * data,size_t size)125 bool CreatorFuzzTest(const uint8_t* data, size_t size)
126 {
127     SetNativeToken();
128     if ((data == nullptr) || (size <= 0)) {
129         HILOG_ERROR("parameter data is nullptr or parameter size <= 0.");
130         return false;
131     }
132     std::string bundleName(reinterpret_cast<const char*>(data), size);
133     auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
134     if (saManager == nullptr) {
135         return nullptr;
136     }
137     auto remoteObj = saManager->GetSystemAbility(ABILITY_ID);
138     AAFwk::Want want;
139     want.SetElementName(bundleName, "FileExtensionAbility");
140     vector<AAFwk::Want> wants {want};
141     setuid(UID_TRANSFORM_TMP);
142     shared_ptr<FileAccessHelper> helper = nullptr;
143     helper = FileAccessHelper::Creator(remoteObj, wants);
144     if (helper == nullptr) {
145         HILOG_ERROR("creator return nullptr.");
146         return false;
147     }
148     setuid(UID_DEFAULT);
149     return true;
150 }
151 
GetDownloadUri()152 static tuple<shared_ptr<FileAccessHelper>, Uri> GetDownloadUri()
153 {
154     shared_ptr<FileAccessHelper> helper = GetFileAccessHelper();
155     if (helper == nullptr) {
156         HILOG_ERROR("GetFileAccessHelper return nullptr.");
157         return {nullptr, Uri("")};
158     }
159     vector<RootInfo> info;
160     int result = helper->GetRoots(info);
161     if (result != OHOS::FileAccessFwk::ERR_OK) {
162         HILOG_ERROR("GetRoots failed. ret : %{public}d", result);
163         return {helper, Uri("")};
164     }
165     Uri rootUri("");
166     if (info.size() > OHOS::FileAccessFwk::ERR_OK) {
167         rootUri = Uri(info[0].uri + "/file");
168     }
169     bool isExist = false;
170     Uri downloadUri(rootUri.ToString() + "/Download");
171     result = helper->Access(downloadUri, isExist);
172     if (result <= OHOS::FileAccessFwk::ERR_OK) {
173         HILOG_ERROR("Access failed. ret : %{public}d", result);
174         return {helper, Uri("")};
175     }
176     if (isExist) {
177         return {helper, downloadUri};
178     }
179     downloadUri = Uri("");
180     result = helper->Mkdir(rootUri, "Download", downloadUri);
181     if (result <= OHOS::FileAccessFwk::ERR_OK) {
182         HILOG_ERROR("Mkdir failed. ret : %{public}d", result);
183         return {helper, Uri("")};
184     }
185     return {helper, downloadUri};
186 }
187 
AccessFuzzTest(const uint8_t * data,size_t size)188 bool AccessFuzzTest(const uint8_t* data, size_t size)
189 {
190     shared_ptr<FileAccessHelper> helper;
191     Uri downloadUri;
192 
193     if (!CheckDataAndGetDownloadUri(data, size, helper, downloadUri)) {
194         return false;
195     }
196     Uri uri(downloadUri.ToString() + "/" + std::string(reinterpret_cast<const char*>(data), size));
197     bool isExist = false;
198     int result = helper->Access(uri, isExist);
199     if (isExist != true || result != OHOS::FileAccessFwk::ERR_OK) {
200         HILOG_ERROR("Access failed. ret : %{public}d", result);
201         return false;
202     }
203     return true;
204 }
205 
OpenFileFuzzTest(const uint8_t * data,size_t size)206 bool OpenFileFuzzTest(const uint8_t* data, size_t size)
207 {
208     shared_ptr<FileAccessHelper> helper;
209     Uri downloadUri;
210 
211     if (!CheckDataAndGetDownloadUri(data, size, helper, downloadUri)) {
212         return false;
213     }
214     Uri uri(downloadUri.ToString() + "/" + std::string(reinterpret_cast<const char*>(data), size));
215     int fd = -1;
216     int result = helper->OpenFile(uri, WRITE_READ, fd);
217     if (result != OHOS::FileAccessFwk::ERR_OK) {
218         HILOG_ERROR("OpenFile failed. ret : %{public}d", result);
219         return false;
220     }
221     close(fd);
222     return true;
223 }
224 
CreateFileFuzzTest(const uint8_t * data,size_t size)225 bool CreateFileFuzzTest(const uint8_t* data, size_t size)
226 {
227     shared_ptr<FileAccessHelper> helper;
228     Uri downloadUri;
229 
230     if (!CheckDataAndGetDownloadUri(data, size, helper, downloadUri)) {
231         return false;
232     }
233     Uri newFileUri("");
234     int result = helper->CreateFile(downloadUri, std::string(reinterpret_cast<const char*>(data), size), newFileUri);
235     if (result != OHOS::FileAccessFwk::ERR_OK) {
236         HILOG_ERROR("CreateFile failed. ret : %{public}d", result);
237         return false;
238     }
239     result = helper->Delete(newFileUri);
240     if (result != OHOS::FileAccessFwk::ERR_OK) {
241         HILOG_ERROR("Delete failed. ret : %{public}d", result);
242         return false;
243     }
244     return true;
245 }
246 
MkdirFuzzTest(const uint8_t * data,size_t size)247 bool MkdirFuzzTest(const uint8_t* data, size_t size)
248 {
249     shared_ptr<FileAccessHelper> helper;
250     Uri downloadUri;
251 
252     if (!CheckDataAndGetDownloadUri(data, size, helper, downloadUri)) {
253         return false;
254     }
255     Uri newDirUri("");
256     int result = helper->Mkdir(downloadUri, std::string(reinterpret_cast<const char*>(data), size), newDirUri);
257     if (result != OHOS::FileAccessFwk::ERR_OK) {
258         HILOG_ERROR("Mkdir failed. ret : %{public}d", result);
259         return false;
260     }
261     result = helper->Delete(newDirUri);
262     if (result != OHOS::FileAccessFwk::ERR_OK) {
263         HILOG_ERROR("Delete failed. ret : %{public}d", result);
264         return false;
265     }
266     return true;
267 }
268 
DeleteFuzzTest(const uint8_t * data,size_t size)269 bool DeleteFuzzTest(const uint8_t* data, size_t size)
270 {
271     shared_ptr<FileAccessHelper> helper;
272     Uri downloadUri;
273 
274     if (!CheckDataAndGetDownloadUri(data, size, helper, downloadUri)) {
275         return false;
276     }
277     Uri uri(downloadUri.ToString() + "/" + std::string(reinterpret_cast<const char*>(data), size));
278     int result = helper->Delete(uri);
279     if (result != OHOS::FileAccessFwk::ERR_OK) {
280         HILOG_ERROR("Delete failed. ret : %{public}d", result);
281         return false;
282     }
283     return true;
284 }
285 
MoveFuzzTest(const uint8_t * data,size_t size)286 bool MoveFuzzTest(const uint8_t* data, size_t size)
287 {
288     shared_ptr<FileAccessHelper> helper;
289     Uri downloadUri;
290 
291     if (!CheckDataAndGetDownloadUri(data, size, helper, downloadUri)) {
292         return false;
293     }
294     Uri newDirUriTest1("");
295     Uri newDirUriTest2("");
296     int result = helper->Mkdir(downloadUri, "test1", newDirUriTest1);
297     if (result != OHOS::FileAccessFwk::ERR_OK) {
298         HILOG_ERROR("Mkdir failed. ret : %{public}d", result);
299         return false;
300     }
301     result = helper->Mkdir(downloadUri, "test2", newDirUriTest2);
302     if (result != OHOS::FileAccessFwk::ERR_OK) {
303         HILOG_ERROR("Mkdir failed. ret : %{public}d", result);
304         return false;
305     }
306     Uri testUri("");
307     result = helper->CreateFile(newDirUriTest1, std::string(reinterpret_cast<const char*>(data), size), testUri);
308     if (result != OHOS::FileAccessFwk::ERR_OK) {
309         HILOG_ERROR("CreateFile failed. ret : %{public}d", result);
310         return false;
311     }
312     Uri testUri2("");
313     result = helper->Move(testUri, newDirUriTest2, testUri2);
314     if (result != OHOS::FileAccessFwk::ERR_OK) {
315         HILOG_ERROR("Move failed. ret : %{public}d", result);
316         return false;
317     }
318     result = helper->Delete(newDirUriTest1);
319     if (result != OHOS::FileAccessFwk::ERR_OK) {
320         HILOG_ERROR("Delete failed. ret : %{public}d", result);
321         return false;
322     }
323     result = helper->Delete(newDirUriTest2);
324     if (result != OHOS::FileAccessFwk::ERR_OK) {
325         HILOG_ERROR("Delete failed. ret : %{public}d", result);
326         return false;
327     }
328     return true;
329 }
330 
RenameFuzzTest(const uint8_t * data,size_t size)331 bool RenameFuzzTest(const uint8_t* data, size_t size)
332 {
333     shared_ptr<FileAccessHelper> helper;
334     Uri downloadUri;
335 
336     if (!CheckDataAndGetDownloadUri(data, size, helper, downloadUri)) {
337         return false;
338     }
339     Uri newDirUriTest("");
340     int result = helper->Mkdir(downloadUri, "test", newDirUriTest);
341     if (result != OHOS::FileAccessFwk::ERR_OK) {
342         HILOG_ERROR("Mkdir failed. ret : %{public}d", result);
343         return false;
344     }
345     Uri renameUri("");
346     result = helper->Rename(newDirUriTest, std::string(reinterpret_cast<const char*>(data), size), renameUri);
347     if (result != OHOS::FileAccessFwk::ERR_OK) {
348         HILOG_ERROR("Rename failed. ret : %{public}d", result);
349         return false;
350     }
351     result = helper->Delete(renameUri);
352     if (result != OHOS::FileAccessFwk::ERR_OK) {
353         HILOG_ERROR("Delete failed. ret : %{public}d", result);
354         return false;
355     }
356     return true;
357 }
358 
ListFileFuzzTest(const uint8_t * data,size_t size)359 bool ListFileFuzzTest(const uint8_t* data, size_t size)
360 {
361     shared_ptr<FileAccessHelper> helper;
362     Uri downloadUri;
363 
364     if (!CheckDataAndGetDownloadUri(data, size, helper, downloadUri)) {
365         return false;
366     }
367     FileInfo fileInfo;
368     fileInfo.uri = downloadUri.ToString() + "/" + std::string(reinterpret_cast<const char*>(data), size);
369     int64_t offset = 0;
370     int64_t maxCount = 1000;
371     std::vector<FileInfo> fileInfoVec;
372     FileFilter filter;
373     int result = helper->ListFile(fileInfo, offset, maxCount, filter, fileInfoVec);
374     if (result != OHOS::FileAccessFwk::ERR_OK) {
375         HILOG_ERROR("ListFile failed. ret : %{public}d", result);
376         return false;
377     }
378     return true;
379 }
380 
ScanFileFuzzTest(const uint8_t * data,size_t size)381 bool ScanFileFuzzTest(const uint8_t* data, size_t size)
382 {
383     shared_ptr<FileAccessHelper> helper;
384     Uri downloadUri;
385     if (!CheckDataAndGetDownloadUri(data, size, helper, downloadUri)) {
386         return false;
387     }
388     FileInfo fileInfo;
389     fileInfo.uri = downloadUri.ToString() + "/" + std::string(reinterpret_cast<const char*>(data), size);
390     int64_t offset = 0;
391     int64_t maxCount = 1000;
392     std::vector<FileInfo> fileInfoVec;
393     FileFilter filter;
394     int result = helper->ScanFile(fileInfo, offset, maxCount, filter, fileInfoVec);
395     if (result != OHOS::FileAccessFwk::ERR_OK) {
396         HILOG_ERROR("ScanFile failed. ret : %{public}d", result);
397         return false;
398     }
399     return true;
400 }
401 
402 }
403 
404 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)405 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
406 {
407     /* Run your code on data */
408     OHOS::CreatorFuzzTest(data, size);
409     OHOS::AccessFuzzTest(data, size);
410     OHOS::OpenFileFuzzTest(data, size);
411     OHOS::MkdirFuzzTest(data, size);
412     OHOS::CreateFileFuzzTest(data, size);
413     OHOS::DeleteFuzzTest(data, size);
414     OHOS::MoveFuzzTest(data, size);
415     OHOS::RenameFuzzTest(data, size);
416     OHOS::ListFileFuzzTest(data, size);
417     OHOS::ScanFileFuzzTest(data, size);
418     return 0;
419 }