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 #include "permission_utils.h"
16
17 #include <unordered_set>
18
19 #include "access_token.h"
20 #include "accesstoken_kit.h"
21 #include "el5_filekey_manager_kit.h"
22 #include "ipc_skeleton.h"
23 #include "iservice_registry.h"
24 #include "media_file_utils.h"
25 #include "media_log.h"
26 #include "medialibrary_db_const.h"
27 #include "medialibrary_errno.h"
28 #include "medialibrary_tracer.h"
29 #include "privacy_kit.h"
30 #include "system_ability_definition.h"
31 #include "tokenid_kit.h"
32
33 namespace OHOS {
34 namespace Media {
35 using namespace std;
36 using namespace OHOS::Security::AccessToken;
37 using namespace OHOS::AppExecFwk::Constants;
38
39 const int32_t CAPACITY = 50;
40 bool g_isDelayTask;
41 const int32_t HDC_SHELL_UID = 2000;
42 const int32_t BASE_USER_RANGE = 200000;
43
44 std::mutex PermissionUtils::uninstallMutex_;
45 std::list<std::pair<int32_t, BundleInfo>> PermissionUtils::bundleInfoList_ = {};
46 std::unordered_map<int32_t, std::list<std::pair<int32_t, BundleInfo>>::iterator> PermissionUtils::bundleInfoMap_ = {};
47 std::mutex addPhotoPermissionRecordLock_;
48 std::thread delayTask_;
49 std::vector<Security::AccessToken::AddPermParamInfo> infos_;
50
51 sptr<AppExecFwk::IBundleMgr> PermissionUtils::bundleMgr_ = nullptr;
52 mutex PermissionUtils::bundleMgrMutex_;
GetSysBundleManager()53 sptr<AppExecFwk::IBundleMgr> PermissionUtils::GetSysBundleManager()
54 {
55 if (bundleMgr_ != nullptr) {
56 return bundleMgr_;
57 }
58
59 lock_guard<mutex> lock(bundleMgrMutex_);
60 if (bundleMgr_ != nullptr) {
61 return bundleMgr_;
62 }
63
64 auto systemAbilityMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
65 if (systemAbilityMgr == nullptr) {
66 MEDIA_ERR_LOG("Failed to get SystemAbilityManager.");
67 return nullptr;
68 }
69
70 auto bundleObj = systemAbilityMgr->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
71 if (bundleObj == nullptr) {
72 MEDIA_ERR_LOG("Remote object is nullptr.");
73 return nullptr;
74 }
75
76 auto bundleMgr = iface_cast<AppExecFwk::IBundleMgr>(bundleObj);
77 if (bundleMgr == nullptr) {
78 MEDIA_ERR_LOG("Failed to iface_cast");
79 return nullptr;
80 }
81 bundleMgr_ = bundleMgr;
82
83 return bundleMgr_;
84 }
85
GetBundleNameFromCache(int uid,string & bundleName)86 void PermissionUtils::GetBundleNameFromCache(int uid, string &bundleName)
87 {
88 lock_guard<mutex> lock(uninstallMutex_);
89 auto iter = bundleInfoMap_.find(uid);
90 if (iter != bundleInfoMap_.end() && !iter->second->second.bundleName.empty()) {
91 bundleInfoList_.splice(bundleInfoList_.begin(), bundleInfoList_, iter->second);
92 bundleName = iter->second->second.bundleName;
93 return;
94 }
95 bundleMgr_ = GetSysBundleManager();
96 if (bundleMgr_ == nullptr) {
97 bundleName = "";
98 return;
99 }
100 auto result = bundleMgr_->GetBundleNameForUid(uid, bundleName);
101 if (!result) {
102 bundleName = "";
103 return;
104 }
105
106 UpdateBundleNameInCache(uid, bundleName);
107 }
108
GetPackageNameFromCache(int uid,const string & bundleName,string & packageName)109 void PermissionUtils::GetPackageNameFromCache(int uid, const string &bundleName, string &packageName)
110 {
111 lock_guard<mutex> lock(uninstallMutex_);
112 auto iter = bundleInfoMap_.find(uid);
113 if (iter != bundleInfoMap_.end() && !iter->second->second.packageName.empty()) {
114 bundleInfoList_.splice(bundleInfoList_.begin(), bundleInfoList_, iter->second);
115 packageName = iter->second->second.packageName;
116 return;
117 }
118
119 int32_t userId = uid / BASE_USER_RANGE;
120 MEDIA_DEBUG_LOG("uid:%{private}d, userId:%{private}d", uid, userId);
121
122 AAFwk::Want want;
123 auto bundleMgr = GetSysBundleManager();
124 if (bundleMgr == nullptr) {
125 MEDIA_ERR_LOG("Get BundleManager failed");
126 packageName = "";
127 return;
128 }
129 int ret = bundleMgr->GetLaunchWantForBundle(bundleName, want, userId);
130 if (ret != ERR_OK) {
131 MEDIA_ERR_LOG("Can not get bundleName by want, err=%{public}d, userId=%{private}d", ret, userId);
132 packageName = "";
133 return;
134 }
135 string abilityName = want.GetOperation().GetAbilityName();
136 packageName = bundleMgr->GetAbilityLabel(bundleName, abilityName);
137
138 UpdatePackageNameInCache(uid, packageName);
139 }
140
GetAppIdFromCache(int uid,const string & bundleName,string & appId)141 void PermissionUtils::GetAppIdFromCache(int uid, const string &bundleName, string &appId)
142 {
143 lock_guard<mutex> lock(uninstallMutex_);
144 auto iter = bundleInfoMap_.find(uid);
145 if (iter != bundleInfoMap_.end() && !iter->second->second.appId.empty()) {
146 bundleInfoList_.splice(bundleInfoList_.begin(), bundleInfoList_, iter->second);
147 appId = iter->second->second.appId;
148 return;
149 }
150 int32_t userId = uid / BASE_USER_RANGE;
151 MEDIA_DEBUG_LOG("uid:%{private}d, userId:%{private}d", uid, userId);
152
153 auto bundleMgr_ = GetSysBundleManager();
154 if (bundleMgr_ == nullptr) {
155 MEDIA_ERR_LOG("Get BundleManager failed");
156 return;
157 }
158
159 appId = bundleMgr_->GetAppIdByBundleName(bundleName, userId);
160
161 UpdateAppIdInCache(uid, appId);
162 }
163
UpdateLatestBundleInfo(int uid,const BundleInfo & bundleInfo)164 void PermissionUtils::UpdateLatestBundleInfo(int uid, const BundleInfo &bundleInfo)
165 {
166 auto iter = bundleInfoMap_.find(uid);
167 if (iter != bundleInfoMap_.end()) {
168 bundleInfoList_.erase(iter->second);
169 }
170 bundleInfoList_.push_front(make_pair(uid, bundleInfo));
171 bundleInfoMap_[uid] = bundleInfoList_.begin();
172 if (bundleInfoMap_.size() > CAPACITY) {
173 int32_t deleteKey = bundleInfoList_.back().first;
174 bundleInfoMap_.erase(deleteKey);
175 bundleInfoList_.pop_back();
176 }
177 }
178
UpdateBundleNameInCache(int uid,const string & bundleName)179 void PermissionUtils::UpdateBundleNameInCache(int uid, const string &bundleName)
180 {
181 auto iter = bundleInfoMap_.find(uid);
182 if (iter != bundleInfoMap_.end()) {
183 BundleInfo bundleInfo = bundleInfoMap_[uid]->second;
184 bundleInfo.bundleName = bundleName;
185 UpdateLatestBundleInfo(uid, bundleInfo);
186 return;
187 }
188 BundleInfo bundleInfo { bundleName, "", "" };
189 UpdateLatestBundleInfo(uid, bundleInfo);
190 }
191
UpdatePackageNameInCache(int uid,const string & packageName)192 void PermissionUtils::UpdatePackageNameInCache(int uid, const string &packageName)
193 {
194 auto iter = bundleInfoMap_.find(uid);
195 if (iter != bundleInfoMap_.end()) {
196 BundleInfo bundleInfo = bundleInfoMap_[uid]->second;
197 bundleInfo.packageName = packageName;
198 UpdateLatestBundleInfo(uid, bundleInfo);
199 return;
200 }
201 BundleInfo bundleInfo { "", packageName, "" };
202 UpdateLatestBundleInfo(uid, bundleInfo);
203 }
204
UpdateAppIdInCache(int uid,const string & appId)205 void PermissionUtils::UpdateAppIdInCache(int uid, const string &appId)
206 {
207 BundleInfo bundleInfo { "", "", appId };
208 auto iter = bundleInfoMap_.find(uid);
209 if (iter != bundleInfoMap_.end()) {
210 bundleInfo = bundleInfoMap_[uid]->second;
211 bundleInfo.appId = appId;
212 }
213 UpdateLatestBundleInfo(uid, bundleInfo);
214 }
215
ClearBundleInfoInCache()216 void PermissionUtils::ClearBundleInfoInCache()
217 {
218 lock_guard<mutex> lock(uninstallMutex_);
219 bundleInfoMap_.clear();
220 bundleInfoList_.clear();
221 MEDIA_INFO_LOG("clear all info from cache");
222 }
223
GetClientBundle(const int uid,string & bundleName)224 void PermissionUtils::GetClientBundle(const int uid, string &bundleName)
225 {
226 GetBundleNameFromCache(uid, bundleName);
227 }
228
GetPackageName(const int uid,std::string & packageName)229 void PermissionUtils::GetPackageName(const int uid, std::string &packageName)
230 {
231 packageName = "";
232 string bundleName;
233 GetClientBundle(uid, bundleName);
234 if (bundleName.empty()) {
235 MEDIA_ERR_LOG("Get bundle name failed");
236 return;
237 }
238
239 GetPackageNameFromCache(uid, bundleName, packageName);
240 }
241
ShouldAddPermissionRecord(const AccessTokenID & token)242 bool inline ShouldAddPermissionRecord(const AccessTokenID &token)
243 {
244 return (AccessTokenKit::GetTokenTypeFlag(token) == TOKEN_HAP);
245 }
246
AddPermissionRecord(const AccessTokenID & token,const string & perm,const bool permGranted)247 void AddPermissionRecord(const AccessTokenID &token, const string &perm, const bool permGranted)
248 {
249 if (!ShouldAddPermissionRecord(token)) {
250 return;
251 }
252
253 int res = PrivacyKit::AddPermissionUsedRecord(token, perm, !!permGranted, !permGranted, true);
254 if (res != 0) {
255 /* Failed to add permission used record, not fatal */
256 MEDIA_WARN_LOG("Failed to add permission used record: %{public}s, permGranted: %{public}d, err: %{public}d",
257 perm.c_str(), permGranted, res);
258 }
259 }
260
GetPermissionRecord()261 vector<AddPermParamInfo> GetPermissionRecord()
262 {
263 lock_guard<mutex> lock(addPhotoPermissionRecordLock_);
264 vector<AddPermParamInfo> result = infos_;
265 infos_.clear();
266 return result;
267 }
268
AddPermissionRecord()269 void AddPermissionRecord()
270 {
271 vector<AddPermParamInfo> infos = GetPermissionRecord();
272 for (const auto &info : infos) {
273 int32_t ret = PrivacyKit::AddPermissionUsedRecord(info, true);
274 if (ret != 0) {
275 /* Failed to add permission used record, not fatal */
276 MEDIA_WARN_LOG("Failed to add permission used record: %{public}s, permGranted: %{public}d, err: %{public}d",
277 info.permissionName.c_str(), info.successCount, ret);
278 }
279 MEDIA_DEBUG_LOG("Info: token = %{private}d, perm = %{private}s, permGranted = %{private}d, \
280 !permGranted = %{private}d, type = %{public}d", info.tokenId, info.permissionName.c_str(),
281 info.successCount, info.failCount, info.type);
282 }
283 infos.clear();
284 }
285
DelayAddPermissionRecord()286 void DelayAddPermissionRecord()
287 {
288 string name("DelayAddPermissionRecord");
289 pthread_setname_np(pthread_self(), name.c_str());
290 MEDIA_INFO_LOG("DelayTask start");
291 std::this_thread::sleep_for(std::chrono::seconds(1));
292 AddPermissionRecord();
293 g_isDelayTask = false;
294 MEDIA_INFO_LOG("DelayTask end");
295 }
296
DelayTaskInit()297 void DelayTaskInit()
298 {
299 if (!g_isDelayTask) {
300 MEDIA_INFO_LOG("DelayTaskInit");
301 delayTask_ = thread(DelayAddPermissionRecord);
302 delayTask_.detach();
303 g_isDelayTask = true;
304 }
305 }
306
CollectPermissionRecord(const AccessTokenID & token,const string & perm,const bool permGranted,const PermissionUsedType type)307 void CollectPermissionRecord(const AccessTokenID &token, const string &perm,
308 const bool permGranted, const PermissionUsedType type)
309 {
310 lock_guard<mutex> lock(addPhotoPermissionRecordLock_);
311 DelayTaskInit();
312
313 if (!ShouldAddPermissionRecord(token)) {
314 return;
315 }
316
317 AddPermParamInfo info = {token, perm, permGranted, !permGranted, type};
318 auto iter = find_if(infos_.begin(), infos_.end(), [&token, &perm, type](auto &info) {
319 return info.tokenId == token && info.permissionName == perm && info.type == type;
320 });
321 if (iter == infos_.end()) {
322 infos_.push_back(info);
323 } else if (permGranted) {
324 iter->successCount += 1;
325 } else if (!permGranted) {
326 iter->failCount += 1;
327 }
328 }
329
CollectPermissionInfo(const string & permission,const bool permGranted,const PermissionUsedType type)330 void PermissionUtils::CollectPermissionInfo(const string &permission,
331 const bool permGranted, const PermissionUsedType type)
332 {
333 AccessTokenID tokenCaller = IPCSkeleton::GetCallingTokenID();
334 CollectPermissionRecord(tokenCaller, permission, permGranted, type);
335 }
336
CheckPhotoCallerPermission(const string & permission)337 bool PermissionUtils::CheckPhotoCallerPermission(const string &permission)
338 {
339 PermissionUsedType type = PermissionUsedTypeValue::NORMAL_TYPE;
340 AccessTokenID tokenCaller = IPCSkeleton::GetCallingTokenID();
341 int res = AccessTokenKit::VerifyAccessToken(tokenCaller, permission);
342 if (res != PermissionState::PERMISSION_GRANTED) {
343 MEDIA_ERR_LOG("Have no media permission: %{public}s", permission.c_str());
344 CollectPermissionRecord(tokenCaller, permission, false, type);
345 return false;
346 }
347 CollectPermissionRecord(tokenCaller, permission, true, type);
348 return true;
349 }
350
CheckPhotoCallerPermission(const vector<string> & perms)351 bool PermissionUtils::CheckPhotoCallerPermission(const vector<string> &perms)
352 {
353 if (perms.empty()) {
354 return false;
355 }
356
357 for (const auto &perm : perms) {
358 if (!CheckPhotoCallerPermission(perm)) {
359 return false;
360 }
361 }
362 return true;
363 }
364
CheckCallerPermission(const string & permission)365 bool PermissionUtils::CheckCallerPermission(const string &permission)
366 {
367 MediaLibraryTracer tracer;
368 tracer.Start("CheckCallerPermission");
369
370 AccessTokenID tokenCaller = IPCSkeleton::GetCallingTokenID();
371 int res = AccessTokenKit::VerifyAccessToken(tokenCaller, permission);
372 if (res != PermissionState::PERMISSION_GRANTED) {
373 MEDIA_ERR_LOG("Have no media permission: %{public}s", permission.c_str());
374 AddPermissionRecord(tokenCaller, permission, false);
375 return false;
376 }
377 AddPermissionRecord(tokenCaller, permission, true);
378
379 return true;
380 }
381
382 /* Check whether caller has at least one of @perms */
CheckHasPermission(const vector<string> & perms)383 bool PermissionUtils::CheckHasPermission(const vector<string> &perms)
384 {
385 if (perms.empty()) {
386 return false;
387 }
388
389 for (const auto &perm : perms) {
390 if (CheckCallerPermission(perm)) {
391 return true;
392 }
393 }
394
395 return false;
396 }
397
398 /* Check whether caller has all the @perms */
CheckCallerPermission(const vector<string> & perms)399 bool PermissionUtils::CheckCallerPermission(const vector<string> &perms)
400 {
401 if (perms.empty()) {
402 return false;
403 }
404
405 for (const auto &perm : perms) {
406 if (!CheckCallerPermission(perm)) {
407 return false;
408 }
409 }
410 return true;
411 }
412
GetTokenId()413 uint32_t PermissionUtils::GetTokenId()
414 {
415 return IPCSkeleton::GetCallingTokenID();
416 }
417
IsSystemApp()418 bool PermissionUtils::IsSystemApp()
419 {
420 uint64_t tokenId = IPCSkeleton::GetCallingFullTokenID();
421 return TokenIdKit::IsSystemAppByFullTokenID(tokenId);
422 }
423
CheckIsSystemAppByUid()424 bool PermissionUtils::CheckIsSystemAppByUid()
425 {
426 int uid = IPCSkeleton::GetCallingUid();
427 bundleMgr_ = GetSysBundleManager();
428 if (bundleMgr_ == nullptr) {
429 MEDIA_ERR_LOG("Can not get bundleMgr");
430 return false;
431 }
432 return bundleMgr_->CheckIsSystemAppByUid(uid);
433 }
434
IsNativeSAApp()435 bool PermissionUtils::IsNativeSAApp()
436 {
437 uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
438 ATokenTypeEnum tokenType = AccessTokenKit::GetTokenTypeFlag(tokenId);
439 MEDIA_DEBUG_LOG("check if native sa token, tokenId:%{public}d, tokenType:%{public}d",
440 tokenId, tokenType);
441 if (tokenType == ATokenTypeEnum::TOKEN_NATIVE) {
442 return true;
443 }
444 return false;
445 }
446
IsRootShell()447 bool PermissionUtils::IsRootShell()
448 {
449 return IPCSkeleton::GetCallingUid() == 0;
450 }
451
IsHdcShell()452 bool PermissionUtils::IsHdcShell()
453 {
454 return IPCSkeleton::GetCallingUid() == HDC_SHELL_UID;
455 }
456
GetPackageNameByBundleName(const string & bundleName)457 string PermissionUtils::GetPackageNameByBundleName(const string &bundleName)
458 {
459 const static int32_t INVALID_UID = -1;
460
461 string packageName = "";
462 int uid = IPCSkeleton::GetCallingUid();
463 if (uid <= INVALID_UID) {
464 MEDIA_ERR_LOG("Get INVALID_UID UID %{public}d", uid);
465 return packageName;
466 }
467 GetPackageNameFromCache(uid, bundleName, packageName);
468
469 return packageName;
470 }
471
GetAppIdByBundleName(const string & bundleName)472 string PermissionUtils::GetAppIdByBundleName(const string &bundleName)
473 {
474 int uid = IPCSkeleton::GetCallingUid();
475 return GetAppIdByBundleName(bundleName, uid);
476 }
477
GetAppIdByBundleName(const string & bundleName,int32_t uid)478 string PermissionUtils::GetAppIdByBundleName(const string &bundleName, int32_t uid)
479 {
480 if (uid <= INVALID_UID) {
481 MEDIA_ERR_LOG("Get INVALID_UID UID %{public}d", uid);
482 return "";
483 }
484 string appId = "";
485 GetAppIdFromCache(uid, bundleName, appId);
486
487 return appId;
488 }
489
SetEPolicy()490 bool PermissionUtils::SetEPolicy()
491 {
492 MEDIA_INFO_LOG("SetEPolicy for directory");
493 int ret = Security::AccessToken::El5FilekeyManagerKit::SetFilePathPolicy();
494 if (ret != 0) {
495 MEDIA_ERR_LOG("SetEPolicy fail of %{public}d", ret);
496 return false;
497 }
498 return true;
499 }
500 } // namespace Media
501 } // namespace OHOS
502