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