1 /*
2 * Copyright (c) 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 "medialibrarypermission_fuzzer.h"
17
18 #include <cstdint>
19 #include <string>
20 #include <vector>
21 #include <fuzzer/FuzzedDataProvider.h>
22
23 #include "ability_context_impl.h"
24 #include "media_log.h"
25 #include "medialibrary_data_manager.h"
26 #include "medialibrary_errno.h"
27 #include "medialibrary_unistore_manager.h"
28 #include "medialibrary_kvstore_manager.h"
29 #include "media_app_uri_permission_column.h"
30 #include "media_composite_permission_check.h"
31 #include "media_read_permission_check.h"
32 #include "media_write_permission_check.h"
33
34 namespace OHOS {
35 namespace Media {
36 using namespace std;
37 static const int32_t NUM_BYTES = 1;
38 static const int32_t DEFAULT_CALLING_UID = 1;
39 static const int32_t DEFAULT_BUSINESS_CODE = 1;
40 static const int32_t USER_ID = -1;
41 static const int32_t MAX_URI_TYPE = 1;
42 static const int32_t MAX_PERMISSION_TYPE = 5;
43 std::shared_ptr<Media::MediaLibraryRdbStore> g_rdbStore;
44 FuzzedDataProvider *provider;
45
46 static const string SQL_INSERT_URIPERMISSION =
47 "INSERT INTO UriPermission (target_tokenId, file_id, uri_type, permission_type)";
48 static const string VALUES_END = ") ";
49
MockIsCalledBySelf()50 bool MockIsCalledBySelf()
51 {
52 return provider->ConsumeBool();
53 }
54
MockGetCallingUid()55 pid_t MockGetCallingUid()
56 {
57 uint8_t data = provider->ConsumeIntegralInRange<uint8_t>(0, CALLING_UID_LIST.size() - DEFAULT_CALLING_UID);
58 return CALLING_UID_LIST[data];
59 }
60
FuzzUriType()61 static int FuzzUriType()
62 {
63 vector<int> vecUriType;
64 vecUriType.assign(Media::AppUriPermissionColumn::URI_TYPES_ALL.begin(),
65 Media::AppUriPermissionColumn::URI_TYPES_ALL.end());
66 uint8_t data = provider->ConsumeIntegralInRange<uint8_t>(0, MAX_URI_TYPE);
67 return vecUriType[data];
68 }
69
FuzzMediaLibraryBusinessCode()70 static inline MediaLibraryBusinessCode FuzzMediaLibraryBusinessCode()
71 {
72 uint8_t data = provider->ConsumeIntegralInRange<uint8_t>(0, BUSINESS_CODE_LIST.size() - DEFAULT_BUSINESS_CODE);
73 return static_cast<MediaLibraryBusinessCode>(data);
74 }
75
FuzzPermissionType()76 static int FuzzPermissionType()
77 {
78 vector<int> vecPermissionType;
79 vecPermissionType.assign(AppUriPermissionColumn::PERMISSION_TYPES_ALL.begin(),
80 AppUriPermissionColumn::PERMISSION_TYPES_ALL.end());
81 uint8_t data = provider->ConsumeIntegralInRange<uint8_t>(0, MAX_PERMISSION_TYPE);
82 return vecPermissionType[data];
83 }
84
InsertUriPermissionRecord(const uint32_t & tokenId,const int32_t & fileId,const int32_t & uriType,const int32_t & permissionType)85 static void InsertUriPermissionRecord(
86 const uint32_t &tokenId, const int32_t &fileId, const int32_t &uriType, const int32_t &permissionType)
87 {
88 if (g_rdbStore == nullptr) {
89 MEDIA_ERR_LOG("g_rdbStore is null.");
90 return;
91 }
92 std::string insertSql = SQL_INSERT_URIPERMISSION + " VALUES (" + to_string(tokenId) + "," + to_string(fileId) +
93 "," + to_string(uriType) + "," + to_string(permissionType) + VALUES_END;
94 int32_t ret = g_rdbStore->ExecuteSql(insertSql);
95 if (ret != NativeRdb::E_OK) {
96 MEDIA_ERR_LOG("Execute sql %{public}s failed", insertSql.c_str());
97 return;
98 }
99 MEDIA_INFO_LOG("Execute sql %{public}s success", insertSql.c_str());
100 }
101
102 static std::unordered_map<uint32_t, std::vector<std::vector<PermissionType>>> testMap = {
103 {1, {{PRIVATE_PERM}}},
104 {2, {{CLOUDFILE_SYNC}}},
105 {3, {{READ_PERM}}},
106 {4, {{WRITE_PERM}}},
107 {5, {{SYSTEMAPI_PERM}, {}}},
108 {6, {{}, {SYSTEMAPI_PERM}}},
109 {7, {}},
110 {8, {{PRIVATE_PERM, CLOUDFILE_SYNC, READ_PERM, WRITE_PERM}}},
111 {9, {{CLOUD_READ}, {CLOUD_WRITE}}},
112 {0, {{READ_PERM}, {WRITE_PERM}}},
113 {static_cast<uint32_t>(MediaLibraryBusinessCode::PAH_OPEN), {{READ_PERM, WRITE_PERM}}}, // openfile api
114 };
115
GetTestPermissionPolicy(uint32_t code,std::vector<std::vector<PermissionType>> & permissionPolicy)116 static int32_t GetTestPermissionPolicy(uint32_t code, std::vector<std::vector<PermissionType>> &permissionPolicy)
117 {
118 auto it = testMap.find(code);
119 if (it != testMap.end()) {
120 permissionPolicy = it->second;
121 return E_SUCCESS;
122 }
123 return E_FAIL;
124 }
125
PreparePermissionParam(uint32_t code,int32_t userId,bool isDBBypass,std::unordered_map<std::string,std::string> & headerMap,PermissionHeaderReq & data)126 static int32_t PreparePermissionParam(uint32_t code, int32_t userId, bool isDBBypass,
127 std::unordered_map<std::string, std::string> &headerMap, PermissionHeaderReq &data)
128 {
129 std::vector<std::vector<PermissionType>> permissionPolicy;
130 if (GetTestPermissionPolicy(code, permissionPolicy) != E_SUCCESS) {
131 return E_FAIL;
132 }
133 data = PermissionHeaderReq::convertToPermissionHeaderReq(headerMap, userId, permissionPolicy, isDBBypass);
134 return E_SUCCESS;
135 }
136
ReadPermissionCheckTest()137 static void ReadPermissionCheckTest()
138 {
139 MEDIA_INFO_LOG("ReadPermissionCheckTest enter");
140 uint32_t businessCode = static_cast<uint32_t>(FuzzMediaLibraryBusinessCode());
141
142 uint32_t tokenId = PermissionUtils::GetTokenId();
143 int32_t permissionType = static_cast<int32_t>(FuzzPermissionType());
144 int32_t fileId = provider->ConsumeIntegral<int32_t>();
145 int32_t uriType = static_cast<int32_t>(FuzzUriType());
146 InsertUriPermissionRecord(tokenId, fileId, uriType, permissionType);
147 PermissionHeaderReq data;
148 std::unordered_map<std::string, std::string> headerMap;
149 if (provider->ConsumeBool()) {
150 headerMap = {
151 {PermissionHeaderReq::FILE_ID_KEY, to_string(fileId)},
152 {PermissionHeaderReq::URI_TYPE_KEY, to_string(uriType)},
153 {PermissionHeaderReq::OPEN_URI_KEY, provider->ConsumeBytesAsString(NUM_BYTES)},
154 {PermissionHeaderReq::OPEN_MODE_KEY, "rw"}
155 };
156 }
157 int32_t userId = provider->ConsumeBool() ? USER_ID : provider->ConsumeIntegral<int32_t>();
158 PreparePermissionParam(businessCode, userId, provider->ConsumeBool(), headerMap, data);
159
160 auto readCompositePermCheck = make_shared<ReadCompositePermCheck>();
161 CHECK_AND_RETURN_LOG(readCompositePermCheck != nullptr, "readCompositePermCheck is nullptr");
162 shared_ptr<PermissionCheck> check = make_shared<CompositePermissionCheck>();
163 readCompositePermCheck->AddCheck(check);
164 readCompositePermCheck->CheckPermission(businessCode, data);
165
166 auto readPrivilegePermCheck = make_shared<ReadPrivilegePermCheck>();
167 CHECK_AND_RETURN_LOG(readPrivilegePermCheck != nullptr, "readPrivilegePermCheck is nullptr");
168 readPrivilegePermCheck->CheckPermission(businessCode, data);
169
170 auto dbReadPermCheck = make_shared<DbReadPermCheck>();
171 CHECK_AND_RETURN_LOG(dbReadPermCheck != nullptr, "dbReadPermCheck is nullptr");
172 dbReadPermCheck->CheckPermission(businessCode, data);
173
174 auto grantReadPermCheck = make_shared<GrantReadPermCheck>();
175 CHECK_AND_RETURN_LOG(grantReadPermCheck != nullptr, "grantReadPermCheck is nullptr");
176 grantReadPermCheck->CheckPermission(businessCode, data);
177
178 auto mediaToolReadPermCheck = make_shared<MediaToolReadPermCheck>();
179 CHECK_AND_RETURN_LOG(mediaToolReadPermCheck != nullptr, "mediaToolReadPermCheck is nullptr");
180 mediaToolReadPermCheck->CheckPermission(businessCode, data);
181
182 auto deprecatedReadPermCheck = make_shared<DeprecatedReadPermCheck>();
183 CHECK_AND_RETURN_LOG(deprecatedReadPermCheck != nullptr, "deprecatedReadPermCheck is nullptr");
184 deprecatedReadPermCheck->CheckPermission(businessCode, data);
185 MEDIA_INFO_LOG("ReadPermissionCheckTest end");
186 }
187
WritePermissionCheckTest()188 static void WritePermissionCheckTest()
189 {
190 MEDIA_INFO_LOG("WritePermissionCheckTest enter");
191 uint32_t businessCode = static_cast<uint32_t>(FuzzMediaLibraryBusinessCode());
192
193 uint32_t tokenId = PermissionUtils::GetTokenId();
194 int32_t permissionType = static_cast<int32_t>(FuzzPermissionType());
195 int32_t fileId = provider->ConsumeIntegral<int32_t>();
196 int32_t uriType = static_cast<int32_t>(FuzzUriType());
197 InsertUriPermissionRecord(tokenId, fileId, uriType, permissionType);
198 PermissionHeaderReq data;
199 std::unordered_map<std::string, std::string> headerMap;
200 if (provider->ConsumeBool()) {
201 headerMap = {
202 {PermissionHeaderReq::FILE_ID_KEY, to_string(fileId)},
203 {PermissionHeaderReq::URI_TYPE_KEY, to_string(uriType)},
204 {PermissionHeaderReq::OPEN_URI_KEY, provider->ConsumeBytesAsString(NUM_BYTES)},
205 {PermissionHeaderReq::OPEN_MODE_KEY, "rw"}
206 };
207 }
208 int32_t userId = provider->ConsumeBool() ? USER_ID : provider->ConsumeIntegral<int32_t>();
209 PreparePermissionParam(businessCode, userId, provider->ConsumeBool(), headerMap, data);
210
211 auto writeCompositePermCheck = make_shared<WriteCompositePermCheck>();
212 CHECK_AND_RETURN_LOG(writeCompositePermCheck != nullptr, "writeCompositePermCheck is nullptr");
213 shared_ptr<PermissionCheck> check = make_shared<CompositePermissionCheck>();
214 writeCompositePermCheck->AddCheck(check);
215 writeCompositePermCheck->CheckPermission(businessCode, data);
216
217 auto writePrivilegePermCheck = make_shared<WritePrivilegePermCheck>();
218 CHECK_AND_RETURN_LOG(writePrivilegePermCheck != nullptr, "writePrivilegePermCheck is nullptr");
219 writePrivilegePermCheck->CheckPermission(businessCode, data);
220
221 auto dbWritePermCheck = make_shared<DbWritePermCheck>();
222 CHECK_AND_RETURN_LOG(dbWritePermCheck != nullptr, "dbWritePermCheck is nullptr");
223 dbWritePermCheck->CheckPermission(businessCode, data);
224
225 auto grantWritePermCheck = make_shared<GrantWritePermCheck>();
226 CHECK_AND_RETURN_LOG(grantWritePermCheck != nullptr, "grantWritePermCheck is nullptr");
227 grantWritePermCheck->CheckPermission(businessCode, data);
228
229 auto mediaToolWritePermCheck = make_shared<MediaToolWritePermCheck>();
230 CHECK_AND_RETURN_LOG(mediaToolWritePermCheck != nullptr, "mediaToolWritePermCheck is nullptr");
231 mediaToolWritePermCheck->CheckPermission(businessCode, data);
232
233 auto securityComponentPermCheck = make_shared<SecurityComponentPermCheck>();
234 CHECK_AND_RETURN_LOG(securityComponentPermCheck != nullptr, "securityComponentPermCheck is nullptr");
235 securityComponentPermCheck->CheckPermission(businessCode, data);
236
237 auto deprecatedWritePermCheck = make_shared<DeprecatedWritePermCheck>();
238 CHECK_AND_RETURN_LOG(deprecatedWritePermCheck != nullptr, "deprecatedWritePermCheck is nullptr");
239 deprecatedWritePermCheck->CheckPermission(businessCode, data);
240
241 auto shortTermWritePermCheck = make_shared<ShortTermWritePermCheck>();
242 CHECK_AND_RETURN_LOG(shortTermWritePermCheck != nullptr, "shortTermWritePermCheck is nullptr");
243 shortTermWritePermCheck->CheckPermission(businessCode, data);
244 MEDIA_INFO_LOG("WritePermissionCheckTest end");
245 }
246
SetTables()247 void SetTables()
248 {
249 vector<string> createTableSqlList = {
250 AppUriPermissionColumn::CREATE_APP_URI_PERMISSION_TABLE
251 };
252 for (auto &createTableSql : createTableSqlList) {
253 int32_t ret = g_rdbStore->ExecuteSql(createTableSql);
254 if (ret != NativeRdb::E_OK) {
255 MEDIA_ERR_LOG("Execute sql %{private}s failed", createTableSql.c_str());
256 return;
257 }
258 MEDIA_DEBUG_LOG("Execute sql %{private}s success", createTableSql.c_str());
259 }
260 }
261
Init()262 static void Init()
263 {
264 auto stageContext = std::make_shared<AbilityRuntime::ContextImpl>();
265 auto abilityContextImpl = std::make_shared<OHOS::AbilityRuntime::AbilityContextImpl>();
266 abilityContextImpl->SetStageContext(stageContext);
267 int32_t sceneCode = 0;
268 auto ret = Media::MediaLibraryDataManager::GetInstance()->InitMediaLibraryMgr(abilityContextImpl,
269 abilityContextImpl, sceneCode);
270 CHECK_AND_RETURN_LOG(ret == NativeRdb::E_OK, "InitMediaLibraryMgr failed, ret: %{public}d", ret);
271
272 auto rdbStore = Media::MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
273 if (rdbStore == nullptr) {
274 MEDIA_ERR_LOG("rdbStore is nullptr");
275 return;
276 }
277 g_rdbStore = rdbStore;
278 SetTables();
279 }
280
ClearKvStore()281 static inline void ClearKvStore()
282 {
283 Media::MediaLibraryKvStoreManager::GetInstance().CloseAllKvStore();
284 }
285 } //namespace Media
286 } // namespace OHOS
287
LLVMFuzzerInitialize(int * argc,char *** argv)288 extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv)
289 {
290 OHOS::Media::Init();
291 return 0;
292 }
293
294 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)295 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
296 {
297 FuzzedDataProvider provider(data, size);
298 OHOS::Media::provider = &provider;
299 if (data == nullptr) {
300 return 0;
301 }
302 OHOS::Media::isCalledBySelfPtr = OHOS::Media::MockIsCalledBySelf;
303 OHOS::Media::getCallingUidPtr = OHOS::Media::MockGetCallingUid;
304 OHOS::Media::ReadPermissionCheckTest();
305 OHOS::Media::WritePermissionCheckTest();
306 OHOS::Media::ClearKvStore();
307 return 0;
308 }