• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-2025 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 "utils/ability_permission_util.h"
17 
18 #include "ability_connect_manager.h"
19 #include "ability_info.h"
20 #include "ability_util.h"
21 #include "app_utils.h"
22 #include "accesstoken_kit.h"
23 #include "global_constant.h"
24 #include "hitrace_meter.h"
25 #include "insight_intent_execute_param.h"
26 #include "ipc_skeleton.h"
27 #include "multi_instance_utils.h"
28 #include "permission_constants.h"
29 #include "permission_verification.h"
30 #include "start_ability_utils.h"
31 #include "utils/app_mgr_util.h"
32 #ifdef SUPPORT_SCREEN
33 #include "scene_board_judgement.h"
34 #include "session_manager_lite.h"
35 #endif // SUPPORT_SCREEN
36 
37 using OHOS::Security::AccessToken::AccessTokenKit;
38 
39 namespace OHOS {
40 namespace AAFwk {
41 namespace {
42 constexpr const char* IS_DELEGATOR_CALL = "isDelegatorCall";
43 constexpr const char* SETTINGS = "settings";
44 constexpr int32_t BASE_USER_RANGE = 200000;
45 constexpr int32_t INDEX_PID = 0;
46 constexpr int32_t INDEX_TOKENID = 1;
47 constexpr int32_t INDEX_COUNT = 2;
48 }
49 
StartSelfUIAbilityRecordGuard(pid_t pid,int32_t tokenId)50 StartSelfUIAbilityRecordGuard::StartSelfUIAbilityRecordGuard(pid_t pid, int32_t tokenId) : pid_(pid)
51 {
52     AbilityPermissionUtil::GetInstance().AddStartSelfUIAbilityRecord(pid, tokenId);
53 }
54 
~StartSelfUIAbilityRecordGuard()55 StartSelfUIAbilityRecordGuard::~StartSelfUIAbilityRecordGuard()
56 {
57     AbilityPermissionUtil::GetInstance().RemoveStartSelfUIAbilityRecord(pid_);
58 }
59 
GetInstance()60 AbilityPermissionUtil &AbilityPermissionUtil::GetInstance()
61 {
62     static AbilityPermissionUtil instance;
63     return instance;
64 }
65 
IsDelegatorCall(const AppExecFwk::RunningProcessInfo & processInfo,const AbilityRequest & abilityRequest) const66 inline bool AbilityPermissionUtil::IsDelegatorCall(const AppExecFwk::RunningProcessInfo &processInfo,
67     const AbilityRequest &abilityRequest) const
68 {
69     /*  To make sure the AbilityDelegator is not counterfeited
70      *   1. The caller-process must be test-process
71      *   2. The callerToken must be nullptr
72      */
73     if (processInfo.isTestProcess &&
74         !abilityRequest.callerToken && abilityRequest.want.GetBoolParam(IS_DELEGATOR_CALL, false)) {
75         return true;
76     }
77     return false;
78 }
79 
IsDominateScreen(const Want & want,bool isPendingWantCaller)80 bool AbilityPermissionUtil::IsDominateScreen(const Want &want, bool isPendingWantCaller)
81 {
82     if (!isPendingWantCaller &&
83         !PermissionVerification::GetInstance()->IsSACall() && !PermissionVerification::GetInstance()->IsShellCall()) {
84         auto callerPid = IPCSkeleton::GetCallingPid();
85         AppExecFwk::RunningProcessInfo processInfo;
86         DelayedSingleton<AppScheduler>::GetInstance()->GetRunningProcessInfoByPid(callerPid, processInfo);
87         bool isDelegatorCall = processInfo.isTestProcess && want.GetBoolParam(IS_DELEGATOR_CALL, false);
88         if (isDelegatorCall || InsightIntentExecuteParam::IsInsightIntentExecute(want)) {
89             TAG_LOGD(AAFwkTag::ABILITYMGR, "not dominate screen.");
90             return false;
91         }
92         // add temporarily
93         std::string bundleName = want.GetElement().GetBundleName();
94         std::string abilityName = want.GetElement().GetAbilityName();
95         bool withoutSettings = bundleName.find(SETTINGS) == std::string::npos &&
96             abilityName.find(SETTINGS) == std::string::npos;
97         if (withoutSettings && AppUtils::GetInstance().IsAllowStartAbilityWithoutCallerToken(bundleName, abilityName)) {
98             TAG_LOGD(AAFwkTag::ABILITYMGR, "not dominate screen, allow.");
99             return false;
100         } else if (AppUtils::GetInstance().IsAllowStartAbilityWithoutCallerToken(bundleName, abilityName)) {
101             auto bms = AbilityUtil::GetBundleManagerHelper();
102             CHECK_POINTER_RETURN_BOOL(bms);
103             int32_t callerUid = IPCSkeleton::GetCallingUid();
104             std::string callerBundleName;
105             if (IN_PROCESS_CALL(bms->GetNameForUid(callerUid, callerBundleName)) != ERR_OK) {
106                 TAG_LOGE(AAFwkTag::ABILITYMGR, "failed to get caller bundle name.");
107                 return false;
108             }
109             auto userId = callerUid / BASE_USER_RANGE;
110             AppExecFwk::BundleInfo info;
111             TAG_LOGD(AAFwkTag::ABILITYMGR, "callerBundleName: %{public}s, userId: %{public}d",
112                 callerBundleName.c_str(), userId);
113             if (!IN_PROCESS_CALL(
114                 bms->GetBundleInfo(callerBundleName, AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT, info, userId))) {
115                 TAG_LOGE(AAFwkTag::ABILITYMGR, "failed to get bundle info.");
116                 return false;
117             }
118             if (info.applicationInfo.needAppDetail) {
119                 TAG_LOGD(AAFwkTag::ABILITYMGR, "not dominate screen, app detail.");
120                 return false;
121             }
122         } else if (IsStartSelfUIAbility()) {
123             TAG_LOGI(AAFwkTag::ABILITYMGR, "caller from capi.");
124             return false;
125         }
126         TAG_LOGE(AAFwkTag::ABILITYMGR, "dominate screen.");
127         return true;
128     }
129     TAG_LOGD(AAFwkTag::ABILITYMGR, "not dominate screen.");
130     return false;
131 }
132 
CheckMultiInstanceAndAppClone(Want & want,int32_t userId,int32_t appIndex,sptr<IRemoteObject> callerToken)133 int32_t AbilityPermissionUtil::CheckMultiInstanceAndAppClone(Want &want, int32_t userId, int32_t appIndex,
134     sptr<IRemoteObject> callerToken)
135 {
136     auto instanceKey = want.GetStringParam(Want::APP_INSTANCE_KEY);
137     auto isCreating = want.GetBoolParam(Want::CREATE_APP_INSTANCE_KEY, false);
138     AppExecFwk::ApplicationInfo appInfo;
139     auto isSupportMultiInstance = AppUtils::GetInstance().IsSupportMultiInstance();
140     if (isSupportMultiInstance) {
141         if (!StartAbilityUtils::GetApplicationInfo(want.GetBundle(), userId, appInfo)) {
142             TAG_LOGI(AAFwkTag::ABILITYMGR, "implicit start");
143             return ERR_OK;
144         }
145         if (appInfo.multiAppMode.multiAppModeType == AppExecFwk::MultiAppModeType::UNSPECIFIED) {
146             if (!instanceKey.empty() || isCreating ||
147                 (appIndex != 0 && appIndex <= AbilityRuntime::GlobalConstant::MAX_APP_CLONE_INDEX)) {
148                 TAG_LOGE(AAFwkTag::ABILITYMGR, "Not support multi-instance or appClone");
149                 return ERR_MULTI_APP_NOT_SUPPORTED;
150             }
151         }
152         if (appInfo.multiAppMode.multiAppModeType == AppExecFwk::MultiAppModeType::MULTI_INSTANCE) {
153             if (appIndex != 0) {
154                 TAG_LOGE(AAFwkTag::ABILITYMGR, "Not support appClone");
155                 return ERR_NOT_SUPPORT_APP_CLONE;
156             }
157             return CheckMultiInstance(want, callerToken, isCreating, instanceKey, appInfo.multiAppMode.maxCount);
158         }
159     }
160     if (!isSupportMultiInstance || appInfo.multiAppMode.multiAppModeType == AppExecFwk::MultiAppModeType::APP_CLONE) {
161         if (!instanceKey.empty() || isCreating) {
162             TAG_LOGE(AAFwkTag::ABILITYMGR, "Not support multi-instance");
163             return ERR_MULTI_INSTANCE_NOT_SUPPORTED;
164         }
165     }
166     return ERR_OK;
167 }
168 
CheckMultiInstance(Want & want,sptr<IRemoteObject> callerToken,bool isCreating,const std::string & instanceKey,int32_t maxCount)169 int32_t AbilityPermissionUtil::CheckMultiInstance(Want &want, sptr<IRemoteObject> callerToken,
170     bool isCreating, const std::string &instanceKey, int32_t maxCount)
171 {
172     auto appMgr = AppMgrUtil::GetAppMgr();
173     if (appMgr == nullptr) {
174         TAG_LOGE(AAFwkTag::FREE_INSTALL, "null appMgr");
175         return ERR_INVALID_VALUE;
176     }
177     auto callerRecord = Token::GetAbilityRecordByToken(callerToken);
178     std::vector<std::string> instanceKeyArray;
179     auto result = IN_PROCESS_CALL(appMgr->GetAllRunningInstanceKeysByBundleName(want.GetBundle(), instanceKeyArray));
180     if (result != ERR_OK) {
181         TAG_LOGE(AAFwkTag::FREE_INSTALL, "Failed to get instance key");
182         return ERR_INVALID_VALUE;
183     }
184     // in-app launch
185     if ((callerRecord != nullptr && callerRecord->GetAbilityInfo().bundleName == want.GetBundle()) ||
186         IsStartSelfUIAbility()) {
187         if (isCreating) {
188             if (!instanceKey.empty()) {
189                 TAG_LOGE(AAFwkTag::ABILITYMGR, "Not allow to set instanceKey");
190                 return ERR_APP_INSTANCE_KEY_NOT_SUPPORT;
191             }
192             if (static_cast<int32_t>(instanceKeyArray.size()) == maxCount) {
193                 TAG_LOGE(AAFwkTag::ABILITYMGR, "reach upper limit");
194                 return ERR_UPPER_LIMIT;
195             }
196             return ERR_OK;
197         }
198         if (callerRecord != nullptr) {
199             return UpdateInstanceKey(want, instanceKey, instanceKeyArray, callerRecord->GetInstanceKey());
200         }
201         TAG_LOGI(AAFwkTag::ABILITYMGR, "native c call set instanceKey");
202         return UpdateInstanceKey(want, instanceKey, instanceKeyArray, instanceKey);
203     }
204     // inter-app launch
205     if (isCreating) {
206         TAG_LOGE(AAFwkTag::ABILITYMGR, "not support to create a new instance");
207         return ERR_CREATE_NEW_INSTANCE_NOT_SUPPORT;
208     }
209     std::string defaultInstanceKey = "app_instance_0";
210     return UpdateInstanceKey(want, instanceKey, instanceKeyArray, defaultInstanceKey);
211 }
212 
UpdateInstanceKey(Want & want,const std::string & originInstanceKey,const std::vector<std::string> & instanceKeyArray,const std::string & instanceKey)213 int32_t AbilityPermissionUtil::UpdateInstanceKey(Want &want, const std::string &originInstanceKey,
214     const std::vector<std::string> &instanceKeyArray, const std::string &instanceKey)
215 {
216     if (originInstanceKey.empty()) {
217         want.SetParam(Want::APP_INSTANCE_KEY, instanceKey);
218         return ERR_OK;
219     }
220     for (const auto& key : instanceKeyArray) {
221         if (key == originInstanceKey) {
222             return ERR_OK;
223         }
224     }
225     TAG_LOGE(AAFwkTag::ABILITYMGR, "invalid instanceKey");
226     return ERR_INVALID_APP_INSTANCE_KEY;
227 }
228 
CheckMultiInstanceKeyForExtension(const AbilityRequest & abilityRequest)229 int32_t AbilityPermissionUtil::CheckMultiInstanceKeyForExtension(const AbilityRequest &abilityRequest)
230 {
231     if (abilityRequest.want.GetBoolParam(Want::CREATE_APP_INSTANCE_KEY, false)) {
232         TAG_LOGE(AAFwkTag::ABILITYMGR, "not support to create a new instance");
233         return ERR_CREATE_NEW_INSTANCE_NOT_SUPPORT;
234     }
235     auto instanceKey = MultiInstanceUtils::GetInstanceKey(abilityRequest.want);
236     if (instanceKey.empty()) {
237         return ERR_OK;
238     }
239     TAG_LOGI(AAFwkTag::ABILITYMGR, "instanceKey:%{public}s", instanceKey.c_str());
240     if (!AppUtils::GetInstance().IsSupportMultiInstance()) {
241         TAG_LOGE(AAFwkTag::ABILITYMGR, "not support multi-instance");
242         return ERR_CAPABILITY_NOT_SUPPORT;
243     }
244     if (!MultiInstanceUtils::IsMultiInstanceApp(abilityRequest.appInfo)) {
245         TAG_LOGE(AAFwkTag::ABILITYMGR, "not multi-instance app");
246         return ERR_MULTI_INSTANCE_NOT_SUPPORTED;
247     }
248     if (MultiInstanceUtils::IsDefaultInstanceKey(instanceKey)) {
249         return ERR_OK;
250     }
251     if (!MultiInstanceUtils::IsSupportedExtensionType(abilityRequest.abilityInfo.extensionAbilityType)) {
252         TAG_LOGE(AAFwkTag::ABILITYMGR, "invalid extension type");
253         return ERR_INVALID_EXTENSION_TYPE;
254     }
255     if (!MultiInstanceUtils::IsInstanceKeyExist(abilityRequest.want.GetBundle(), instanceKey)) {
256         TAG_LOGE(AAFwkTag::ABILITYMGR, "key not found");
257         return ERR_INVALID_APP_INSTANCE_KEY;
258     }
259     return ERR_OK;
260 }
261 
CheckStartRecentAbility(const Want & want,AbilityRequest & request)262 int32_t AbilityPermissionUtil::CheckStartRecentAbility(const Want &want, AbilityRequest &request)
263 {
264     bool startRecent = want.GetBoolParam(Want::PARAM_RESV_START_RECENT, false);
265     if (!startRecent) {
266         return ERR_OK;
267     }
268     if (!AAFwk::PermissionVerification::GetInstance()->JudgeCallerIsAllowedToUseSystemAPI()) {
269         TAG_LOGE(AAFwkTag::ABILITYMGR, "caller no system-app, can not use system-api");
270         return ERR_NOT_SYSTEM_APP;
271     }
272     if (AAFwk::PermissionVerification::GetInstance()->VerifyStartRecentAbilityPermission()) {
273         TAG_LOGD(AAFwkTag::ABILITYMGR, "Set start recent.");
274         request.startRecent = true;
275     }
276     return ERR_OK;
277 }
278 
279 #ifdef SUPPORT_SCREEN
CheckStartCallHasFloatingWindow(const sptr<IRemoteObject> & callerToken)280 int32_t AbilityPermissionUtil::CheckStartCallHasFloatingWindow(const sptr<IRemoteObject> &callerToken)
281 {
282     if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
283         auto sceneSessionManager = Rosen::SessionManagerLite::GetInstance().GetSceneSessionManagerLiteProxy();
284         CHECK_POINTER_AND_RETURN_LOG(sceneSessionManager, CHECK_PERMISSION_FAILED, "sceneSessionManager is nullptr");
285         bool hasFloatingWindow = false;
286         auto err = sceneSessionManager->HasFloatingWindowForeground(callerToken, hasFloatingWindow);
287         TAG_LOGI(AAFwkTag::ABILITYMGR,
288             "check floatingwindow permission. Ret: %{public}d, hasFloatingWindow: %{public}d",
289             static_cast<int32_t>(err), hasFloatingWindow);
290         if (err != Rosen::WMError::WM_OK) {
291             TAG_LOGE(AAFwkTag::ABILITYMGR,
292                 "checking floatingwindow err: %{public}d", static_cast<int32_t>(err));
293         } else if (hasFloatingWindow) {
294             return ERR_OK;
295         }
296     }
297     return CHECK_PERMISSION_FAILED;
298 }
299 #endif // SUPPORT_SCREEN
300 
AddStartSelfUIAbilityRecord(pid_t pid,int32_t tokenId)301 void AbilityPermissionUtil::AddStartSelfUIAbilityRecord(pid_t pid, int32_t tokenId)
302 {
303     std::lock_guard<ffrt::mutex> guard(startSelfUIAbilityRecordsMutex_);
304     auto iter = startSelfUIAbilityRecords_.begin();
305     for (; iter != startSelfUIAbilityRecords_.end(); iter++) {
306         if ((*iter)[INDEX_PID] == pid) {
307             break;
308         }
309     }
310     if (iter != startSelfUIAbilityRecords_.end()) {
311         TAG_LOGI(AAFwkTag::ABILITYMGR, "found");
312         (*iter)[INDEX_COUNT]++;
313         return;
314     }
315     TAG_LOGI(AAFwkTag::ABILITYMGR, "create new record");
316     startSelfUIAbilityRecords_.push_back({pid, tokenId, 1});
317 }
318 
RemoveStartSelfUIAbilityRecord(pid_t pid)319 void AbilityPermissionUtil::RemoveStartSelfUIAbilityRecord(pid_t pid)
320 {
321     std::lock_guard<ffrt::mutex> guard(startSelfUIAbilityRecordsMutex_);
322     auto iter = startSelfUIAbilityRecords_.begin();
323     for (; iter != startSelfUIAbilityRecords_.end(); iter++) {
324         if ((*iter)[INDEX_PID] == pid) {
325             break;
326         }
327     }
328     if (iter == startSelfUIAbilityRecords_.end()) {
329         TAG_LOGI(AAFwkTag::ABILITYMGR, "not found");
330         return;
331     }
332     if ((*iter)[INDEX_COUNT] == 1) {
333         TAG_LOGI(AAFwkTag::ABILITYMGR, "last one");
334         startSelfUIAbilityRecords_.erase(iter);
335         return;
336     }
337     (*iter)[INDEX_COUNT]--;
338 }
339 
GetTokenIdByPid(pid_t pid)340 int AbilityPermissionUtil::GetTokenIdByPid(pid_t pid)
341 {
342     std::lock_guard<ffrt::mutex> guard(startSelfUIAbilityRecordsMutex_);
343     auto iter = startSelfUIAbilityRecords_.begin();
344     for (; iter != startSelfUIAbilityRecords_.end(); iter++) {
345         if ((*iter)[INDEX_PID] == pid) {
346             return (*iter)[INDEX_TOKENID];
347         }
348     }
349     return -1;
350 }
351 
IsStartSelfUIAbility()352 bool AbilityPermissionUtil::IsStartSelfUIAbility()
353 {
354     if (!AppUtils::GetInstance().IsStartOptionsWithAnimation()) {
355         return false;
356     }
357     auto callerPid = IPCSkeleton::GetCallingPid();
358     auto tokenId = GetTokenIdByPid(callerPid);
359     if (tokenId < 0) {
360         TAG_LOGE(AAFwkTag::ABILITYMGR, "invalid tokenId");
361         return false;
362     }
363     return PermissionVerification::GetInstance()->VerifyStartSelfUIAbility(tokenId);
364 }
365 
CheckPrepareTerminateEnable(const std::shared_ptr<AbilityRecord> & abilityRecord)366 int32_t AbilityPermissionUtil::CheckPrepareTerminateEnable(const std::shared_ptr<AbilityRecord> &abilityRecord)
367 {
368     if (!AppUtils::GetInstance().IsPrepareTerminateEnabled()) {
369         TAG_LOGE(AAFwkTag::ABILITYMGR, "prepare terminate not supported");
370         return ERR_INVALID_VALUE; // ERR_NOT_SUPPORTED_PRODUCT_TYPE;
371     }
372     if (abilityRecord == nullptr || abilityRecord->IsTerminating()) {
373         TAG_LOGE(AAFwkTag::ABILITYMGR, "ability record not exist/ on terminating");
374         return ERR_INVALID_VALUE;
375     }
376     auto type = abilityRecord->GetAbilityInfo().type;
377     bool isStageBasedModel = abilityRecord->GetAbilityInfo().isStageBasedModel;
378     if (!isStageBasedModel || type != AppExecFwk::AbilityType::PAGE) {
379         TAG_LOGE(AAFwkTag::ABILITYMGR, "ability mode not support.");
380         return RESOLVE_CALL_ABILITY_TYPE_ERR;
381     }
382     auto tokenId = abilityRecord->GetApplicationInfo().accessTokenId;
383     if (!AAFwk::PermissionVerification::GetInstance()->VerifyPrepareTerminatePermission(tokenId)) {
384         TAG_LOGE(AAFwkTag::ABILITYMGR, "failed, please apply permission ohos.permission.PREPARE_APP_TERMINATE");
385         return ERR_INVALID_VALUE; // CHECK_PERMISSION_FAILED;
386     }
387     return ERR_OK;
388 }} // AAFwk
389 } // OHOS