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