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