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 "bundle_clone_installer.h"
17
18 #include "ability_manager_helper.h"
19 #include "bundle_mgr_service.h"
20 #include "bundle_permission_mgr.h"
21 #include "bundle_resource_helper.h"
22 #include "bundle_service_constants.h"
23 #include "datetime_ex.h"
24 #include "hitrace_meter.h"
25 #include "installd_client.h"
26 #include "inner_bundle_clone_common.h"
27 #include "parameters.h"
28 #include "perf_profile.h"
29 #include "scope_guard.h"
30 #include "ipc_skeleton.h"
31
32 namespace OHOS {
33 namespace AppExecFwk {
34 using namespace OHOS::Security;
35
36 std::mutex gCloneInstallerMutex;
37
BundleCloneInstaller()38 BundleCloneInstaller::BundleCloneInstaller()
39 {
40 APP_LOGD("bundle clone installer instance is created");
41 }
42
~BundleCloneInstaller()43 BundleCloneInstaller::~BundleCloneInstaller()
44 {
45 APP_LOGD("bundle clone installer instance is destroyed");
46 }
47
InstallCloneApp(const std::string & bundleName,const int32_t userId,int32_t & appIndex)48 ErrCode BundleCloneInstaller::InstallCloneApp(const std::string &bundleName,
49 const int32_t userId, int32_t &appIndex)
50 {
51 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
52 APP_LOGD("InstallCloneApp %{public}s begin", bundleName.c_str());
53
54 PerfProfile::GetInstance().SetBundleInstallStartTime(GetTickCount());
55
56 ErrCode result = ProcessCloneBundleInstall(bundleName, userId, appIndex);
57 NotifyBundleEvents installRes = {
58 .bundleName = bundleName,
59 .resultCode = result,
60 .type = NotifyType::INSTALL,
61 .uid = uid_,
62 .accessTokenId = accessTokenId_,
63 .appIndex = appIndex,
64 .appId = appId_,
65 .appIdentifier = appIdentifier_,
66 };
67 std::shared_ptr<BundleCommonEventMgr> commonEventMgr = std::make_shared<BundleCommonEventMgr>();
68 std::shared_ptr<BundleDataMgr> dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
69 commonEventMgr->NotifyBundleStatus(installRes, dataMgr);
70
71 SendBundleSystemEvent(bundleName, BundleEventType::INSTALL, userId, appIndex,
72 false, false, InstallScene::NORMAL, result);
73
74 ResetInstallProperties();
75 PerfProfile::GetInstance().SetBundleInstallEndTime(GetTickCount());
76 return result;
77 }
78
UninstallCloneApp(const std::string & bundleName,const int32_t userId,const int32_t appIndex)79 ErrCode BundleCloneInstaller::UninstallCloneApp(
80 const std::string &bundleName, const int32_t userId, const int32_t appIndex)
81 {
82 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
83 APP_LOGD("UninstallCloneApp %{public}s _ %{public}d begin", bundleName.c_str(), appIndex);
84
85 PerfProfile::GetInstance().SetBundleUninstallStartTime(GetTickCount());
86
87 ErrCode result = ProcessCloneBundleUninstall(bundleName, userId, appIndex);
88 NotifyBundleEvents installRes = {
89 .bundleName = bundleName,
90 .resultCode = result,
91 .type = NotifyType::UNINSTALL_BUNDLE,
92 .uid = uid_,
93 .accessTokenId = accessTokenId_,
94 .appIndex = appIndex,
95 .appId = appId_,
96 .appIdentifier = appIdentifier_,
97 };
98 std::shared_ptr<BundleCommonEventMgr> commonEventMgr = std::make_shared<BundleCommonEventMgr>();
99 std::shared_ptr<BundleDataMgr> dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
100 commonEventMgr->NotifyBundleStatus(installRes, dataMgr);
101
102 SendBundleSystemEvent(bundleName, BundleEventType::UNINSTALL, userId, appIndex,
103 false, false, InstallScene::NORMAL, result);
104
105 ResetInstallProperties();
106
107 PerfProfile::GetInstance().SetBundleUninstallEndTime(GetTickCount());
108 return result;
109 }
110
UninstallAllCloneApps(const std::string & bundleName,int32_t userId)111 ErrCode BundleCloneInstaller::UninstallAllCloneApps(const std::string &bundleName, int32_t userId)
112 {
113 // All clone will be uninstalled when the original application is updated or uninstalled
114 APP_LOGI("begin");
115 if (bundleName.empty()) {
116 APP_LOGE("UninstallAllCloneApps failed due to empty bundle name");
117 return ERR_APPEXECFWK_CLONE_UNINSTALL_INVALID_BUNDLE_NAME;
118 }
119 if (GetDataMgr() != ERR_OK) {
120 APP_LOGE("Get dataMgr shared_ptr nullptr");
121 return ERR_APPEXECFWK_CLONE_UNINSTALL_INTERNAL_ERROR;
122 }
123 if (!dataMgr_->HasUserId(userId)) {
124 APP_LOGE("install clone app user %{public}d not exist", userId);
125 return ERR_APPEXECFWK_CLONE_UNINSTALL_USER_NOT_EXIST;
126 }
127 ScopeGuard bundleEnabledGuard([&] { dataMgr_->EnableBundle(bundleName); });
128 InnerBundleInfo info;
129 bool isExist = dataMgr_->GetInnerBundleInfo(bundleName, info);
130 if (!isExist) {
131 APP_LOGE("the bundle is not installed");
132 return ERR_APPEXECFWK_CLONE_UNINSTALL_APP_NOT_EXISTED;
133 }
134 InnerBundleUserInfo userInfo;
135 if (!info.GetInnerBundleUserInfo(userId, userInfo)) {
136 APP_LOGE("the origin application is not installed at current user");
137 return ERR_APPEXECFWK_CLONE_UNINSTALL_NOT_INSTALLED_AT_SPECIFIED_USERID;
138 }
139 ErrCode result = ERR_OK;
140 for (auto it = userInfo.cloneInfos.begin(); it != userInfo.cloneInfos.end(); it++) {
141 if (UninstallCloneApp(bundleName, userId, std::stoi(it->first)) != ERR_OK) {
142 APP_LOGE("UninstallCloneApp failed, appIndex %{public}s", it->first.c_str());
143 result = ERR_APPEXECFWK_CLONE_UNINSTALL_INTERNAL_ERROR;
144 }
145 }
146 APP_LOGI("end");
147 return result;
148 }
149
ProcessCloneBundleInstall(const std::string & bundleName,const int32_t userId,int32_t & appIndex)150 ErrCode BundleCloneInstaller::ProcessCloneBundleInstall(const std::string &bundleName,
151 const int32_t userId, int32_t &appIndex)
152 {
153 if (bundleName.empty()) {
154 APP_LOGE("the bundle name is empty");
155 return ERR_APPEXECFWK_CLONE_INSTALL_PARAM_ERROR;
156 }
157
158 std::shared_ptr<BundleDataMgr> dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
159
160 std::lock_guard<std::mutex> cloneGuard(gCloneInstallerMutex);
161 // 1. check whether original application installed or not
162 InnerBundleInfo info;
163 bool isExist = dataMgr->FetchInnerBundleInfo(bundleName, info);
164 if (!isExist) {
165 APP_LOGE("the bundle is not installed");
166 return ERR_APPEXECFWK_CLONE_INSTALL_APP_NOT_EXISTED;
167 }
168
169 // 2. obtain userId
170 if (userId < Constants::DEFAULT_USERID) {
171 APP_LOGE("userId(%{public}d) invalid", userId);
172 return ERR_APPEXECFWK_CLONE_INSTALL_USER_NOT_EXIST;
173 }
174 if (!dataMgr->HasUserId(userId)) {
175 APP_LOGE("install clone app user %{public}d not exist", userId);
176 return ERR_APPEXECFWK_CLONE_INSTALL_USER_NOT_EXIST;
177 }
178
179 // 3. check whether original application installed at current userId or not
180 InnerBundleUserInfo userInfo;
181 if (!info.GetInnerBundleUserInfo(userId, userInfo)) {
182 APP_LOGE("the origin application is not installed at current user");
183 return ERR_APPEXECFWK_CLONE_INSTALL_NOT_INSTALLED_AT_SPECIFIED_USERID;
184 }
185
186 ErrCode ackRes = info.VerifyAndAckCloneAppIndex(userId, appIndex);
187 if (ackRes != ERR_OK) {
188 APP_LOGE("installCloneApp fail for verifyAndAck res %{public}d", ackRes);
189 return ackRes;
190 }
191
192 // uid
193 std::string cloneBundleName = BundleCloneCommonHelper::GetCloneBundleIdKey(bundleName, appIndex);
194 InnerBundleUserInfo tmpUserInfo;
195 tmpUserInfo.bundleName = cloneBundleName;
196 tmpUserInfo.bundleUserInfo.userId = userId;
197 dataMgr->GenerateUidAndGid(tmpUserInfo);
198 int32_t uid = tmpUserInfo.uid;
199
200 // 4. generate the accesstoken id and inherit original permissions
201 info.SetAppIndex(appIndex);
202 Security::AccessToken::AccessTokenIDEx newTokenIdEx;
203 if (BundlePermissionMgr::InitHapToken(info, userId, 0, newTokenIdEx) != ERR_OK) {
204 APP_LOGE("bundleName:%{public}s InitHapToken failed", bundleName.c_str());
205 return ERR_APPEXECFWK_INSTALL_GRANT_REQUEST_PERMISSIONS_FAILED;
206 }
207 ScopeGuard applyAccessTokenGuard([&] {
208 BundlePermissionMgr::DeleteAccessTokenId(newTokenIdEx.tokenIdExStruct.tokenID);
209 });
210
211 InnerBundleCloneInfo attr = {
212 .userId = userId,
213 .appIndex = appIndex,
214 .uid = uid,
215 .gids = tmpUserInfo.gids,
216 .accessTokenId = newTokenIdEx.tokenIdExStruct.tokenID,
217 .accessTokenIdEx = newTokenIdEx.tokenIDEx,
218 };
219 uid_ = uid;
220 accessTokenId_ = newTokenIdEx.tokenIdExStruct.tokenID;
221 versionCode_ = info.GetVersionCode();
222 appId_ = info.GetAppId();
223 appIdentifier_ = info.GetAppIdentifier();
224
225 ErrCode result = CreateCloneDataDir(info, userId, uid, appIndex);
226 if (result != ERR_OK) {
227 APP_LOGE("InstallCloneApp create clone dir failed");
228 return result;
229 }
230 ScopeGuard createCloneDataDirGuard([&] { RemoveCloneDataDir(bundleName, userId, appIndex); });
231
232 ScopeGuard addCloneBundleGuard([&] { dataMgr->RemoveCloneBundle(bundleName, userId, appIndex); });
233 ErrCode addRes = dataMgr->AddCloneBundle(bundleName, attr);
234 if (addRes != ERR_OK) {
235 APP_LOGE("dataMgr add clone bundle fail, bundleName: %{public}s, userId: %{public}d, appIndex: %{public}d",
236 bundleName.c_str(), userId, appIndex);
237 return addRes;
238 }
239
240 // process icon and label
241 {
242 auto appIndexes = info.GetCloneBundleAppIndexes();
243 // appIndex not exist, need parse
244 if (appIndexes.find(appIndex) == appIndexes.end()) {
245 BundleResourceHelper::AddCloneBundleResourceInfo(bundleName, appIndex, userId);
246 }
247 }
248
249 // total to commit, avoid rollback
250 applyAccessTokenGuard.Dismiss();
251 createCloneDataDirGuard.Dismiss();
252 addCloneBundleGuard.Dismiss();
253 APP_LOGI("InstallCloneApp %{public}s appIndex:%{public}d succesfully", bundleName.c_str(), appIndex);
254 return ERR_OK;
255 }
256
ProcessCloneBundleUninstall(const std::string & bundleName,int32_t userId,int32_t appIndex)257 ErrCode BundleCloneInstaller::ProcessCloneBundleUninstall(const std::string &bundleName,
258 int32_t userId, int32_t appIndex)
259 {
260 if (bundleName.empty()) {
261 APP_LOGE("UninstallCloneApp failed due to empty bundle name");
262 return ERR_APPEXECFWK_CLONE_UNINSTALL_INVALID_BUNDLE_NAME;
263 }
264 if (appIndex < ServiceConstants::CLONE_APP_INDEX_MIN || appIndex > ServiceConstants::CLONE_APP_INDEX_MAX) {
265 APP_LOGE("Add Clone Bundle Fail, appIndex: %{public}d not in valid range", appIndex);
266 return ERR_APPEXECFWK_CLONE_UNINSTALL_INVALID_APP_INDEX;
267 }
268 if (GetDataMgr() != ERR_OK) {
269 APP_LOGE("Get dataMgr shared_ptr nullptr");
270 return ERR_APPEXECFWK_CLONE_UNINSTALL_INTERNAL_ERROR;
271 }
272 if (!dataMgr_->HasUserId(userId)) {
273 APP_LOGE("install clone app user %{public}d not exist", userId);
274 return ERR_APPEXECFWK_CLONE_UNINSTALL_USER_NOT_EXIST;
275 }
276 InnerBundleInfo info;
277 bool isExist = dataMgr_->FetchInnerBundleInfo(bundleName, info);
278 if (!isExist) {
279 APP_LOGE("the bundle is not installed");
280 return ERR_APPEXECFWK_CLONE_UNINSTALL_APP_NOT_EXISTED;
281 }
282 InnerBundleUserInfo userInfo;
283 if (!info.GetInnerBundleUserInfo(userId, userInfo)) {
284 APP_LOGE("the origin application is not installed at current user");
285 return ERR_APPEXECFWK_CLONE_UNINSTALL_NOT_INSTALLED_AT_SPECIFIED_USERID;
286 }
287 auto it = userInfo.cloneInfos.find(std::to_string(appIndex));
288 if (it == userInfo.cloneInfos.end()) {
289 APP_LOGE("the clone app is not installed");
290 return ERR_APPEXECFWK_CLONE_UNINSTALL_APP_NOT_CLONED;
291 }
292 uid_ = it->second.uid;
293 accessTokenId_ = it->second.accessTokenId;
294 versionCode_ = info.GetVersionCode();
295 appId_ = info.GetAppId();
296 appIdentifier_ = info.GetAppIdentifier();
297 if (BundlePermissionMgr::DeleteAccessTokenId(accessTokenId_) !=
298 AccessToken::AccessTokenKitRet::RET_SUCCESS) {
299 APP_LOGE("delete AT failed clone");
300 }
301 if (!AbilityManagerHelper::UninstallApplicationProcesses(bundleName, uid_, false, appIndex)) {
302 APP_LOGE("fail to kill running application");
303 }
304 if (dataMgr_->RemoveCloneBundle(bundleName, userId, appIndex)) {
305 APP_LOGE("RemoveCloneBundle failed");
306 return ERR_APPEXECFWK_CLONE_UNINSTALL_INTERNAL_ERROR;
307 }
308 if (RemoveCloneDataDir(bundleName, userId, appIndex) != ERR_OK) {
309 APP_LOGW("RemoveCloneDataDir failed");
310 }
311 // process icon and label
312 {
313 InnerBundleInfo info;
314 if (dataMgr_->FetchInnerBundleInfo(bundleName, info)) {
315 auto appIndexes = info.GetCloneBundleAppIndexes();
316 if (appIndexes.find(appIndex) == appIndexes.end()) {
317 BundleResourceHelper::DeleteCloneBundleResourceInfo(bundleName, appIndex, userId);
318 }
319 }
320 }
321 #ifdef BUNDLE_FRAMEWORK_APP_CONTROL
322 std::shared_ptr<AppControlManager> appControlMgr = DelayedSingleton<AppControlManager>::GetInstance();
323 if (appControlMgr != nullptr) {
324 APP_LOGD("Delete disposed rule when bundleName :%{public}s uninstall", bundleName.c_str());
325 appControlMgr->DeleteAllDisposedRuleByBundle(info, appIndex, userId);
326 }
327 #endif
328 UninstallDebugAppSandbox(bundleName, uid_, appIndex, info);
329 APP_LOGI("UninstallCloneApp %{public}s _ %{public}d succesfully", bundleName.c_str(), appIndex);
330 return ERR_OK;
331 }
332
UninstallDebugAppSandbox(const std::string & bundleName,const int32_t uid,int32_t appIndex,const InnerBundleInfo & innerBundleInfo)333 void BundleCloneInstaller::UninstallDebugAppSandbox(const std::string &bundleName, const int32_t uid,
334 int32_t appIndex, const InnerBundleInfo& innerBundleInfo)
335 {
336 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
337 APP_LOGD("call UninstallDebugAppSandbox start");
338 bool isDebugApp = innerBundleInfo.GetBaseApplicationInfo().appProvisionType == Constants::APP_PROVISION_TYPE_DEBUG;
339 bool isDeveloperMode = OHOS::system::GetBoolParameter(ServiceConstants::DEVELOPERMODE_STATE, false);
340 if (isDeveloperMode && isDebugApp) {
341 AppSpawnRemoveSandboxDirMsg removeSandboxDirMsg;
342 removeSandboxDirMsg.code = MSG_UNINSTALL_DEBUG_HAP;
343 removeSandboxDirMsg.bundleName = bundleName;
344 removeSandboxDirMsg.bundleIndex = appIndex;
345 removeSandboxDirMsg.uid = uid;
346 removeSandboxDirMsg.flags = APP_FLAGS_CLONE_ENABLE;
347 if (BundleAppSpawnClient::GetInstance().RemoveSandboxDir(removeSandboxDirMsg) != 0) {
348 APP_LOGE("RemoveSandboxDir failed");
349 }
350 }
351 APP_LOGD("call UninstallDebugAppSandbox end");
352 }
353
CreateCloneDataDir(InnerBundleInfo & info,const int32_t userId,const int32_t & uid,const int32_t & appIndex) const354 ErrCode BundleCloneInstaller::CreateCloneDataDir(InnerBundleInfo &info,
355 const int32_t userId, const int32_t &uid, const int32_t &appIndex) const
356 {
357 APP_LOGD("CreateCloneDataDir %{public}s _ %{public}d begin", info.GetBundleName().c_str(), appIndex);
358 std::string innerDataDir = BundleCloneCommonHelper::GetCloneDataDir(info.GetBundleName(), appIndex);
359 CreateDirParam createDirParam;
360 createDirParam.bundleName = innerDataDir;
361 createDirParam.userId = userId;
362 createDirParam.uid = uid;
363 createDirParam.gid = uid;
364 createDirParam.apl = info.GetAppPrivilegeLevel();
365 createDirParam.isPreInstallApp = info.IsPreInstallApp();
366 createDirParam.debug = info.GetBaseApplicationInfo().appProvisionType == Constants::APP_PROVISION_TYPE_DEBUG;
367 auto result = InstalldClient::GetInstance()->CreateBundleDataDir(createDirParam);
368 if (result != ERR_OK) {
369 APP_LOGE("fail to create sandbox data dir, error is %{public}d", result);
370 return result;
371 }
372 APP_LOGI("CreateCloneDataDir successfully");
373 return result;
374 }
375
RemoveCloneDataDir(const std::string bundleName,int32_t userId,int32_t appIndex)376 ErrCode BundleCloneInstaller::RemoveCloneDataDir(const std::string bundleName, int32_t userId, int32_t appIndex)
377 {
378 std::string key = BundleCloneCommonHelper::GetCloneDataDir(bundleName, appIndex);
379 if (InstalldClient::GetInstance()->RemoveBundleDataDir(key, userId) != ERR_OK) {
380 APP_LOGW("CloneApp cannot remove the data dir");
381 return ERR_APPEXECFWK_CLONE_INSTALL_INTERNAL_ERROR;
382 }
383 return ERR_OK;
384 }
385
GetDataMgr()386 ErrCode BundleCloneInstaller::GetDataMgr()
387 {
388 if (dataMgr_ == nullptr) {
389 dataMgr_ = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
390 if (dataMgr_ == nullptr) {
391 APP_LOGE("Get dataMgr shared_ptr nullptr");
392 return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
393 }
394 }
395 return ERR_OK;
396 }
397
SendBundleSystemEvent(const std::string & bundleName,BundleEventType bundleEventType,int32_t userId,int32_t appIndex,bool isPreInstallApp,bool isFreeInstallMode,InstallScene preBundleScene,ErrCode errCode)398 void BundleCloneInstaller::SendBundleSystemEvent(const std::string &bundleName, BundleEventType bundleEventType,
399 int32_t userId, int32_t appIndex, bool isPreInstallApp, bool isFreeInstallMode,
400 InstallScene preBundleScene, ErrCode errCode)
401 {
402 EventInfo sysEventInfo;
403 sysEventInfo.bundleName = bundleName;
404 sysEventInfo.isPreInstallApp = isPreInstallApp;
405 sysEventInfo.errCode = errCode;
406 sysEventInfo.isFreeInstallMode = isFreeInstallMode;
407 sysEventInfo.userId = userId;
408 sysEventInfo.appIndex = appIndex;
409 sysEventInfo.callingUid = IPCSkeleton::GetCallingUid();
410 sysEventInfo.versionCode = versionCode_;
411 sysEventInfo.preBundleScene = preBundleScene;
412 GetCallingEventInfo(sysEventInfo);
413 EventReport::SendBundleSystemEvent(bundleEventType, sysEventInfo);
414 }
415
GetCallingEventInfo(EventInfo & eventInfo)416 void BundleCloneInstaller::GetCallingEventInfo(EventInfo &eventInfo)
417 {
418 APP_LOGD("GetCallingEventInfo start, bundleName:%{public}s", eventInfo.callingBundleName.c_str());
419 if (dataMgr_ == nullptr) {
420 APP_LOGE("Get dataMgr shared_ptr nullptr");
421 return;
422 }
423 if (!dataMgr_->GetBundleNameForUid(eventInfo.callingUid, eventInfo.callingBundleName)) {
424 APP_LOGE("CallingUid %{public}d is not hap, no bundleName", eventInfo.callingUid);
425 eventInfo.callingBundleName = Constants::EMPTY_STRING;
426 return;
427 }
428 BundleInfo bundleInfo;
429 if (!dataMgr_->GetBundleInfo(eventInfo.callingBundleName, BundleFlag::GET_BUNDLE_DEFAULT, bundleInfo,
430 eventInfo.callingUid / Constants::BASE_USER_RANGE)) {
431 APP_LOGE("GetBundleInfo failed, bundleName: %{public}s", eventInfo.callingBundleName.c_str());
432 return;
433 }
434 eventInfo.callingAppId = bundleInfo.appId;
435 }
436
ResetInstallProperties()437 void BundleCloneInstaller::ResetInstallProperties()
438 {
439 uid_ = 0;
440 accessTokenId_ = 0;
441 versionCode_ = 0;
442 appId_ = "";
443 appIdentifier_ = "";
444 }
445 } // AppExecFwk
446 } // OHOS
447