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_multiuser_installer.h"
17
18 #include "ability_manager_helper.h"
19 #include "bms_extension_data_mgr.h"
20 #include "bundle_constants.h"
21 #include "bundle_mgr_service.h"
22 #include "bundle_permission_mgr.h"
23 #include "bundle_resource_helper.h"
24 #include "bundle_util.h"
25 #include "datetime_ex.h"
26 #include "hitrace_meter.h"
27 #include "installd_client.h"
28 #include "perf_profile.h"
29 #include "scope_guard.h"
30
31
32 namespace OHOS {
33 namespace AppExecFwk {
34 using namespace OHOS::Security;
35
BundleMultiUserInstaller()36 BundleMultiUserInstaller::BundleMultiUserInstaller()
37 {
38 APP_LOGD("created");
39 }
40
~BundleMultiUserInstaller()41 BundleMultiUserInstaller::~BundleMultiUserInstaller()
42 {
43 APP_LOGD("~");
44 }
45
InstallExistedApp(const std::string &bundleName, const int32_t userId)46 ErrCode BundleMultiUserInstaller::InstallExistedApp(const std::string &bundleName, const int32_t userId)
47 {
48 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
49 APP_LOGI("-n %{public}s -u %{public}d begin", bundleName.c_str(), userId);
50
51 BmsExtensionDataMgr bmsExtensionDataMgr;
52 if (bmsExtensionDataMgr.IsAppInBlocklist(bundleName, userId)) {
53 APP_LOGE("app %{public}s is in blocklist", bundleName.c_str());
54 return ERR_APPEXECFWK_INSTALL_APP_IN_BLOCKLIST;
55 }
56
57 if (GetDataMgr() != ERR_OK) {
58 return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
59 }
60
61 PerfProfile::GetInstance().SetBundleInstallStartTime(GetTickCount());
62 ErrCode result = ProcessBundleInstall(bundleName, userId);
63 NotifyBundleEvents installRes = {
64 .type = NotifyType::INSTALL,
65 .resultCode = result,
66 .accessTokenId = accessTokenId_,
67 .uid = uid_,
68 .appIndex = 0,
69 .bundleName = bundleName
70 };
71 std::shared_ptr<BundleCommonEventMgr> commonEventMgr = std::make_shared<BundleCommonEventMgr>();
72 commonEventMgr->NotifyBundleStatus(installRes, dataMgr_);
73
74 ResetInstallProperties();
75 PerfProfile::GetInstance().SetBundleInstallEndTime(GetTickCount());
76 APP_LOGI("-n %{public}s -u %{public}d, ret:%{public}d finished",
77 bundleName.c_str(), userId, result);
78 return result;
79 }
80
ProcessBundleInstall(const std::string &bundleName, const int32_t userId)81 ErrCode BundleMultiUserInstaller::ProcessBundleInstall(const std::string &bundleName, const int32_t userId)
82 {
83 if (bundleName.empty()) {
84 APP_LOGE("bundleName empty");
85 return ERR_APPEXECFWK_INSTALL_PARAM_ERROR;
86 }
87
88 if (userId <= Constants::DEFAULT_USERID) {
89 APP_LOGE("userId(%{public}d) invalid", userId);
90 return ERR_BUNDLE_MANAGER_INVALID_USER_ID;
91 }
92 if (GetDataMgr() != ERR_OK) {
93 return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
94 }
95
96 // 1. check whether original application installed or not
97 ScopeGuard bundleEnabledGuard([&] { dataMgr_->EnableBundle(bundleName); });
98 InnerBundleInfo info;
99 bool isExist = dataMgr_->GetInnerBundleInfoWithDisable(bundleName, info);
100 if (!isExist) {
101 APP_LOGE("the bundle is not installed");
102 return ERR_BUNDLE_MANAGER_BUNDLE_NOT_EXIST;
103 }
104
105 // 2. obtain userId
106 if (!dataMgr_->HasUserId(userId)) {
107 APP_LOGE("install app user %{public}d not exist", userId);
108 return ERR_BUNDLE_MANAGER_INVALID_USER_ID;
109 }
110
111 // 3. check whether original application installed at current userId or not
112 InnerBundleUserInfo userInfo;
113 if (info.GetInnerBundleUserInfo(userId, userInfo)) {
114 APP_LOGE("the origin application had installed at current user");
115 return ERR_OK;
116 }
117
118 std::string appDistributionType = info.GetAppDistributionType();
119 if (appDistributionType == Constants::APP_DISTRIBUTION_TYPE_ENTERPRISE
120 || appDistributionType == Constants::APP_DISTRIBUTION_TYPE_ENTERPRISE_NORMAL
121 || appDistributionType == Constants::APP_DISTRIBUTION_TYPE_ENTERPRISE_MDM) {
122 APP_LOGE("the origin application is enterprise, not allow to install here");
123 return ERR_APPEXECFWK_INSTALL_EXISTED_ENTERPRISE_BUNDLE_NOT_ALLOWED;
124 }
125 if (appDistributionType == Constants::APP_DISTRIBUTION_TYPE_INTERNALTESTING) {
126 APP_LOGE("the origin application is inrternaltesting, not allow to install here");
127 return ERR_APPEXECFWK_INSTALL_FAILED_CONTROLLED;
128 }
129
130 // uid
131 InnerBundleUserInfo newUserInfo;
132 newUserInfo.bundleName = bundleName;
133 newUserInfo.bundleUserInfo.userId = userId;
134 if (!dataMgr_->GenerateUidAndGid(newUserInfo)) {
135 return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
136 }
137 int32_t uid = newUserInfo.uid;
138
139 // 4. generate the accesstoken id and inherit original permissions
140 Security::AccessToken::AccessTokenIDEx newTokenIdEx;
141 if (BundlePermissionMgr::InitHapToken(info, userId, 0, newTokenIdEx) != ERR_OK) {
142 APP_LOGE("bundleName:%{public}s InitHapToken failed", bundleName.c_str());
143 return ERR_APPEXECFWK_INSTALL_GRANT_REQUEST_PERMISSIONS_FAILED;
144 }
145 ScopeGuard applyAccessTokenGuard([&] {
146 BundlePermissionMgr::DeleteAccessTokenId(newTokenIdEx.tokenIdExStruct.tokenID);
147 });
148 newUserInfo.accessTokenId = newTokenIdEx.tokenIdExStruct.tokenID;
149 newUserInfo.accessTokenIdEx = newTokenIdEx.tokenIDEx;
150 uid_ = uid;
151 accessTokenId_ = newTokenIdEx.tokenIdExStruct.tokenID;
152 int64_t now = BundleUtil::GetCurrentTime();
153 newUserInfo.installTime = now;
154 newUserInfo.updateTime = now;
155
156 ScopeGuard createUserDataDirGuard([&] { RemoveDataDir(bundleName, userId); });
157 ErrCode result = CreateDataDir(info, userId, uid);
158 if (result != ERR_OK) {
159 APP_LOGE("InstallExisted create dir failed");
160 return result;
161 }
162
163 ScopeGuard addBundleUserGuard([&] { dataMgr_->RemoveInnerBundleUserInfo(bundleName, userId); });
164 if (!dataMgr_->AddInnerBundleUserInfo(bundleName, newUserInfo)) {
165 return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
166 }
167
168 // total to commit, avoid rollback
169 applyAccessTokenGuard.Dismiss();
170 createUserDataDirGuard.Dismiss();
171 addBundleUserGuard.Dismiss();
172 APP_LOGI("InstallExisted %{public}s succesfully", bundleName.c_str());
173 return ERR_OK;
174 }
175
CreateDataDir(InnerBundleInfo &info, const int32_t userId, const int32_t &uid) const176 ErrCode BundleMultiUserInstaller::CreateDataDir(InnerBundleInfo &info,
177 const int32_t userId, const int32_t &uid) const
178 {
179 APP_LOGD("CreateDataDir %{public}s begin", info.GetBundleName().c_str());
180 std::string innerDataDir = info.GetBundleName();
181 CreateDirParam createDirParam;
182 createDirParam.bundleName = innerDataDir;
183 createDirParam.userId = userId;
184 createDirParam.uid = uid;
185 createDirParam.gid = uid;
186 createDirParam.apl = info.GetAppPrivilegeLevel();
187 createDirParam.isPreInstallApp = info.IsPreInstallApp();
188 createDirParam.debug = info.GetBaseApplicationInfo().appProvisionType == Constants::APP_PROVISION_TYPE_DEBUG;
189 auto result = InstalldClient::GetInstance()->CreateBundleDataDir(createDirParam);
190 if (result != ERR_OK) {
191 APP_LOGE("fail to create data dir, error is %{public}d", result);
192 return result;
193 }
194 APP_LOGI("CreateDataDir successfully");
195 return result;
196 }
197
RemoveDataDir(const std::string bundleName, int32_t userId)198 ErrCode BundleMultiUserInstaller::RemoveDataDir(const std::string bundleName, int32_t userId)
199 {
200 std::string key = bundleName;
201 if (InstalldClient::GetInstance()->RemoveBundleDataDir(key, userId) != ERR_OK) {
202 APP_LOGW("App cannot remove the data dir");
203 return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
204 }
205 return ERR_OK;
206 }
207
GetDataMgr()208 ErrCode BundleMultiUserInstaller::GetDataMgr()
209 {
210 if (dataMgr_ == nullptr) {
211 dataMgr_ = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
212 if (dataMgr_ == nullptr) {
213 APP_LOGE("Get dataMgr shared_ptr nullptr");
214 return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
215 }
216 }
217 return ERR_OK;
218 }
219
ResetInstallProperties()220 void BundleMultiUserInstaller::ResetInstallProperties()
221 {
222 uid_ = 0;
223 accessTokenId_ = 0;
224 }
225 } // AppExecFwk
226 } // OHOS
227