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