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_info.h"
19 #include "ability_manager_errors.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 || AppExecFwk::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,bool isScbCall)133 int32_t AbilityPermissionUtil::CheckMultiInstanceAndAppClone(Want &want, int32_t userId, int32_t appIndex,
134 sptr<IRemoteObject> callerToken, bool isScbCall)
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, appInfo.multiAppMode.maxCount, isScbCall);
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,int32_t maxCount,bool isScbCall)169 int32_t AbilityPermissionUtil::CheckMultiInstance(Want &want, sptr<IRemoteObject> callerToken,
170 int32_t maxCount, bool isScbCall)
171 {
172 auto appMgr = AppMgrUtil::GetAppMgr();
173 if (appMgr == nullptr) {
174 TAG_LOGE(AAFwkTag::ABILITYMGR, "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::ABILITYMGR, "Failed to get instance key");
182 return ERR_INVALID_VALUE;
183 }
184 auto instanceKey = want.GetStringParam(Want::APP_INSTANCE_KEY);
185 auto isCreating = want.GetBoolParam(Want::CREATE_APP_INSTANCE_KEY, false);
186 // in-app launch
187 if ((callerRecord != nullptr && callerRecord->GetAbilityInfo().bundleName == want.GetBundle()) ||
188 IsStartSelfUIAbility()) {
189 if (isCreating) {
190 if (!instanceKey.empty()) {
191 TAG_LOGE(AAFwkTag::ABILITYMGR, "Not allow to set instanceKey");
192 return ERR_APP_INSTANCE_KEY_NOT_SUPPORT;
193 }
194 if (static_cast<int32_t>(instanceKeyArray.size()) == maxCount) {
195 TAG_LOGE(AAFwkTag::ABILITYMGR, "reach upper limit");
196 return ERR_UPPER_LIMIT;
197 }
198 return ERR_OK;
199 }
200 if (callerRecord != nullptr) {
201 return UpdateInstanceKey(want, instanceKey, instanceKeyArray, callerRecord->GetInstanceKey());
202 }
203 TAG_LOGI(AAFwkTag::ABILITYMGR, "native c call set instanceKey");
204 return UpdateInstanceKey(want, instanceKey, instanceKeyArray, instanceKey);
205 }
206 // inter-app launch
207 if (isCreating) {
208 TAG_LOGE(AAFwkTag::ABILITYMGR, "not support to create a new instance");
209 return ERR_CREATE_NEW_INSTANCE_NOT_SUPPORT;
210 }
211 if (!isScbCall) {
212 std::string defaultInstanceKey = "app_instance_0";
213 return UpdateInstanceKey(want, instanceKey, instanceKeyArray, defaultInstanceKey);
214 }
215 return ERR_OK;
216 }
217
UpdateInstanceKey(Want & want,const std::string & originInstanceKey,const std::vector<std::string> & instanceKeyArray,const std::string & instanceKey)218 int32_t AbilityPermissionUtil::UpdateInstanceKey(Want &want, const std::string &originInstanceKey,
219 const std::vector<std::string> &instanceKeyArray, const std::string &instanceKey)
220 {
221 if (originInstanceKey.empty()) {
222 want.SetParam(Want::APP_INSTANCE_KEY, instanceKey);
223 return ERR_OK;
224 }
225 for (const auto& key : instanceKeyArray) {
226 if (key == originInstanceKey) {
227 return ERR_OK;
228 }
229 }
230 TAG_LOGE(AAFwkTag::ABILITYMGR, "invalid instanceKey");
231 return ERR_INVALID_APP_INSTANCE_KEY;
232 }
233
CheckMultiInstanceKeyForExtension(const AbilityRequest & abilityRequest)234 int32_t AbilityPermissionUtil::CheckMultiInstanceKeyForExtension(const AbilityRequest &abilityRequest)
235 {
236 if (abilityRequest.want.GetBoolParam(Want::CREATE_APP_INSTANCE_KEY, false)) {
237 TAG_LOGE(AAFwkTag::ABILITYMGR, "not support to create a new instance");
238 return ERR_CREATE_NEW_INSTANCE_NOT_SUPPORT;
239 }
240 auto instanceKey = MultiInstanceUtils::GetInstanceKey(abilityRequest.want);
241 if (instanceKey.empty()) {
242 return ERR_OK;
243 }
244 TAG_LOGI(AAFwkTag::ABILITYMGR, "instanceKey:%{public}s", instanceKey.c_str());
245 if (!AppUtils::GetInstance().IsSupportMultiInstance()) {
246 TAG_LOGE(AAFwkTag::ABILITYMGR, "not support multi-instance");
247 return ERR_CAPABILITY_NOT_SUPPORT;
248 }
249 if (!MultiInstanceUtils::IsMultiInstanceApp(abilityRequest.appInfo)) {
250 TAG_LOGE(AAFwkTag::ABILITYMGR, "not multi-instance app");
251 return ERR_MULTI_INSTANCE_NOT_SUPPORTED;
252 }
253 if (MultiInstanceUtils::IsDefaultInstanceKey(instanceKey)) {
254 return ERR_OK;
255 }
256 if (!MultiInstanceUtils::IsSupportedExtensionType(abilityRequest.abilityInfo.extensionAbilityType)) {
257 TAG_LOGE(AAFwkTag::ABILITYMGR, "invalid extension type");
258 return ERR_INVALID_EXTENSION_TYPE;
259 }
260 if (!MultiInstanceUtils::IsInstanceKeyExist(abilityRequest.want.GetBundle(), instanceKey)) {
261 TAG_LOGE(AAFwkTag::ABILITYMGR, "key not found");
262 return ERR_INVALID_APP_INSTANCE_KEY;
263 }
264 return ERR_OK;
265 }
266
CheckStartRecentAbility(const Want & want,AbilityRequest & request)267 int32_t AbilityPermissionUtil::CheckStartRecentAbility(const Want &want, AbilityRequest &request)
268 {
269 bool startRecent = want.GetBoolParam(Want::PARAM_RESV_START_RECENT, false);
270 if (!startRecent) {
271 return ERR_OK;
272 }
273 if (!AAFwk::PermissionVerification::GetInstance()->JudgeCallerIsAllowedToUseSystemAPI()) {
274 TAG_LOGE(AAFwkTag::ABILITYMGR, "caller no system-app, can not use system-api");
275 return ERR_NOT_SYSTEM_APP;
276 }
277 if (AAFwk::PermissionVerification::GetInstance()->VerifyStartRecentAbilityPermission()) {
278 TAG_LOGD(AAFwkTag::ABILITYMGR, "Set start recent.");
279 request.startRecent = true;
280 }
281 return ERR_OK;
282 }
283
284 #ifdef SUPPORT_SCREEN
CheckStartCallHasFloatingWindow(const sptr<IRemoteObject> & callerToken)285 int32_t AbilityPermissionUtil::CheckStartCallHasFloatingWindow(const sptr<IRemoteObject> &callerToken)
286 {
287 if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
288 auto sceneSessionManager = Rosen::SessionManagerLite::GetInstance().GetSceneSessionManagerLiteProxy();
289 CHECK_POINTER_AND_RETURN_LOG(sceneSessionManager, CHECK_PERMISSION_FAILED, "sceneSessionManager is nullptr");
290 bool hasFloatingWindow = false;
291 auto err = sceneSessionManager->HasFloatingWindowForeground(callerToken, hasFloatingWindow);
292 TAG_LOGI(AAFwkTag::ABILITYMGR,
293 "check floatingwindow permission. Ret: %{public}d, hasFloatingWindow: %{public}d",
294 static_cast<int32_t>(err), hasFloatingWindow);
295 if (err != Rosen::WMError::WM_OK) {
296 TAG_LOGE(AAFwkTag::ABILITYMGR,
297 "checking floatingwindow err: %{public}d", static_cast<int32_t>(err));
298 } else if (hasFloatingWindow) {
299 return ERR_OK;
300 }
301 }
302 return CHECK_PERMISSION_FAILED;
303 }
304 #endif // SUPPORT_SCREEN
305
AddStartSelfUIAbilityRecord(pid_t pid,int32_t tokenId)306 void AbilityPermissionUtil::AddStartSelfUIAbilityRecord(pid_t pid, int32_t tokenId)
307 {
308 std::lock_guard<ffrt::mutex> guard(startSelfUIAbilityRecordsMutex_);
309 auto iter = startSelfUIAbilityRecords_.begin();
310 for (; iter != startSelfUIAbilityRecords_.end(); iter++) {
311 if ((*iter)[INDEX_PID] == pid) {
312 break;
313 }
314 }
315 if (iter != startSelfUIAbilityRecords_.end()) {
316 TAG_LOGI(AAFwkTag::ABILITYMGR, "found");
317 (*iter)[INDEX_COUNT]++;
318 return;
319 }
320 TAG_LOGI(AAFwkTag::ABILITYMGR, "create new record");
321 startSelfUIAbilityRecords_.push_back({pid, tokenId, 1});
322 }
323
RemoveStartSelfUIAbilityRecord(pid_t pid)324 void AbilityPermissionUtil::RemoveStartSelfUIAbilityRecord(pid_t pid)
325 {
326 std::lock_guard<ffrt::mutex> guard(startSelfUIAbilityRecordsMutex_);
327 auto iter = startSelfUIAbilityRecords_.begin();
328 for (; iter != startSelfUIAbilityRecords_.end(); iter++) {
329 if ((*iter)[INDEX_PID] == pid) {
330 break;
331 }
332 }
333 if (iter == startSelfUIAbilityRecords_.end()) {
334 TAG_LOGI(AAFwkTag::ABILITYMGR, "not found");
335 return;
336 }
337 if ((*iter)[INDEX_COUNT] == 1) {
338 TAG_LOGI(AAFwkTag::ABILITYMGR, "last one");
339 startSelfUIAbilityRecords_.erase(iter);
340 return;
341 }
342 (*iter)[INDEX_COUNT]--;
343 }
344
GetTokenIdByPid(pid_t pid)345 int AbilityPermissionUtil::GetTokenIdByPid(pid_t pid)
346 {
347 std::lock_guard<ffrt::mutex> guard(startSelfUIAbilityRecordsMutex_);
348 auto iter = startSelfUIAbilityRecords_.begin();
349 for (; iter != startSelfUIAbilityRecords_.end(); iter++) {
350 if ((*iter)[INDEX_PID] == pid) {
351 return (*iter)[INDEX_TOKENID];
352 }
353 }
354 return -1;
355 }
356
IsStartSelfUIAbility()357 bool AbilityPermissionUtil::IsStartSelfUIAbility()
358 {
359 if (!AppUtils::GetInstance().IsStartOptionsWithAnimation()) {
360 return false;
361 }
362 auto callerPid = IPCSkeleton::GetCallingPid();
363 auto tokenId = GetTokenIdByPid(callerPid);
364 if (tokenId < 0) {
365 TAG_LOGE(AAFwkTag::ABILITYMGR, "invalid tokenId");
366 return false;
367 }
368 return PermissionVerification::GetInstance()->VerifyStartSelfUIAbility(tokenId);
369 }
370
CheckPrepareTerminateEnable(std::shared_ptr<AbilityRecord> abilityRecord)371 int32_t AbilityPermissionUtil::CheckPrepareTerminateEnable(std::shared_ptr<AbilityRecord> abilityRecord)
372 {
373 if (!AppUtils::GetInstance().IsPrepareTerminateEnabled()) {
374 TAG_LOGE(AAFwkTag::ABILITYMGR, "prepare terminate not supported");
375 return ERR_INVALID_VALUE; // ERR_NOT_SUPPORTED_PRODUCT_TYPE;
376 }
377 if (abilityRecord == nullptr || abilityRecord->IsTerminating()) {
378 TAG_LOGE(AAFwkTag::ABILITYMGR, "ability record not exist/ on terminating");
379 return ERR_INVALID_VALUE;
380 }
381 auto type = abilityRecord->GetAbilityInfo().type;
382 bool isStageBasedModel = abilityRecord->GetAbilityInfo().isStageBasedModel;
383 if (!isStageBasedModel || type != AppExecFwk::AbilityType::PAGE) {
384 TAG_LOGE(AAFwkTag::ABILITYMGR, "ability mode not support.");
385 return RESOLVE_CALL_ABILITY_TYPE_ERR;
386 }
387 auto tokenId = abilityRecord->GetApplicationInfo().accessTokenId;
388 if (!AAFwk::PermissionVerification::GetInstance()->VerifyPrepareTerminatePermission(tokenId)) {
389 TAG_LOGE(AAFwkTag::ABILITYMGR, "failed, please apply permission ohos.permission.PREPARE_APP_TERMINATE");
390 return ERR_INVALID_VALUE; // CHECK_PERMISSION_FAILED;
391 }
392 return ERR_OK;
393 }} // AAFwk
394 } // OHOS