1 /*
2 * Copyright (c) 2022 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_sandbox_installer.h"
17
18 #include "ability_manager_helper.h"
19 #include "bundle_mgr_service.h"
20 #include "bundle_permission_mgr.h"
21 #include "datetime_ex.h"
22 #include "hitrace_meter.h"
23 #include "installd_client.h"
24 #include "perf_profile.h"
25 #include "scope_guard.h"
26
27 namespace OHOS {
28 namespace AppExecFwk {
29 namespace {
30 const int32_t DLP_SANDBOX_APP_INDEX = 1000;
31 } // namespace
32
33 using namespace OHOS::Security;
34
BundleSandboxInstaller()35 BundleSandboxInstaller::BundleSandboxInstaller()
36 {
37 APP_LOGD("bundle sandbox installer instance is created");
38 }
39
~BundleSandboxInstaller()40 BundleSandboxInstaller::~BundleSandboxInstaller()
41 {
42 APP_LOGD("bundle sandbox installer instance is destroyed");
43 }
44
InstallSandboxApp(const std::string & bundleName,const int32_t & dlpType,const int32_t & userId,int32_t & appIndex)45 ErrCode BundleSandboxInstaller::InstallSandboxApp(const std::string &bundleName, const int32_t &dlpType,
46 const int32_t &userId, int32_t &appIndex)
47 {
48 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
49 APP_LOGD("InstallSandboxApp %{public}s begin", bundleName.c_str());
50
51 PerfProfile::GetInstance().SetBundleInstallStartTime(GetTickCount());
52
53 if (bundleName.empty()) {
54 APP_LOGE("the bundle name is empty");
55 return ERR_APPEXECFWK_SANDBOX_INSTALL_PARAM_ERROR;
56 }
57 bundleName_ = bundleName;
58
59 // 1. check whether original application installed or not
60 InnerBundleInfo info;
61 bool isExist = false;
62 if (!GetInnerBundleInfo(info, isExist) || !isExist) {
63 APP_LOGE("the bundle is not installed");
64 return ERR_APPEXECFWK_SANDBOX_INSTALL_APP_NOT_EXISTED;
65 }
66
67 // 2. obtain userId
68 if (userId < Constants::DEFAULT_USERID) {
69 APP_LOGE("userId(%{public}d) is invalid", userId);
70 return ERR_APPEXECFWK_SANDBOX_INSTALL_PARAM_ERROR;
71 }
72 userId_ = userId;
73
74 if (!dataMgr_->HasUserId(userId_)) {
75 APP_LOGE("the user %{public}d does not exist when when install sandbox application", userId_);
76 return ERR_APPEXECFWK_SANDBOX_INSTALL_USER_NOT_EXIST;
77 }
78
79 // 3. check whether original application installed at current userId or not
80 InnerBundleUserInfo userInfo;
81 if (!info.GetInnerBundleUserInfo(userId_, userInfo)) {
82 APP_LOGE("the origin application is not installed at current user");
83 return ERR_APPEXECFWK_SANDBOX_INSTALL_NOT_INSTALLED_AT_SPECIFIED_USERID;
84 }
85 ScopeGuard sandboxAppGuard([&] { SandboxAppRollBack(info, userId_); });
86
87 // 4. generate the accesstoken id and inherit original permissions
88 if (GetSandboxDataMgr() != ERR_OK) {
89 APP_LOGE("get sandbox data mgr failed");
90 return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
91 }
92 auto newAppIndex = sandboxDataMgr_->GenerateSandboxAppIndex(bundleName_);
93 if (newAppIndex == Constants::INITIAL_SANDBOX_APP_INDEX) {
94 APP_LOGE("invalid app index generated");
95 return ERR_APPEXECFWK_SANDBOX_INSTALL_INVALID_APP_INDEX;
96 }
97 info.SetAppIndex(newAppIndex);
98 info.SetIsSandbox(true);
99
100 Security::AccessToken::AccessTokenIDEx newTokenIdEx;
101 if (BundlePermissionMgr::InitHapToken(info, userId_, dlpType, newTokenIdEx) != ERR_OK) {
102 APP_LOGE("bundleName:%{public}s InitHapToken failed", bundleName_.c_str());
103 return ERR_APPEXECFWK_INSTALL_GRANT_REQUEST_PERMISSIONS_FAILED;
104 }
105
106 // 5. create data dir and generate uid and gid
107 info.CleanInnerBundleUserInfos();
108 userInfo.bundleName = std::to_string(newAppIndex) + Constants::FILE_UNDERLINE + bundleName_;
109 userInfo.gids.clear();
110 dataMgr_->GenerateUidAndGid(userInfo);
111 userInfo.bundleName = bundleName_;
112 info.AddInnerBundleUserInfo(userInfo);
113 info.SetBundleInstallTime(BundleUtil::GetCurrentTime(), userId_);
114 info.SetBundleUpdateTime(0, userId_);
115 info.SetAccessTokenIdEx(newTokenIdEx, userId_);
116 APP_LOGD("InstallSandboxApp generate uid of sandbox is %{public}d", userInfo.uid);
117 ErrCode result = CreateSandboxDataDir(info, userInfo.uid, newAppIndex);
118 if (result != ERR_OK) {
119 APP_LOGE("InstallSandboxApp create sandbox dir failed");
120 return result;
121 }
122
123 // 6. store new bundleInfo to sandbox data manager
124 sandboxDataMgr_->SaveSandboxAppInfo(info, newAppIndex);
125
126 // 7. SaveSandboxPersistentInfo
127 bool saveBundleInfoRes = sandboxDataMgr_->SaveSandboxPersistentInfo(std::to_string(newAppIndex) +
128 Constants::FILE_UNDERLINE + bundleName_, info);
129 if (!saveBundleInfoRes) {
130 APP_LOGE("InstallSandboxApp SaveSandboxPersistentInfo failed");
131 return ERR_APPEXECFWK_SANDBOX_INSTALL_DATABASE_OPERATION_FAILED;
132 }
133 sandboxAppGuard.Dismiss();
134 dataMgr_->EnableBundle(bundleName_);
135
136 // 8. publish common event
137 std::shared_ptr<BundleCommonEventMgr> commonEventMgr = std::make_shared<BundleCommonEventMgr>();
138 result = commonEventMgr->NotifySandboxAppStatus(info, userInfo.uid, userId_, SandboxInstallType::INSTALL);
139 if (result != ERR_OK) {
140 APP_LOGE("NotifySandboxAppStatus failed due to error : %{public}d", result);
141 }
142
143 appIndex = newAppIndex;
144 PerfProfile::GetInstance().SetBundleInstallEndTime(GetTickCount());
145
146 APP_LOGD("InstallSandboxApp %{public}s succesfully", bundleName.c_str());
147 return result;
148 }
149
UninstallSandboxApp(const std::string & bundleName,const int32_t & appIndex,const int32_t & userId)150 ErrCode BundleSandboxInstaller::UninstallSandboxApp(
151 const std::string &bundleName, const int32_t &appIndex, const int32_t &userId)
152 {
153 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
154 APP_LOGD("UninstallSandboxApp %{public}s _ %{public}d begin", bundleName.c_str(), appIndex);
155
156 PerfProfile::GetInstance().SetBundleInstallStartTime(GetTickCount());
157
158 // 1. check userId
159 if (GetDataMgr() != ERR_OK) {
160 APP_LOGE("Get dataMgr shared_ptr nullptr");
161 return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
162 }
163 if (userId < Constants::DEFAULT_USERID) {
164 APP_LOGE("userId(%{public}d) is invalid", userId);
165 return ERR_APPEXECFWK_SANDBOX_INSTALL_PARAM_ERROR;
166 }
167 userId_ = userId;
168 if (!dataMgr_->HasUserId(userId_)) {
169 APP_LOGE("The user %{public}d does not exist when uninstall sandbox application", userId_);
170 return ERR_APPEXECFWK_SANDBOX_INSTALL_USER_NOT_EXIST;
171 }
172
173 // 2. check whether sandbox appinfo can be found from data manager or not
174 InnerBundleInfo info;
175 if (GetSandboxDataMgr() != ERR_OK) {
176 APP_LOGE("get sandbox data mgr failed");
177 return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
178 }
179 ErrCode result = ERR_OK;
180 if ((result = sandboxDataMgr_->GetSandboxAppInfo(bundleName, appIndex, userId_, info)) != ERR_OK) {
181 APP_LOGE("UninstallSandboxApp no sandbox app info can be found");
182 return result;
183 }
184
185 // 3. check whether sandbox app is installed at current user
186 InnerBundleUserInfo userInfo;
187 if (!info.GetInnerBundleUserInfo(userId_, userInfo)) {
188 APP_LOGE("the sandbox app is not installed at this user %{public}d", userId_);
189 return ERR_APPEXECFWK_SANDBOX_INSTALL_NOT_INSTALLED_AT_SPECIFIED_USERID;
190 }
191
192 // 4. kill sandbox app process
193 if (!AbilityManagerHelper::UninstallApplicationProcesses(info.GetApplicationName(), info.GetUid(userId_))) {
194 APP_LOGW("sandbox app process cannot be killed");
195 }
196
197 // 5. delete accesstoken id and appIndex
198 uint32_t accessTokenId = info.GetAccessTokenId(userId_);
199 if (BundlePermissionMgr::DeleteAccessTokenId(accessTokenId) !=
200 AccessToken::AccessTokenKitRet::RET_SUCCESS) {
201 APP_LOGE("delete accessToken failed");
202 }
203
204 if (!sandboxDataMgr_->DeleteSandboxAppIndex(bundleName, appIndex)) {
205 APP_LOGE("delete sandbox app index failed");
206 return ERR_APPEXECFWK_SANDBOX_INSTALL_DELETE_APP_INDEX_FAILED;
207 }
208
209 // 6. remove data dir and uid, gid
210 std::string innerBundleName = std::to_string(appIndex) + Constants::FILE_UNDERLINE + bundleName;
211 result = InstalldClient::GetInstance()->RemoveBundleDataDir(innerBundleName, userId_);
212 if (result != ERR_OK) {
213 APP_LOGE("fail to remove data dir: %{public}s, error is %{public}d", innerBundleName.c_str(), result);
214 return result;
215 }
216 userInfo.bundleName = innerBundleName;
217 info.AddInnerBundleUserInfo(userInfo);
218 dataMgr_->RecycleUidAndGid(info);
219
220 // 7. remove new innerBundleInfo from sandData manager
221 sandboxDataMgr_->DeleteSandboxAppInfo(bundleName, appIndex);
222
223 // 8. remove sandbox persistent info
224 bool saveBundleInfoRes = sandboxDataMgr_->RemoveSandboxPersistentInfo(innerBundleName);
225 if (!saveBundleInfoRes) {
226 APP_LOGE("UninstallSandboxApp RemoveSandboxPersistentInfo failed");
227 return ERR_APPEXECFWK_SANDBOX_INSTALL_DATABASE_OPERATION_FAILED;
228 }
229
230 // 9. publish common event
231 std::shared_ptr<BundleCommonEventMgr> commonEventMgr = std::make_shared<BundleCommonEventMgr>();
232 result = commonEventMgr->NotifySandboxAppStatus(info, userInfo.uid, userId_, SandboxInstallType::UNINSTALL);
233 if (result != ERR_OK) {
234 APP_LOGE("NotifySandboxAppStatus failed due to error : %{public}d", result);
235 }
236
237 PerfProfile::GetInstance().SetBundleInstallEndTime(GetTickCount());
238
239 APP_LOGI("UninstallSandboxApp %{public}s _ %{public}d succesfully", bundleName.c_str(), appIndex);
240 return result;
241 }
242
CreateSandboxDataDir(InnerBundleInfo & info,const int32_t & uid,const int32_t & appIndex) const243 ErrCode BundleSandboxInstaller::CreateSandboxDataDir(
244 InnerBundleInfo &info, const int32_t &uid, const int32_t &appIndex) const
245 {
246 APP_LOGD("CreateSandboxDataDir %{public}s _ %{public}d begin", info.GetBundleName().c_str(), appIndex);
247 std::string innerDataDir = std::to_string(appIndex) + Constants::FILE_UNDERLINE + info.GetBundleName();
248 CreateDirParam createDirParam;
249 createDirParam.bundleName = innerDataDir;
250 createDirParam.userId = userId_;
251 createDirParam.uid = uid;
252 createDirParam.gid = uid;
253 createDirParam.apl = info.GetAppPrivilegeLevel();
254 createDirParam.isPreInstallApp = info.IsPreInstallApp();
255 createDirParam.debug = info.GetBaseApplicationInfo().appProvisionType == Constants::APP_PROVISION_TYPE_DEBUG;
256 createDirParam.isDlpSandbox = (appIndex > DLP_SANDBOX_APP_INDEX);
257 auto result = InstalldClient::GetInstance()->CreateBundleDataDir(createDirParam);
258 if (result != ERR_OK) {
259 APP_LOGE("fail to create sandbox data dir, error is %{public}d", result);
260 return result;
261 }
262 std::string dataBaseDir = ServiceConstants::BUNDLE_APP_DATA_BASE_DIR + ServiceConstants::BUNDLE_EL[1] +
263 ServiceConstants::DATABASE + innerDataDir;
264 info.SetAppDataBaseDir(dataBaseDir);
265 APP_LOGI("CreateSandboxDataDir successfully");
266 return result;
267 }
268
SandboxAppRollBack(InnerBundleInfo & info,const int32_t & userId)269 void BundleSandboxInstaller::SandboxAppRollBack(InnerBundleInfo &info, const int32_t &userId)
270 {
271 // when a sandbox is installed failed, some stuff, including uid, gid, appIndex,
272 // accessToken Id and the data dir will be removed.
273 APP_LOGI("SandboxAppRollBack begin");
274 BundlePermissionMgr::DeleteAccessTokenId(info.GetAccessTokenId(userId));
275 auto bundleName = info.GetBundleName();
276 auto appIndex = info.GetAppIndex();
277 if (GetSandboxDataMgr() != ERR_OK) {
278 APP_LOGE("get sandbox data mgr failed");
279 return;
280 }
281 sandboxDataMgr_->DeleteSandboxAppIndex(bundleName, appIndex);
282 auto key = std::to_string(appIndex) + Constants::FILE_UNDERLINE + bundleName;
283 InnerBundleUserInfo userInfo;
284 if (!info.GetInnerBundleUserInfo(userId, userInfo)) {
285 APP_LOGW("SandboxAppRollBack cannot obtain the userInfo");
286 } else {
287 userInfo.bundleName = key;
288 info.AddInnerBundleUserInfo(userInfo);
289 dataMgr_->RecycleUidAndGid(info);
290 }
291 if (InstalldClient::GetInstance()->RemoveBundleDataDir(key, userId) != ERR_OK) {
292 APP_LOGW("SandboxAppRollBack cannot remove the data dir");
293 }
294 APP_LOGI("SandboxAppRollBack finish");
295 }
296
UninstallAllSandboxApps(const std::string & bundleName,int32_t userId)297 ErrCode BundleSandboxInstaller::UninstallAllSandboxApps(const std::string &bundleName, int32_t userId)
298 {
299 // All sandbox will be uninstalled when the original application is updated or uninstalled
300 if (bundleName.empty()) {
301 APP_LOGE("UninstallAllSandboxApps failed due to empty bundle name");
302 return ERR_APPEXECFWK_SANDBOX_INSTALL_PARAM_ERROR;
303 }
304
305 if (GetDataMgr() != ERR_OK) {
306 APP_LOGE("UninstallAllSandboxApps get dataMgr shared_ptr nullptr");
307 return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
308 }
309 if (GetSandboxDataMgr() != ERR_OK) {
310 APP_LOGE("get sandbox data mgr failed");
311 return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
312 }
313 auto sandboxAppInfoMap = sandboxDataMgr_->GetSandboxAppInfoMap();
314 for_each(sandboxAppInfoMap.begin(), sandboxAppInfoMap.end(), [&bundleName, &userId, this](
315 std::unordered_map<std::string, InnerBundleInfo>::reference info)->void {
316 auto pos = info.first.find(bundleName);
317 if (pos != std::string::npos && pos > 1) {
318 std::string appIndexStr = info.first.substr(0, pos - 1);
319 int32_t appIndex = Constants::INITIAL_SANDBOX_APP_INDEX;
320 if (!StrToInt(appIndexStr, appIndex)) {
321 APP_LOGE("UninstallAllSandboxApps obtain appIndex failed");
322 return;
323 }
324 auto userInfos = info.second.GetInnerBundleUserInfos();
325 if (userInfos.empty()) {
326 APP_LOGE("userInfos is empty");
327 return;
328 }
329 auto specifiedUserId = (userInfos.begin()->second).bundleUserInfo.userId;
330 if (specifiedUserId == userId || userId == Constants::INVALID_USERID) {
331 if (this->UninstallSandboxApp(bundleName, appIndex, specifiedUserId) != ERR_OK) {
332 APP_LOGE("UninstallSandboxApp failed");
333 return;
334 }
335 }
336 }
337 });
338 return ERR_OK;
339 }
340
GetInnerBundleInfo(InnerBundleInfo & info,bool & isAppExist)341 bool BundleSandboxInstaller::GetInnerBundleInfo(InnerBundleInfo &info, bool &isAppExist)
342 {
343 if (GetDataMgr() != ERR_OK) {
344 APP_LOGE("Get dataMgr shared_ptr failed");
345 return false;
346 }
347 isAppExist = dataMgr_->GetInnerBundleInfo(bundleName_, info);
348 return true;
349 }
350
GetSandboxDataMgr()351 ErrCode BundleSandboxInstaller::GetSandboxDataMgr()
352 {
353 if (sandboxDataMgr_ == nullptr) {
354 if (GetDataMgr() != ERR_OK) {
355 APP_LOGE("Get dataMgr shared_ptr failed");
356 return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
357 }
358
359 sandboxDataMgr_ = dataMgr_->GetSandboxAppHelper()->GetSandboxDataMgr();
360 if (sandboxDataMgr_ == nullptr) {
361 APP_LOGE("Get sandbox dataMgr shared_ptr nullptr");
362 return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
363 }
364 }
365 return ERR_OK;
366 }
367
GetDataMgr()368 ErrCode BundleSandboxInstaller::GetDataMgr()
369 {
370 if (dataMgr_ == nullptr) {
371 dataMgr_ = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
372 if (dataMgr_ == nullptr) {
373 APP_LOGE("Get dataMgr shared_ptr nullptr");
374 return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
375 }
376 }
377 return ERR_OK;
378 }
379 } // AppExecFwk
380 } // OHOS
381