• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 #include "bundle_clone_mgr.h"
16 
17 #include <iostream>
18 #include <fstream>
19 
20 #include "installd_client.h"
21 #include "bundle_mgr_service.h"
22 #include "ability_manager_interface.h"
23 #include "system_ability_helper.h"
24 #include "system_ability_definition.h"
25 #include "nlohmann/json.hpp"
26 #include "ipc_skeleton.h"
27 #include "scope_guard.h"
28 
29 namespace OHOS {
30 namespace AppExecFwk {
31 namespace {
UninstallApplicationProcesses(const std::string & bundleName,const int uid)32 bool UninstallApplicationProcesses(const std::string &bundleName, const int uid)
33 {
34     APP_LOGI("remove cloned bundle kill running processes, app name is %{public}s", bundleName.c_str());
35     sptr<AAFwk::IAbilityManager> abilityMgrProxy =
36         iface_cast<AAFwk::IAbilityManager>(SystemAbilityHelper::GetSystemAbility(ABILITY_MGR_SERVICE_ID));
37     if (!abilityMgrProxy) {
38         APP_LOGE("fail to find the app mgr service to kill application");
39         return false;
40     }
41     if (abilityMgrProxy->UninstallApp(bundleName, uid) != 0) {
42         APP_LOGE("kill application process failed");
43         return false;
44     }
45     return true;
46 }
47 }
48 
BundleCloneMgr()49 BundleCloneMgr::BundleCloneMgr()
50 {
51     APP_LOGI("");
52 }
53 
~BundleCloneMgr()54 BundleCloneMgr::~BundleCloneMgr()
55 {
56     APP_LOGI("");
57 }
58 
BundleClone(const std::string & bundleName)59 bool BundleCloneMgr::BundleClone(const std::string &bundleName)
60 {
61     APP_LOGD("BundleClone start");
62     auto result = CheckBundleNameInAllowList(bundleName);
63     if (result != true) {
64         APP_LOGE("The APP is not on the AllowList");
65         APP_LOGE("BundleClone fail");
66         return false;
67     }
68     result = SetCloneAppName(bundleName);
69     if (result != true) {
70         APP_LOGE("BundleClone fail because the APP clone file already exists");
71         APP_LOGE("BundleClone fail");
72         return false;
73     }
74     result = CreateCloneBundleInfo(bundleName);
75     if (result != true) {
76         DeleteCloneAppName(bundleName);
77         APP_LOGE("CreateCloneBundleInfo fail");
78         APP_LOGE("BundleClone fail");
79         return false;
80     }
81     result = ProcessCloneInstall(bundleName);
82     if (result != ERR_OK) {
83         DeleteCloneAppName(bundleName);
84         APP_LOGE("ProcessCloneInstall fail");
85         APP_LOGE("BundleClone fail");
86         return false;
87     }
88     APP_LOGD("clone app success");
89     return true;
90 }
91 
SetCloneAppName(const std::string & bundleName)92 bool BundleCloneMgr::SetCloneAppName(const std::string &bundleName)
93 {
94     APP_LOGD("SetCloneAppName start");
95     std::fstream f("/data/clonefile/CloneAppName.json");
96     bool isExist = f.good();
97     if (isExist) {
98         nlohmann::json jParse;
99         f.seekg(0, std::ios::end);
100         int len = static_cast<int>(f.tellg());
101         if (len == 0) {
102             jParse[bundleName] = bundleName;
103             f << std::setw(Constants::DUMP_INDENT) << jParse << std::endl;
104             APP_LOGD("clone bundleName Of file success (first)");
105         } else {
106             f.seekg(0, std::ios::beg);
107             nlohmann::json jsonFile;
108             f >> jsonFile;
109             if (jsonFile.find(bundleName) != jsonFile.end()) {
110                 APP_LOGE("clone bundleName = %{public}s is exist", bundleName.c_str());
111                 f.close();
112                 return false;
113             } else {
114                 jsonFile[bundleName] = bundleName;
115                 f.seekp(0, std::ios::beg);
116                 f << std::setw(Constants::DUMP_INDENT) << jsonFile << std::endl;
117                 APP_LOGD("clone bundleName = %{public}s Of file success", bundleName.c_str());
118             }
119         }
120     } else {
121         APP_LOGE("clone file not exist");
122         return false;
123     }
124     f.close();
125     return true;
126 }
127 
DeleteCloneAppName(const std::string & bundleName)128 bool BundleCloneMgr::DeleteCloneAppName(const std::string &bundleName)
129 {
130     APP_LOGI("delete clone file");
131     bool isEmpty = false;
132     std::ifstream i("/data/clonefile/CloneAppName.json", std::ifstream::in);
133     nlohmann::json jParse;
134     if (!i.is_open()) {
135         APP_LOGE("failed to open clone file");
136         return false;
137     } else {
138         i.seekg(0, std::ios::end);
139         int len = static_cast<int>(i.tellg());
140         if (len != 0) {
141             i.seekg(0, std::ios::beg);
142             i >> jParse;
143             APP_LOGE("find name in the clone file");
144             if (jParse.find(bundleName) != jParse.end()) {
145                 jParse.erase(bundleName);
146                 APP_LOGE("clone file fstream delete success");
147             } else {
148                 APP_LOGE("not find appName = %{public}s", bundleName.c_str());
149             }
150         } else {
151             APP_LOGE("file is empty appName = %{private}s", bundleName.c_str());
152         }
153     }
154     i.close();
155 
156     std::ofstream o("/data/clonefile/CloneAppName.json");
157     if (!o.is_open()) {
158         APP_LOGE("failed to open clone file");
159         return false;
160     } else {
161         if (!isEmpty) {
162             o << std::setw(Constants::DUMP_INDENT) << jParse;
163         }
164     }
165     o.close();
166     APP_LOGD("clone file AppName delete success");
167     return true;
168 }
169 
CreateCloneBundleInfo(const std::string & bundleName)170 bool BundleCloneMgr::CreateCloneBundleInfo(const std::string &bundleName)
171 {
172     APP_LOGD("CreateCloneBundleInfo start");
173     dataMgr_ = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
174     if (dataMgr_ == nullptr) {
175         APP_LOGE("datamgr is nullptr");
176         return false;
177     }
178     auto result = dataMgr_->GetInnerBundleInfo(bundleName, Constants::CURRENT_DEVICE_ID, cloneInfo_);
179     if (!result) {
180         APP_LOGE("Clone AppName BundleInfo fail");
181         return false;
182     }
183     APP_LOGD("finish CreateCloneBundleInfo");
184     cloneInfo_.SetIsCloned(true);
185     bool LogisCloned = cloneInfo_.GetisCloned();
186     APP_LOGD("cloneInfo_.GetisCloned() is %{public}d", LogisCloned);
187     return result;
188 }
189 
ProcessCloneInstall(const std::string & bundleName)190 ErrCode BundleCloneMgr::ProcessCloneInstall(const std::string &bundleName)
191 {
192     APP_LOGD("ProcessCloneInstall start");
193     ErrCode result = 0;
194     dataMgr_ = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
195     if (!ModifyInstallDirByHapType(cloneInfo_)) {
196         APP_LOGE("clone modify bundle install dir failed %{public}d", result);
197         return ERR_APPEXECFWK_INSTALL_PARAM_ERROR;
198     }
199     bundleName_ = cloneInfo_.GetBundleName();
200     modulePackage_ = cloneInfo_.GetCurrentModulePackage();
201     mainAbility_ = cloneInfo_.GetMainAbilityName();
202 
203     // Create clone Uid
204     result = CreateBundleAndDataDir(cloneInfo_);
205     if (result != ERR_OK) {
206         APP_LOGE("clone create bundle and data dir failed");
207         return result;
208     }
209     cloneInfo_.SetBundleStatus(InnerBundleInfo::BundleStatus::ENABLED);
210     if (!dataMgr_->SaveNewInfoToDB(bundleName_, cloneInfo_)) {
211         APP_LOGE("clone add bundle %{public}s info failed", bundleName_.c_str());
212         return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR;
213     }
214     std::string Newbundlename = cloneInfo_.GetDBKeyBundleName();
215     dataMgr_->EnableBundle(Newbundlename);
216     dataMgr_->EnableBundle(bundleName_);
217     APP_LOGD("ProcessCloneInstall finish");
218     return ERR_OK;
219 }
220 
CreateBundleAndDataDir(InnerBundleInfo & info) const221 ErrCode BundleCloneMgr::CreateBundleAndDataDir(InnerBundleInfo &info) const
222 {
223     APP_LOGD("CreateBundleAndDataDir start");
224     auto cloneCodePath = cloneInfo_.GetAppCodePath();
225     APP_LOGI("clone create bundle dir %{public}s", cloneCodePath.c_str());
226     InnerBundleUserInfo newInnerBundleUserInfo;
227     newInnerBundleUserInfo.bundleUserInfo.userId = Constants::DEFAULT_USERID;
228     newInnerBundleUserInfo.bundleName = bundleName_;
229     if (!dataMgr_->GenerateUidAndGid(newInnerBundleUserInfo)) {
230         APP_LOGE("clone fail to gererate uid and gid");
231         return ERR_APPEXECFWK_INSTALL_GENERATE_UID_ERROR;
232     }
233     info.SetApplicationInfoUid();
234     int logUid = info.GetApplicationInfoUid();
235     APP_LOGD("info.uid is %{public}d", logUid);
236 
237     bool LogisCloned = info.GetisCloned();
238     APP_LOGD("info.GetisCloned is %{public}d", LogisCloned);
239 
240     info.SetNewBundleName(bundleName_);
241     std::string Newbundlename = info.GetDBKeyBundleName();
242     APP_LOGI("clone Newbundlename %{public}s", Newbundlename.c_str());
243     auto cloneDataPath = baseDataPath_ + Constants::PATH_SEPARATOR + Newbundlename;
244     ErrCode result = InstalldClient::GetInstance()->CreateBundleDataDir(
245         cloneDataPath, newInnerBundleUserInfo.bundleUserInfo.userId,
246         newInnerBundleUserInfo.uid, newInnerBundleUserInfo.uid, info.GetAppPrivilegeLevel(), true);
247     if (result != ERR_OK) {
248         APP_LOGE("clone fail to create bundle data dir, error is %{public}d", result);
249         return result;
250     }
251     UpdateBundlePaths(info, cloneDataPath);
252     APP_LOGD("CreateBundleAndDataDir finish");
253     return ERR_OK;
254 }
255 
ModifyInstallDirByHapType(InnerBundleInfo & info)256 bool BundleCloneMgr::ModifyInstallDirByHapType(InnerBundleInfo &info)
257 {
258     auto internalPath = Constants::PATH_SEPARATOR + Constants::USER_ACCOUNT_DIR + Constants::FILE_UNDERLINE +
259                         std::to_string(info.GetUserId()) + Constants::PATH_SEPARATOR;
260     switch (info.GetAppType()) {
261         case Constants::AppType::SYSTEM_APP:
262             baseCodePath_ = Constants::SYSTEM_APP_INSTALL_PATH + internalPath + Constants::APP_CODE_DIR;
263             baseDataPath_ = Constants::SYSTEM_APP_INSTALL_PATH + internalPath + Constants::APP_DATA_DIR;
264             break;
265         case Constants::AppType::THIRD_SYSTEM_APP:
266             baseCodePath_ = Constants::THIRD_SYSTEM_APP_INSTALL_PATH + internalPath + Constants::APP_CODE_DIR;
267             baseDataPath_ = Constants::THIRD_SYSTEM_APP_INSTALL_PATH + internalPath + Constants::APP_DATA_DIR;
268             break;
269         case Constants::AppType::THIRD_PARTY_APP:
270             baseCodePath_ = Constants::THIRD_PARTY_APP_INSTALL_PATH + internalPath + Constants::APP_CODE_DIR;
271             baseDataPath_ = Constants::THIRD_PARTY_APP_INSTALL_PATH + internalPath + Constants::APP_DATA_DIR;
272             break;
273         default:
274             APP_LOGE("Clone app type error");
275             return false;
276     }
277     return true;
278 }
279 
UpdateBundlePaths(InnerBundleInfo & info,const std::string baseDataPath) const280 bool BundleCloneMgr::UpdateBundlePaths(InnerBundleInfo &info, const std::string baseDataPath) const
281 {
282     APP_LOGD("Clone UpdateBundlePaths");
283     info.SetBaseDataDir(baseDataPath);
284     info.SetAppDataDir(baseDataPath);
285     info.SetAppDataBaseDir(baseDataPath + Constants::PATH_SEPARATOR + Constants::DATA_BASE_DIR);
286     info.SetAppCacheDir(baseDataPath + Constants::PATH_SEPARATOR + Constants::CACHE_DIR);
287     return true;
288 }
289 
RemoveClonedBundle(const std::string & oldName,const std::string & bundleName)290 bool BundleCloneMgr::RemoveClonedBundle(const std::string &oldName, const std::string &bundleName)
291 {
292     APP_LOGI("begin to process remove %{public}s cloned bundle", bundleName.c_str());
293     if (bundleName.empty()) {
294         APP_LOGE("bundle name empty");
295         return false;
296     }
297     std::shared_ptr<BundleDataMgr> dataMgr_ = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
298     if (!dataMgr_) {
299         APP_LOGE("Get dataMgr shared_ptr nullptr");
300         return false;
301     }
302     InnerBundleInfo newcloneInfo_;
303     if (!dataMgr_->GetInnerBundleInfo(bundleName, Constants::CURRENT_DEVICE_ID, newcloneInfo_)) {
304         APP_LOGE("remove bundle info missing");
305         return false;
306     }
307     auto uid = newcloneInfo_.GetUid();
308     std::string Newbundlename = cloneInfo_.GetDBKeyBundleName();
309     APP_LOGD("Newbundlename is %{public}s", Newbundlename.c_str());
310     ScopeGuard enableCloneGuard([&] { dataMgr_->EnableBundle(Newbundlename); });
311     APP_LOGD("bundleName_ is %{public}s", bundleName_.c_str());
312     ScopeGuard enableGuard([&] { dataMgr_->EnableBundle(bundleName_); });
313 
314     if (!UninstallApplicationProcesses(newcloneInfo_.GetApplicationName(), uid)) {
315         APP_LOGE("can not kill process");
316         return false;
317     }
318     auto result = InstalldClient::GetInstance()->RemoveDir(newcloneInfo_.GetBaseDataDir());
319     if (result != ERR_OK) {
320         APP_LOGE("fail to remove bundle data dir, error is %{public}d", result);
321         return false;
322     }
323     if (!dataMgr_->RemoveClonedBundleInfo(bundleName)) {
324         APP_LOGE("fail to remove bundle data dir");
325         return false;
326     }
327     result = DeleteCloneAppName(oldName);
328     if (result != true) {
329         APP_LOGE("fail to DeleteCloneAppNameDeleteCloneAppName");
330         return false;
331     }
332     APP_LOGI("finish to process cloned %{public}s bundle remove", bundleName.c_str());
333     return true;
334 }
335 
CheckBundleNameInAllowList(const std::string & bundleName)336 bool BundleCloneMgr::CheckBundleNameInAllowList(const std::string &bundleName)
337 {
338     nlohmann::json jsonObject = nullptr;
339     std::ifstream ifs("/data/clonefile/BundleNameAllowList.json", std::ifstream::in);
340     if (ifs.is_open()) {
341         jsonObject=nlohmann::json::parse(ifs);
342         if (jsonObject.empty()) {
343             ifs.close();
344             return false;
345         }
346         for (auto item : jsonObject) {
347             if (item ["bundlename"] == bundleName) {
348                 ifs.close();
349                 return true;
350             }
351         }
352     }
353     return false;
354 }
355 }  // namespace AppExecFwk
356 }  // namespace OHOS
357