• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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