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 "quick_fix_deployer.h"
17
18 #include "app_log_tag_wrapper.h"
19 #include "bundle_mgr_service.h"
20 #include "installd_client.h"
21 #include "patch_parser.h"
22 #include "scope_guard.h"
23
24 namespace OHOS {
25 namespace AppExecFwk {
26 namespace {
27 const std::string DEBUG_APP_IDENTIFIER = "DEBUG_LIB_ID";
28 const std::string COMPILE_SDK_TYPE_OPEN_HARMONY = "OpenHarmony";
29 const std::string PATCH_DIR = "patch/";
30 }
31
QuickFixDeployer(const std::vector<std::string> & bundleFilePaths,bool isDebug,const std::string & targetPath)32 QuickFixDeployer::QuickFixDeployer(const std::vector<std::string> &bundleFilePaths, bool isDebug,
33 const std::string &targetPath) : patchPaths_(bundleFilePaths), isDebug_(isDebug), targetPath_(targetPath)
34 {}
35
Execute()36 ErrCode QuickFixDeployer::Execute()
37 {
38 ErrCode ret = DeployQuickFix();
39 if (ret != ERR_OK) {
40 LOG_E(BMS_TAG_DEFAULT, "QuickFixDeployer errcode %{public}d", ret);
41 }
42 return ret;
43 }
44
DeployQuickFix()45 ErrCode QuickFixDeployer::DeployQuickFix()
46 {
47 if (patchPaths_.empty() || (GetQuickFixDataMgr() != ERR_OK)) {
48 LOG_E(BMS_TAG_DEFAULT, "DeployQuickFix wrong parms");
49 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
50 }
51
52 std::vector<std::string> realFilePaths;
53 ErrCode ret = ProcessBundleFilePaths(patchPaths_, realFilePaths);
54 if (ret != ERR_OK) {
55 LOG_E(BMS_TAG_DEFAULT, "ProcessBundleFilePaths failed");
56 return ret;
57 }
58 ScopeGuard guardRemovePath([realFilePaths] {
59 for (const auto &path: realFilePaths) {
60 std::string tempPath = path.substr(0, path.rfind(ServiceConstants::PATH_SEPARATOR));
61 if (InstalldClient::GetInstance()->RemoveDir(tempPath) != ERR_OK) {
62 LOG_E(BMS_TAG_DEFAULT, "RemovePatchFile failed path: %{private}s", tempPath.c_str());
63 }
64 }
65 });
66 // parse check multi hqf files, update status DEPLOY_START
67 InnerAppQuickFix newInnerAppQuickFix;
68 InnerAppQuickFix oldInnerAppQuickFix;
69 if ((ret = ToDeployStartStatus(realFilePaths, newInnerAppQuickFix, oldInnerAppQuickFix)) != ERR_OK) {
70 return ret;
71 }
72 // extract diff files, apply diff patch and copy hqf, update status DEPLOY_END
73 ret = ToDeployEndStatus(newInnerAppQuickFix, oldInnerAppQuickFix);
74 if (ret != ERR_OK) {
75 bool isExist = !oldInnerAppQuickFix.GetAppQuickFix().bundleName.empty();
76 if (isExist) {
77 quickFixDataMgr_->SaveInnerAppQuickFix(oldInnerAppQuickFix);
78 } else {
79 quickFixDataMgr_->DeleteInnerAppQuickFix(newInnerAppQuickFix.GetAppQuickFix().bundleName);
80 }
81 return ret;
82 }
83 // remove old deploying patch_versionCode
84 const AppQuickFix &appQuick = oldInnerAppQuickFix.GetAppQuickFix();
85 if (!appQuick.bundleName.empty()) {
86 std::string oldPath = Constants::BUNDLE_CODE_DIR + ServiceConstants::PATH_SEPARATOR +
87 appQuick.bundleName + ServiceConstants::PATH_SEPARATOR;
88 if (appQuick.deployingAppqfInfo.type == QuickFixType::HOT_RELOAD) {
89 oldPath += ServiceConstants::HOT_RELOAD_PATH + std::to_string(appQuick.deployingAppqfInfo.versionCode);
90 } else {
91 oldPath += ServiceConstants::PATCH_PATH + std::to_string(appQuick.deployingAppqfInfo.versionCode);
92 }
93 if (InstalldClient::GetInstance()->RemoveDir(oldPath)) {
94 LOG_E(BMS_TAG_DEFAULT, "delete %{private}s failed", oldPath.c_str());
95 }
96 }
97 return ERR_OK;
98 }
99
ToDeployStartStatus(const std::vector<std::string> & bundleFilePaths,InnerAppQuickFix & newInnerAppQuickFix,InnerAppQuickFix & oldInnerAppQuickFix)100 ErrCode QuickFixDeployer::ToDeployStartStatus(const std::vector<std::string> &bundleFilePaths,
101 InnerAppQuickFix &newInnerAppQuickFix, InnerAppQuickFix &oldInnerAppQuickFix)
102 {
103 LOG_I(BMS_TAG_DEFAULT, "ToDeployStartStatus start");
104 if (GetQuickFixDataMgr() != ERR_OK) {
105 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
106 }
107 std::unordered_map<std::string, AppQuickFix> infos;
108 // parse and check multi app quick fix info
109 ErrCode ret = ParseAndCheckAppQuickFixInfos(bundleFilePaths, infos);
110 CHECK_QUICK_FIX_RESULT_RETURN_IF_FAIL(ret);
111
112 const AppQuickFix &appQuickFix = infos.begin()->second;
113 bool isExist = quickFixDataMgr_->QueryInnerAppQuickFix(appQuickFix.bundleName, oldInnerAppQuickFix);
114 const QuickFixMark &mark = oldInnerAppQuickFix.GetQuickFixMark();
115 if (isExist && (mark.status != QuickFixStatus::DEPLOY_START) && (mark.status != QuickFixStatus::DEPLOY_END)) {
116 LOG_E(BMS_TAG_DEFAULT, "error: wrong quick fix status, now status : %{public}d", mark.status);
117 return ERR_BUNDLEMANAGER_QUICK_FIX_INVALID_PATCH_STATUS;
118 }
119 const AppQuickFix &oldAppQuickFix = oldInnerAppQuickFix.GetAppQuickFix();
120 // exist and type same need to check version code
121 if (isExist && (appQuickFix.deployingAppqfInfo.type == oldAppQuickFix.deployingAppqfInfo.type)) {
122 // check current app quick fix version code
123 ret = CheckPatchVersionCode(appQuickFix, oldAppQuickFix);
124 CHECK_QUICK_FIX_RESULT_RETURN_IF_FAIL(ret);
125 }
126 // check bundleName exist
127 BundleInfo bundleInfo;
128 ret = GetBundleInfo(appQuickFix.bundleName, bundleInfo);
129 CHECK_QUICK_FIX_RESULT_RETURN_IF_FAIL(ret);
130
131 // check resources/rawfile whether valid
132 ret = CheckHqfResourceIsValid(bundleFilePaths, bundleInfo);
133 CHECK_QUICK_FIX_RESULT_RETURN_IF_FAIL(ret);
134
135 // check with installed bundle
136 if (appQuickFix.deployingAppqfInfo.type == QuickFixType::PATCH) {
137 ret = ProcessPatchDeployStart(bundleFilePaths, bundleInfo, infos);
138 } else if (appQuickFix.deployingAppqfInfo.type == QuickFixType::HOT_RELOAD) {
139 ret = ProcessHotReloadDeployStart(bundleInfo, appQuickFix);
140 } else {
141 ret = ERR_BUNDLEMANAGER_QUICK_FIX_UNKNOWN_QUICK_FIX_TYPE;
142 }
143 CHECK_QUICK_FIX_RESULT_RETURN_IF_FAIL(ret);
144
145 // convert to InnerAppQuickFix
146 ret = ToInnerAppQuickFix(infos, oldInnerAppQuickFix, newInnerAppQuickFix);
147 CHECK_QUICK_FIX_RESULT_RETURN_IF_FAIL(ret);
148
149 // save infos and update status DEPLOY_START
150 ret = SaveAppQuickFix(newInnerAppQuickFix);
151 CHECK_QUICK_FIX_RESULT_RETURN_IF_FAIL(ret);
152
153 LOG_I(BMS_TAG_DEFAULT, "ToDeployStartStatus end");
154 return ERR_OK;
155 }
156
ToDeployQuickFixResult(const AppQuickFix & appQuickFix)157 void QuickFixDeployer::ToDeployQuickFixResult(const AppQuickFix &appQuickFix)
158 {
159 LOG_D(BMS_TAG_DEFAULT, "ToDeployQuickFixResult start");
160 deployQuickFixResult_.bundleName = appQuickFix.bundleName;
161 deployQuickFixResult_.bundleVersionCode = appQuickFix.versionCode;
162 deployQuickFixResult_.patchVersionCode = appQuickFix.deployingAppqfInfo.versionCode;
163 deployQuickFixResult_.type = appQuickFix.deployingAppqfInfo.type;
164 deployQuickFixResult_.isSoContained = HasNativeSoInBundle(appQuickFix);
165 deployQuickFixResult_.moduleNames.clear();
166 for (const auto &hqf : appQuickFix.deployingAppqfInfo.hqfInfos) {
167 deployQuickFixResult_.moduleNames.emplace_back(hqf.moduleName);
168 }
169 LOG_D(BMS_TAG_DEFAULT, "ToDeployQuickFixResult end");
170 }
171
ProcessPatchDeployStart(const std::vector<std::string> bundleFilePaths,const BundleInfo & bundleInfo,std::unordered_map<std::string,AppQuickFix> & infos)172 ErrCode QuickFixDeployer::ProcessPatchDeployStart(
173 const std::vector<std::string> bundleFilePaths,
174 const BundleInfo &bundleInfo,
175 std::unordered_map<std::string, AppQuickFix> &infos)
176 {
177 LOG_I(BMS_TAG_DEFAULT, "ProcessPatchDeployStart start");
178 if (infos.empty()) {
179 LOG_E(BMS_TAG_DEFAULT, "error: appQuickFix infos is empty");
180 return ERR_BUNDLEMANAGER_QUICK_FIX_PROFILE_PARSE_FAILED;
181 }
182 QuickFixChecker checker;
183 // check multiple cpuAbi and native library path
184 ErrCode ret = checker.CheckMultiNativeSo(infos);
185 if (ret != ERR_OK) {
186 LOG_E(BMS_TAG_DEFAULT, "ProcessPatchDeployStart check native so failed");
187 return ret;
188 }
189 // parse signature info
190 std::vector<Security::Verify::HapVerifyResult> hapVerifyRes;
191 ret = checker.CheckMultipleHqfsSignInfo(bundleFilePaths, hapVerifyRes);
192 if (ret != ERR_OK) {
193 LOG_E(BMS_TAG_DEFAULT, "ProcessPatchDeployStart check check multiple hqfs signInfo failed");
194 return ret;
195 }
196 if (hapVerifyRes.empty()) {
197 LOG_E(BMS_TAG_DEFAULT, "error: appQuickFix hapVerifyRes is empty");
198 return ERR_APPEXECFWK_INSTALL_FAILED_INCOMPATIBLE_SIGNATURE;
199 }
200 const auto &provisionInfo = hapVerifyRes[0].GetProvisionInfo();
201 const AppQuickFix &appQuickFix = infos.begin()->second;
202 // check with installed bundle, signature info, bundleName, versionCode
203 ret = checker.CheckPatchWithInstalledBundle(appQuickFix, bundleInfo, provisionInfo);
204 if (ret != ERR_OK) {
205 LOG_E(BMS_TAG_DEFAULT, "check AppQuickFixInfos with installed bundle failed, errcode : %{public}d", ret);
206 return ret;
207 }
208 appDistributionType_ = checker.GetAppDistributionType(provisionInfo.distributionType);
209 LOG_I(BMS_TAG_DEFAULT, "ProcessPatchDeployStart end");
210 return ERR_OK;
211 }
212
ProcessHotReloadDeployStart(const BundleInfo & bundleInfo,const AppQuickFix & appQuickFix)213 ErrCode QuickFixDeployer::ProcessHotReloadDeployStart(
214 const BundleInfo &bundleInfo,
215 const AppQuickFix &appQuickFix)
216 {
217 LOG_I(BMS_TAG_DEFAULT, "ProcessHotReloadDeployStart start");
218 QuickFixChecker checker;
219 ErrCode ret = checker.CheckHotReloadWithInstalledBundle(appQuickFix, bundleInfo);
220 if (ret != ERR_OK) {
221 LOG_E(BMS_TAG_DEFAULT, "check AppQuickFixInfos with installed bundle failed");
222 return ret;
223 }
224 LOG_I(BMS_TAG_DEFAULT, "ProcessHotReloadDeployStart end");
225 return ERR_OK;
226 }
227
ToDeployEndStatus(InnerAppQuickFix & newInnerAppQuickFix,const InnerAppQuickFix & oldInnerAppQuickFix)228 ErrCode QuickFixDeployer::ToDeployEndStatus(InnerAppQuickFix &newInnerAppQuickFix,
229 const InnerAppQuickFix &oldInnerAppQuickFix)
230 {
231 LOG_I(BMS_TAG_DEFAULT, "ToDeployEndStatus start");
232 if ((GetQuickFixDataMgr() != ERR_OK)) {
233 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
234 }
235 // create patch path
236 AppQuickFix newQuickFix = newInnerAppQuickFix.GetAppQuickFix();
237 std::string newPatchPath;
238 ScopeGuard guardRemovePatchPath([&newPatchPath] {
239 InstalldClient::GetInstance()->RemoveDir(newPatchPath);
240 });
241 ErrCode ret = ERR_OK;
242 if (newQuickFix.deployingAppqfInfo.type == QuickFixType::PATCH) {
243 // extract diff files and apply diff patch
244 ret = ProcessPatchDeployEnd(newQuickFix, newPatchPath);
245 } else if (newQuickFix.deployingAppqfInfo.type == QuickFixType::HOT_RELOAD) {
246 ret = ProcessHotReloadDeployEnd(newQuickFix, newPatchPath);
247 } else {
248 LOG_E(BMS_TAG_DEFAULT, "error: unknown QuickFixType");
249 return ERR_BUNDLEMANAGER_QUICK_FIX_PROFILE_PARSE_FAILED;
250 }
251 if (ret != ERR_OK) {
252 LOG_E(BMS_TAG_DEFAULT, "Process Patch or HotReload DeployEnd failed, bundleName:%{public}s",
253 newQuickFix.bundleName.c_str());
254 return ret;
255 }
256
257 // if so files exist, library path add patch_versionCode;
258 // if so files not exist, modify library path to empty.
259 ProcessNativeLibraryPath(newPatchPath, newInnerAppQuickFix);
260
261 // move hqf files to new patch path
262 ret = MoveHqfFiles(newInnerAppQuickFix, newPatchPath);
263 if (ret != ERR_OK) {
264 LOG_E(BMS_TAG_DEFAULT, "error MoveHqfFiles failed, bundleName: %{public}s", newQuickFix.bundleName.c_str());
265 return ret;
266 }
267 ret = VerifyCodeSignatureForHqf(newInnerAppQuickFix, newPatchPath);
268 if (ret != ERR_OK) {
269 LOG_E(BMS_TAG_DEFAULT, "verify failed bundleName: %{public}s", newQuickFix.bundleName.c_str());
270 return ret;
271 }
272 // save and update status DEPLOY_END
273 ret = SaveAppQuickFix(newInnerAppQuickFix);
274 if (ret != ERR_OK) {
275 return ret;
276 }
277 ToDeployQuickFixResult(newQuickFix);
278 ret = SaveToInnerBundleInfo(newInnerAppQuickFix);
279 if (ret != ERR_OK) {
280 LOG_E(BMS_TAG_DEFAULT, "error: bundleName %{public}s update failed due to innerBundleInfo failed",
281 newQuickFix.bundleName.c_str());
282 return ret;
283 }
284 guardRemovePatchPath.Dismiss();
285 LOG_I(BMS_TAG_DEFAULT, "ToDeployEndStatus end");
286 return ERR_OK;
287 }
288
ProcessNativeLibraryPath(const std::string & patchPath,InnerAppQuickFix & innerAppQuickFix)289 void QuickFixDeployer::ProcessNativeLibraryPath(const std::string &patchPath, InnerAppQuickFix &innerAppQuickFix)
290 {
291 AppQuickFix appQuickFix = innerAppQuickFix.GetAppQuickFix();
292 if (!appQuickFix.deployingAppqfInfo.nativeLibraryPath.empty()) {
293 std::string nativeLibraryPath = appQuickFix.deployingAppqfInfo.nativeLibraryPath;
294 ProcessNativeLibraryPath(patchPath, innerAppQuickFix, nativeLibraryPath);
295 appQuickFix.deployingAppqfInfo.nativeLibraryPath = nativeLibraryPath;
296 }
297
298 for (auto &hqfInfo : appQuickFix.deployingAppqfInfo.hqfInfos) {
299 if (!hqfInfo.nativeLibraryPath.empty()) {
300 std::string nativeLibraryPath = hqfInfo.nativeLibraryPath;
301 ProcessNativeLibraryPath(patchPath, innerAppQuickFix, nativeLibraryPath);
302 hqfInfo.nativeLibraryPath = nativeLibraryPath;
303 }
304 }
305
306 if (appQuickFix.deployingAppqfInfo.nativeLibraryPath.empty() && !targetPath_.empty()) {
307 LOG_I(BMS_TAG_DEFAULT, "nativeLibraryPath is empty, set nativeLibraryPath to targetPath");
308 appQuickFix.deployingAppqfInfo.nativeLibraryPath = PATCH_DIR + targetPath_;
309 }
310
311 innerAppQuickFix.SetAppQuickFix(appQuickFix);
312 }
313
ProcessNativeLibraryPath(const std::string & patchPath,const InnerAppQuickFix & innerAppQuickFix,std::string & nativeLibraryPath)314 void QuickFixDeployer::ProcessNativeLibraryPath(
315 const std::string &patchPath, const InnerAppQuickFix &innerAppQuickFix, std::string &nativeLibraryPath)
316 {
317 bool isSoExist = false;
318 auto libraryPath = nativeLibraryPath;
319 std::string soPath = patchPath + ServiceConstants::PATH_SEPARATOR + libraryPath;
320 if (InstalldClient::GetInstance()->IsExistDir(soPath, isSoExist) != ERR_OK) {
321 LOG_E(BMS_TAG_DEFAULT, "ProcessNativeLibraryPath IsExistDir(%{public}s) failed", soPath.c_str());
322 return;
323 }
324
325 AppQuickFix appQuickFix = innerAppQuickFix.GetAppQuickFix();
326 if (isSoExist) {
327 if (!targetPath_.empty()) {
328 nativeLibraryPath = PATCH_DIR + targetPath_ + ServiceConstants::PATH_SEPARATOR + libraryPath;
329 } else {
330 nativeLibraryPath =
331 ServiceConstants::PATCH_PATH + std::to_string(appQuickFix.deployingAppqfInfo.versionCode) +
332 ServiceConstants::PATH_SEPARATOR + libraryPath;
333 }
334 } else {
335 LOG_I(BMS_TAG_DEFAULT, "So(%{public}s) is not exist and set nativeLibraryPath(%{public}s) empty",
336 soPath.c_str(), nativeLibraryPath.c_str());
337 nativeLibraryPath.clear();
338 }
339 }
340
ProcessPatchDeployEnd(const AppQuickFix & appQuickFix,std::string & patchPath)341 ErrCode QuickFixDeployer::ProcessPatchDeployEnd(const AppQuickFix &appQuickFix, std::string &patchPath)
342 {
343 if (!targetPath_.empty()) {
344 patchPath = Constants::BUNDLE_CODE_DIR + ServiceConstants::PATH_SEPARATOR + appQuickFix.bundleName
345 + ServiceConstants::PATH_SEPARATOR + PATCH_DIR + targetPath_;
346 } else {
347 patchPath = Constants::BUNDLE_CODE_DIR + ServiceConstants::PATH_SEPARATOR + appQuickFix.bundleName
348 + ServiceConstants::PATH_SEPARATOR + ServiceConstants::PATCH_PATH
349 + std::to_string(appQuickFix.deployingAppqfInfo.versionCode);
350 }
351 if (InstalldClient::GetInstance()->CreateBundleDir(patchPath) != ERR_OK) {
352 LOG_E(BMS_TAG_DEFAULT, "error: creat patch path failed");
353 return ERR_BUNDLEMANAGER_QUICK_FIX_CREATE_PATCH_PATH_FAILED;
354 }
355 BundleInfo bundleInfo;
356 ErrCode ret = GetBundleInfo(appQuickFix.bundleName, bundleInfo);
357 if (ret != ERR_OK) {
358 return ret;
359 }
360 if (ExtractQuickFixResFile(appQuickFix, bundleInfo) != ERR_OK) {
361 LOG_E(BMS_TAG_DEFAULT, "error: ExtractQuickFixResFile failed");
362 }
363 if (isDebug_ && (bundleInfo.applicationInfo.appProvisionType == Constants::APP_PROVISION_TYPE_DEBUG)) {
364 return ExtractQuickFixSoFile(appQuickFix, patchPath, bundleInfo);
365 }
366 return ERR_OK;
367 }
368
ProcessHotReloadDeployEnd(const AppQuickFix & appQuickFix,std::string & patchPath)369 ErrCode QuickFixDeployer::ProcessHotReloadDeployEnd(const AppQuickFix &appQuickFix, std::string &patchPath)
370 {
371 patchPath = Constants::BUNDLE_CODE_DIR + ServiceConstants::PATH_SEPARATOR + appQuickFix.bundleName +
372 ServiceConstants::PATH_SEPARATOR + ServiceConstants::HOT_RELOAD_PATH +
373 std::to_string(appQuickFix.deployingAppqfInfo.versionCode);
374 ErrCode ret = InstalldClient::GetInstance()->CreateBundleDir(patchPath);
375 if (ret != ERR_OK) {
376 LOG_E(BMS_TAG_DEFAULT, "error: creat hotreload path failed, errcode %{public}d", ret);
377 return ERR_BUNDLEMANAGER_QUICK_FIX_CREATE_PATCH_PATH_FAILED;
378 }
379 return ERR_OK;
380 }
381
ParseAndCheckAppQuickFixInfos(const std::vector<std::string> & bundleFilePaths,std::unordered_map<std::string,AppQuickFix> & infos)382 ErrCode QuickFixDeployer::ParseAndCheckAppQuickFixInfos(
383 const std::vector<std::string> &bundleFilePaths,
384 std::unordered_map<std::string, AppQuickFix> &infos)
385 {
386 // parse hqf file to AppQuickFix
387 PatchParser patchParser;
388 ErrCode ret = patchParser.ParsePatchInfo(bundleFilePaths, infos);
389 if ((ret != ERR_OK) || infos.empty()) {
390 LOG_E(BMS_TAG_DEFAULT, "parse AppQuickFixFiles failed, errcode %{public}d", ret);
391 return ERR_BUNDLEMANAGER_QUICK_FIX_PROFILE_PARSE_FAILED;
392 }
393
394 ResetNativeSoAttrs(infos);
395 QuickFixChecker checker;
396 // check multiple AppQuickFix
397 ret = checker.CheckAppQuickFixInfos(infos);
398 if (ret != ERR_OK) {
399 LOG_E(BMS_TAG_DEFAULT, "check AppQuickFixInfos failed");
400 return ret;
401 }
402 const QuickFixType &quickFixType = infos.begin()->second.deployingAppqfInfo.type;
403 if (quickFixType == QuickFixType::UNKNOWN) {
404 LOG_E(BMS_TAG_DEFAULT, "error unknown quick fix type");
405 return ERR_BUNDLEMANAGER_QUICK_FIX_UNKNOWN_QUICK_FIX_TYPE;
406 }
407 // hqf file path
408 for (auto iter = infos.begin(); iter != infos.end(); ++iter) {
409 if (!iter->second.deployingAppqfInfo.hqfInfos.empty()) {
410 iter->second.deployingAppqfInfo.hqfInfos[0].hqfFilePath = iter->first;
411 } else {
412 return ERR_BUNDLEMANAGER_QUICK_FIX_PROFILE_PARSE_FAILED;
413 }
414 }
415 return ERR_OK;
416 }
417
ResetNativeSoAttrs(std::unordered_map<std::string,AppQuickFix> & infos)418 void QuickFixDeployer::ResetNativeSoAttrs(std::unordered_map<std::string, AppQuickFix> &infos)
419 {
420 for (auto &info : infos) {
421 ResetNativeSoAttrs(info.second);
422 }
423 }
424
ResetNativeSoAttrs(AppQuickFix & appQuickFix)425 void QuickFixDeployer::ResetNativeSoAttrs(AppQuickFix &appQuickFix)
426 {
427 auto &appqfInfo = appQuickFix.deployingAppqfInfo;
428 if (appqfInfo.hqfInfos.size() != 1) {
429 LOG_W(BMS_TAG_DEFAULT, "The number of hqfInfos is not one");
430 return;
431 }
432
433 bool isLibIsolated = IsLibIsolated(appQuickFix.bundleName, appqfInfo.hqfInfos[0].moduleName);
434 if (!isLibIsolated) {
435 LOG_W(BMS_TAG_DEFAULT, "Lib is not isolated");
436 return;
437 }
438
439 appqfInfo.hqfInfos[0].cpuAbi = appqfInfo.cpuAbi;
440 appqfInfo.hqfInfos[0].nativeLibraryPath =
441 appqfInfo.hqfInfos[0].moduleName + ServiceConstants::PATH_SEPARATOR + appqfInfo.nativeLibraryPath;
442 appqfInfo.nativeLibraryPath.clear();
443 }
444
IsLibIsolated(const std::string & bundleName,const std::string & moduleName)445 bool QuickFixDeployer::IsLibIsolated(
446 const std::string &bundleName, const std::string &moduleName)
447 {
448 InnerBundleInfo innerBundleInfo;
449 if (!FetchInnerBundleInfo(bundleName, innerBundleInfo)) {
450 LOG_E(BMS_TAG_DEFAULT, "Fetch bundleInfo(%{public}s) failed", bundleName.c_str());
451 return false;
452 }
453
454 return innerBundleInfo.IsLibIsolated(moduleName);
455 }
456
FetchInnerBundleInfo(const std::string & bundleName,InnerBundleInfo & innerBundleInfo)457 bool QuickFixDeployer::FetchInnerBundleInfo(
458 const std::string &bundleName, InnerBundleInfo &innerBundleInfo)
459 {
460 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
461 if (dataMgr == nullptr) {
462 LOG_E(BMS_TAG_DEFAULT, "error dataMgr is nullptr");
463 return false;
464 }
465
466 if (!dataMgr->FetchInnerBundleInfo(bundleName, innerBundleInfo)) {
467 LOG_E(BMS_TAG_DEFAULT, "Fetch bundleInfo(%{public}s) failed", bundleName.c_str());
468 return false;
469 }
470
471 return true;
472 }
473
FetchPatchNativeSoAttrs(const AppqfInfo & appqfInfo,const HqfInfo hqfInfo,bool isLibIsolated,std::string & nativeLibraryPath,std::string & cpuAbi)474 bool QuickFixDeployer::FetchPatchNativeSoAttrs(const AppqfInfo &appqfInfo,
475 const HqfInfo hqfInfo, bool isLibIsolated, std::string &nativeLibraryPath, std::string &cpuAbi)
476 {
477 if (isLibIsolated) {
478 nativeLibraryPath = hqfInfo.nativeLibraryPath;
479 cpuAbi = hqfInfo.cpuAbi;
480 } else {
481 nativeLibraryPath = appqfInfo.nativeLibraryPath;
482 cpuAbi = appqfInfo.cpuAbi;
483 }
484
485 return !nativeLibraryPath.empty();
486 }
487
HasNativeSoInBundle(const AppQuickFix & appQuickFix)488 bool QuickFixDeployer::HasNativeSoInBundle(const AppQuickFix &appQuickFix)
489 {
490 if (!appQuickFix.deployingAppqfInfo.nativeLibraryPath.empty()) {
491 return true;
492 }
493
494 for (const auto &hqfInfo : appQuickFix.deployingAppqfInfo.hqfInfos) {
495 if (!hqfInfo.nativeLibraryPath.empty()) {
496 return true;
497 }
498 }
499
500 return false;
501 }
502
GetBundleInfo(const std::string & bundleName,BundleInfo & bundleInfo)503 ErrCode QuickFixDeployer::GetBundleInfo(const std::string &bundleName, BundleInfo &bundleInfo)
504 {
505 std::shared_ptr<BundleMgrService> bms = DelayedSingleton<BundleMgrService>::GetInstance();
506 if (bms == nullptr) {
507 LOG_E(BMS_TAG_DEFAULT, "error: bms is nullptr");
508 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
509 }
510 std::shared_ptr<BundleDataMgr> dataMgr = bms->GetDataMgr();
511 if (dataMgr == nullptr) {
512 LOG_E(BMS_TAG_DEFAULT, "error: dataMgr is nullptr");
513 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
514 }
515 // check bundleName is exists
516 if (!dataMgr->GetBundleInfo(bundleName, BundleFlag::GET_BUNDLE_DEFAULT,
517 bundleInfo, Constants::ANY_USERID)) {
518 LOG_E(BMS_TAG_DEFAULT, "error: GetBundleInfo failed, bundleName: %{public}s not exist", bundleName.c_str());
519 return ERR_BUNDLEMANAGER_QUICK_FIX_BUNDLE_NAME_NOT_EXIST;
520 }
521 return ERR_OK;
522 }
523
ToInnerAppQuickFix(const std::unordered_map<std::string,AppQuickFix> infos,const InnerAppQuickFix & oldInnerAppQuickFix,InnerAppQuickFix & newInnerAppQuickFix)524 ErrCode QuickFixDeployer::ToInnerAppQuickFix(const std::unordered_map<std::string, AppQuickFix> infos,
525 const InnerAppQuickFix &oldInnerAppQuickFix, InnerAppQuickFix &newInnerAppQuickFix)
526 {
527 LOG_D(BMS_TAG_DEFAULT, "ToInnerAppQuickFix start");
528 if (infos.empty()) {
529 LOG_E(BMS_TAG_DEFAULT, "error: appQuickFix is empty");
530 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
531 }
532 AppQuickFix oldAppQuickFix = oldInnerAppQuickFix.GetAppQuickFix();
533 AppQuickFix appQuickFix = infos.begin()->second;
534 // copy deployed app qf info
535 appQuickFix.deployedAppqfInfo = oldAppQuickFix.deployedAppqfInfo;
536 newInnerAppQuickFix.SetAppQuickFix(appQuickFix);
537 QuickFixMark mark;
538 mark.bundleName = appQuickFix.bundleName;
539 mark.status = QuickFixStatus::DEPLOY_START;
540 for (auto iter = infos.begin(); iter != infos.end(); ++iter) {
541 const auto &quickFix = iter->second;
542 // hqfInfos will not be empty, it has been judged before.
543 const std::string &moduleName = quickFix.deployingAppqfInfo.hqfInfos[0].moduleName;
544 if (!newInnerAppQuickFix.AddHqfInfo(quickFix)) {
545 LOG_E(BMS_TAG_DEFAULT, "error: appQuickFix add hqf moduleName: %{public}s failed", moduleName.c_str());
546 return ERR_BUNDLEMANAGER_QUICK_FIX_ADD_HQF_FAILED;
547 }
548 }
549 newInnerAppQuickFix.SetQuickFixMark(mark);
550 LOG_D(BMS_TAG_DEFAULT, "ToInnerAppQuickFix end");
551 return ERR_OK;
552 }
553
CheckPatchVersionCode(const AppQuickFix & newAppQuickFix,const AppQuickFix & oldAppQuickFix)554 ErrCode QuickFixDeployer::CheckPatchVersionCode(
555 const AppQuickFix &newAppQuickFix,
556 const AppQuickFix &oldAppQuickFix)
557 {
558 const AppqfInfo &newInfo = newAppQuickFix.deployingAppqfInfo;
559 const AppqfInfo &oldInfoDeployed = oldAppQuickFix.deployedAppqfInfo;
560 const AppqfInfo &oldInfoDeploying = oldAppQuickFix.deployingAppqfInfo;
561 if ((newInfo.versionCode > oldInfoDeployed.versionCode) &&
562 (newInfo.versionCode > oldInfoDeploying.versionCode)) {
563 return ERR_OK;
564 }
565 LOG_E(BMS_TAG_DEFAULT, "CheckPatchVersionCode failed, version code should be greater than the original");
566 return ERR_BUNDLEMANAGER_QUICK_FIX_VERSION_CODE_ERROR;
567 }
568
SaveAppQuickFix(const InnerAppQuickFix & innerAppQuickFix)569 ErrCode QuickFixDeployer::SaveAppQuickFix(const InnerAppQuickFix &innerAppQuickFix)
570 {
571 if ((GetQuickFixDataMgr() != ERR_OK)) {
572 LOG_E(BMS_TAG_DEFAULT, "error: quickFixDataMgr_ is nullptr");
573 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
574 }
575 if (!quickFixDataMgr_->SaveInnerAppQuickFix(innerAppQuickFix)) {
576 LOG_E(BMS_TAG_DEFAULT, "bundleName: %{public}s, inner app quick fix save failed",
577 innerAppQuickFix.GetAppQuickFix().bundleName.c_str());
578 return ERR_BUNDLEMANAGER_QUICK_FIX_SAVE_APP_QUICK_FIX_FAILED;
579 }
580 return ERR_OK;
581 }
582
MoveHqfFiles(InnerAppQuickFix & innerAppQuickFix,const std::string & targetPath)583 ErrCode QuickFixDeployer::MoveHqfFiles(InnerAppQuickFix &innerAppQuickFix, const std::string &targetPath)
584 {
585 LOG_D(BMS_TAG_DEFAULT, "MoveHqfFiles start");
586 if (targetPath.empty() || (GetQuickFixDataMgr() != ERR_OK)) {
587 LOG_E(BMS_TAG_DEFAULT, "MoveHqfFiles params error");
588 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
589 }
590 QuickFixMark mark = innerAppQuickFix.GetQuickFixMark();
591 AppQuickFix appQuickFix = innerAppQuickFix.GetAppQuickFix();
592 std::string path = targetPath;
593 if (path.back() != ServiceConstants::FILE_SEPARATOR_CHAR) {
594 path.push_back(ServiceConstants::FILE_SEPARATOR_CHAR);
595 }
596 for (HqfInfo &info : appQuickFix.deployingAppqfInfo.hqfInfos) {
597 if (info.hqfFilePath.empty()) {
598 LOG_E(BMS_TAG_DEFAULT, "error hapFilePath is empty");
599 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
600 }
601 std::string realPath = path + info.moduleName + ServiceConstants::QUICK_FIX_FILE_SUFFIX;
602 ErrCode ret = InstalldClient::GetInstance()->CopyFile(info.hqfFilePath, realPath);
603 if (ret != ERR_OK) {
604 LOG_E(BMS_TAG_DEFAULT, "error CopyFile failed, errcode: %{public}d", ret);
605 return ERR_BUNDLEMANAGER_QUICK_FIX_MOVE_PATCH_FILE_FAILED;
606 }
607 info.hqfFilePath = realPath;
608 }
609 mark.status = QuickFixStatus::DEPLOY_END;
610 innerAppQuickFix.SetQuickFixMark(mark);
611 innerAppQuickFix.SetAppQuickFix(appQuickFix);
612 LOG_D(BMS_TAG_DEFAULT, "MoveHqfFiles end");
613 return ERR_OK;
614 }
615
GetDeployQuickFixResult() const616 DeployQuickFixResult QuickFixDeployer::GetDeployQuickFixResult() const
617 {
618 return deployQuickFixResult_;
619 }
620
GetQuickFixDataMgr()621 ErrCode QuickFixDeployer::GetQuickFixDataMgr()
622 {
623 if (quickFixDataMgr_ == nullptr) {
624 quickFixDataMgr_ = DelayedSingleton<QuickFixDataMgr>::GetInstance();
625 if (quickFixDataMgr_ == nullptr) {
626 LOG_E(BMS_TAG_DEFAULT, "error: quickFixDataMgr_ is nullptr");
627 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
628 }
629 }
630 return ERR_OK;
631 }
632
SaveToInnerBundleInfo(const InnerAppQuickFix & newInnerAppQuickFix)633 ErrCode QuickFixDeployer::SaveToInnerBundleInfo(const InnerAppQuickFix &newInnerAppQuickFix)
634 {
635 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
636 if (dataMgr == nullptr) {
637 LOG_E(BMS_TAG_DEFAULT, "error dataMgr is nullptr");
638 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
639 }
640 const std::string &bundleName = newInnerAppQuickFix.GetAppQuickFix().bundleName;
641 InnerBundleInfo innerBundleInfo;
642 // obtain innerBundleInfo and enableGuard used to enable bundle which is under disable status
643 if (!dataMgr->GetInnerBundleInfo(bundleName, innerBundleInfo)) {
644 LOG_E(BMS_TAG_DEFAULT, "cannot obtain the innerbundleInfo from data mgr");
645 return ERR_BUNDLEMANAGER_QUICK_FIX_NOT_EXISTED_BUNDLE_INFO;
646 }
647 ScopeGuard enableGuard([&bundleName, &dataMgr] { dataMgr->EnableBundle(bundleName); });
648 AppQuickFix appQuickFix = newInnerAppQuickFix.GetAppQuickFix();
649 appQuickFix.deployedAppqfInfo = innerBundleInfo.GetAppQuickFix().deployedAppqfInfo;
650 // add apply quick fix frequency
651 innerBundleInfo.AddApplyQuickFixFrequency();
652 innerBundleInfo.SetAppQuickFix(appQuickFix);
653 innerBundleInfo.SetBundleStatus(InnerBundleInfo::BundleStatus::ENABLED);
654 if (!dataMgr->UpdateQuickFixInnerBundleInfo(bundleName, innerBundleInfo)) {
655 LOG_E(BMS_TAG_DEFAULT, "update quickfix innerbundleInfo failed");
656 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
657 }
658 // send quick fix data
659 SendQuickFixSystemEvent(innerBundleInfo);
660 return ERR_OK;
661 }
662
ProcessBundleFilePaths(const std::vector<std::string> & bundleFilePaths,std::vector<std::string> & realFilePaths)663 ErrCode QuickFixDeployer::ProcessBundleFilePaths(const std::vector<std::string> &bundleFilePaths,
664 std::vector<std::string> &realFilePaths)
665 {
666 for (const auto &path : bundleFilePaths) {
667 if (path.find(ServiceConstants::RELATIVE_PATH) != std::string::npos) {
668 LOG_E(BMS_TAG_DEFAULT, "ProcessBundleFilePaths path is illegal");
669 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
670 }
671 if (path.find(ServiceConstants::HAP_COPY_PATH + ServiceConstants::PATH_SEPARATOR +
672 ServiceConstants::SECURITY_QUICK_FIX_PATH + ServiceConstants::PATH_SEPARATOR) != 0) {
673 LOG_E(BMS_TAG_DEFAULT, "ProcessBundleFilePaths path is illegal");
674 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
675 }
676 }
677 ErrCode ret = BundleUtil::CheckFilePath(bundleFilePaths, realFilePaths);
678 if (ret != ERR_OK) {
679 LOG_E(BMS_TAG_DEFAULT, "ProcessBundleFilePaths CheckFilePath failed");
680 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
681 }
682 for (const auto &path : realFilePaths) {
683 if (!BundleUtil::CheckFileType(path, ServiceConstants::QUICK_FIX_FILE_SUFFIX)) {
684 LOG_E(BMS_TAG_DEFAULT, "ProcessBundleFilePaths CheckFileType failed");
685 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
686 }
687 }
688 return ERR_OK;
689 }
690
SendQuickFixSystemEvent(const InnerBundleInfo & innerBundleInfo)691 void QuickFixDeployer::SendQuickFixSystemEvent(const InnerBundleInfo &innerBundleInfo)
692 {
693 EventInfo sysEventInfo;
694 sysEventInfo.errCode = ERR_OK;
695 sysEventInfo.bundleName = innerBundleInfo.GetBundleName();
696 sysEventInfo.appDistributionType = appDistributionType_;
697 for (const auto &hqfInfo : innerBundleInfo.GetAppQuickFix().deployingAppqfInfo.hqfInfos) {
698 sysEventInfo.filePath.push_back(hqfInfo.hqfFilePath);
699 sysEventInfo.hashValue.push_back(hqfInfo.hapSha256);
700 }
701 sysEventInfo.applyQuickFixFrequency = innerBundleInfo.GetApplyQuickFixFrequency();
702 EventReport::SendBundleSystemEvent(BundleEventType::QUICK_FIX, sysEventInfo);
703 }
704
ExtractQuickFixSoFile(const AppQuickFix & appQuickFix,const std::string & hqfSoPath,const BundleInfo & bundleInfo)705 ErrCode QuickFixDeployer::ExtractQuickFixSoFile(
706 const AppQuickFix &appQuickFix, const std::string &hqfSoPath, const BundleInfo &bundleInfo)
707 {
708 LOG_D(BMS_TAG_DEFAULT, "start, bundleName:%{public}s", appQuickFix.bundleName.c_str());
709 auto &appQfInfo = appQuickFix.deployingAppqfInfo;
710 if (appQfInfo.hqfInfos.empty()) {
711 LOG_E(BMS_TAG_DEFAULT, "hqfInfos is empty");
712 return ERR_BUNDLEMANAGER_QUICK_FIX_PROFILE_PARSE_FAILED;
713 }
714 for (const auto &hqf : appQfInfo.hqfInfos) {
715 auto iter = std::find_if(std::begin(bundleInfo.hapModuleInfos), std::end(bundleInfo.hapModuleInfos),
716 [hqf](const HapModuleInfo &info) {
717 return info.moduleName == hqf.moduleName;
718 });
719 if (iter == bundleInfo.hapModuleInfos.end()) {
720 LOG_W(BMS_TAG_DEFAULT, "moduleName:%{public}s not exist", hqf.moduleName.c_str());
721 continue;
722 }
723
724 std::string libraryPath;
725 std::string cpuAbi;
726 bool isLibIsolated = IsLibIsolated(appQuickFix.bundleName, hqf.moduleName);
727 if (!FetchPatchNativeSoAttrs(appQuickFix.deployingAppqfInfo, hqf, isLibIsolated, libraryPath, cpuAbi)) {
728 LOG_D(BMS_TAG_DEFAULT, "no so file");
729 continue;
730 }
731 std::string soPath = hqfSoPath + ServiceConstants::PATH_SEPARATOR + libraryPath;
732 ExtractParam extractParam;
733 extractParam.extractFileType = ExtractFileType::SO;
734 extractParam.srcPath = hqf.hqfFilePath;
735 extractParam.targetPath = soPath;
736 extractParam.cpuAbi = cpuAbi;
737 if (InstalldClient::GetInstance()->ExtractFiles(extractParam) != ERR_OK) {
738 LOG_W(BMS_TAG_DEFAULT, "moduleName: %{public}s extract so failed", hqf.moduleName.c_str());
739 continue;
740 }
741 }
742 LOG_D(BMS_TAG_DEFAULT, "end");
743 return ERR_OK;
744 }
745
ExtractSoAndApplyDiff(const AppQuickFix & appQuickFix,const BundleInfo & bundleInfo,const std::string & patchPath)746 ErrCode QuickFixDeployer::ExtractSoAndApplyDiff(const AppQuickFix &appQuickFix, const BundleInfo &bundleInfo,
747 const std::string &patchPath)
748 {
749 auto &appQfInfo = appQuickFix.deployingAppqfInfo;
750 for (const auto &hqf : appQfInfo.hqfInfos) {
751 // if hap has no so file then continue
752 std::string tmpSoPath = ServiceConstants::HAP_COPY_PATH + ServiceConstants::PATH_SEPARATOR +
753 appQuickFix.bundleName + ServiceConstants::TMP_SUFFIX + ServiceConstants::LIBS;
754
755 InnerBundleInfo innerBundleInfo;
756 if (!FetchInnerBundleInfo(appQuickFix.bundleName, innerBundleInfo)) {
757 LOG_E(BMS_TAG_DEFAULT, "Fetch bundleInfo(%{public}s) failed", appQuickFix.bundleName.c_str());
758 return ERR_BUNDLEMANAGER_QUICK_FIX_BUNDLE_NAME_NOT_EXIST;
759 }
760 int32_t bundleUid = Constants::INVALID_UID;
761 if (innerBundleInfo.IsEncryptedMoudle(hqf.moduleName)) {
762 InnerBundleUserInfo innerBundleUserInfo;
763 if (!innerBundleInfo.GetInnerBundleUserInfo(Constants::ALL_USERID, innerBundleUserInfo)) {
764 LOG_E(BMS_TAG_DEFAULT, "no user info of bundle %{public}s", appQuickFix.bundleName.c_str());
765 return ERR_BUNDLEMANAGER_QUICK_FIX_BUNDLE_NAME_NOT_EXIST;
766 }
767 bundleUid = innerBundleUserInfo.uid;
768 if (!ExtractEncryptedSoFiles(bundleInfo, hqf.moduleName, bundleUid, tmpSoPath)) {
769 LOG_W(BMS_TAG_DEFAULT, "module:%{public}s has no so file", hqf.moduleName.c_str());
770 continue;
771 }
772 } else {
773 if (!ExtractSoFiles(bundleInfo, hqf.moduleName, tmpSoPath)) {
774 LOG_W(BMS_TAG_DEFAULT, "module:%{public}s has no so file", hqf.moduleName.c_str());
775 continue;
776 }
777 }
778
779 auto result = ProcessApplyDiffPatch(appQuickFix, hqf, tmpSoPath, patchPath, bundleUid);
780 if (result != ERR_OK) {
781 LOG_E(BMS_TAG_DEFAULT, "bundleName: %{public}s Process failed", appQuickFix.bundleName.c_str());
782 return result;
783 }
784 }
785 return ERR_OK;
786 }
787
ExtractSoFiles(const BundleInfo & bundleInfo,const std::string & moduleName,std::string & tmpSoPath)788 bool QuickFixDeployer::ExtractSoFiles(
789 const BundleInfo &bundleInfo,
790 const std::string &moduleName,
791 std::string &tmpSoPath)
792 {
793 auto iter = std::find_if(std::begin(bundleInfo.hapModuleInfos), std::end(bundleInfo.hapModuleInfos),
794 [&moduleName](const HapModuleInfo &info) {
795 return info.moduleName == moduleName;
796 });
797 if (iter == bundleInfo.hapModuleInfos.end()) {
798 return false;
799 }
800 std::string cpuAbi = bundleInfo.applicationInfo.cpuAbi;
801 std::string nativeLibraryPath = bundleInfo.applicationInfo.nativeLibraryPath;
802 if (!iter->nativeLibraryPath.empty()) {
803 cpuAbi = iter->cpuAbi;
804 nativeLibraryPath = iter->nativeLibraryPath;
805 }
806 if (nativeLibraryPath.empty()) {
807 LOG_W(BMS_TAG_DEFAULT, "nativeLibraryPath is empty");
808 return false;
809 }
810
811 tmpSoPath = (tmpSoPath.back() == ServiceConstants::PATH_SEPARATOR[0]) ? (tmpSoPath + moduleName) :
812 (tmpSoPath + ServiceConstants::PATH_SEPARATOR + moduleName);
813 ExtractParam extractParam;
814 extractParam.extractFileType = ExtractFileType::SO;
815 extractParam.srcPath = iter->hapPath;
816 extractParam.targetPath = tmpSoPath;
817 extractParam.cpuAbi = cpuAbi;
818 if (InstalldClient::GetInstance()->ExtractFiles(extractParam) != ERR_OK) {
819 LOG_W(BMS_TAG_DEFAULT, "bundleName: %{public}s moduleName: %{public}s extract so failed, ",
820 bundleInfo.name.c_str(), moduleName.c_str());
821 return false;
822 }
823 return true;
824 }
825
ProcessApplyDiffPatch(const AppQuickFix & appQuickFix,const HqfInfo & hqf,const std::string & oldSoPath,const std::string & patchPath,int32_t uid)826 ErrCode QuickFixDeployer::ProcessApplyDiffPatch(const AppQuickFix &appQuickFix, const HqfInfo &hqf,
827 const std::string &oldSoPath, const std::string &patchPath, int32_t uid)
828 {
829 std::string libraryPath;
830 std::string cpuAbi;
831 bool isLibIsolated = IsLibIsolated(appQuickFix.bundleName, hqf.moduleName);
832 if (!FetchPatchNativeSoAttrs(appQuickFix.deployingAppqfInfo, hqf, isLibIsolated, libraryPath, cpuAbi)) {
833 return ERR_OK;
834 }
835 // extract diff so, diff so path
836 std::string diffFilePath = ServiceConstants::HAP_COPY_PATH + ServiceConstants::PATH_SEPARATOR +
837 appQuickFix.bundleName + ServiceConstants::TMP_SUFFIX;
838 ScopeGuard guardRemoveDiffPath([diffFilePath] { InstalldClient::GetInstance()->RemoveDir(diffFilePath); });
839 // extract diff so to targetPath
840 auto ret = InstalldClient::GetInstance()->ExtractDiffFiles(hqf.hqfFilePath, diffFilePath, cpuAbi);
841 if (ret != ERR_OK) {
842 LOG_E(BMS_TAG_DEFAULT, "error: ExtractDiffFiles failed errcode :%{public}d", ret);
843 return ERR_BUNDLEMANAGER_QUICK_FIX_EXTRACT_DIFF_FILES_FAILED;
844 }
845 // apply diff patch
846 std::string newSoPath = patchPath + ServiceConstants::PATH_SEPARATOR + libraryPath;
847 ret = InstalldClient::GetInstance()->ApplyDiffPatch(oldSoPath, diffFilePath, newSoPath, uid);
848 if (ret != ERR_OK) {
849 LOG_E(BMS_TAG_DEFAULT, "ApplyDiffPatch failed, bundleName:%{public}s, errcode: %{public}d",
850 appQuickFix.bundleName.c_str(), ret);
851 return ERR_BUNDLEMANAGER_QUICK_FIX_APPLY_DIFF_PATCH_FAILED;
852 }
853 return ERR_OK;
854 }
855
ExtractEncryptedSoFiles(const BundleInfo & bundleInfo,const std::string & moduleName,int32_t uid,std::string & tmpSoPath)856 bool QuickFixDeployer::ExtractEncryptedSoFiles(const BundleInfo &bundleInfo, const std::string &moduleName,
857 int32_t uid, std::string &tmpSoPath)
858 {
859 LOG_D(BMS_TAG_DEFAULT, "start to extract decoded so files to tmp path");
860 auto iter = std::find_if(std::begin(bundleInfo.hapModuleInfos), std::end(bundleInfo.hapModuleInfos),
861 [&moduleName](const HapModuleInfo &info) {
862 return info.moduleName == moduleName;
863 });
864 if (iter == bundleInfo.hapModuleInfos.end()) {
865 return false;
866 }
867 std::string cpuAbi = bundleInfo.applicationInfo.cpuAbi;
868 std::string nativeLibraryPath = bundleInfo.applicationInfo.nativeLibraryPath;
869 if (!iter->nativeLibraryPath.empty()) {
870 cpuAbi = iter->cpuAbi;
871 nativeLibraryPath = iter->nativeLibraryPath;
872 }
873 if (nativeLibraryPath.empty()) {
874 LOG_W(BMS_TAG_DEFAULT, "nativeLibraryPath is empty");
875 return false;
876 }
877 std::string hapPath = iter->hapPath;
878 std::string realSoFilesPath;
879 if (iter->compressNativeLibs) {
880 realSoFilesPath.append(Constants::BUNDLE_CODE_DIR).append(ServiceConstants::PATH_SEPARATOR)
881 .append(bundleInfo.name).append(ServiceConstants::PATH_SEPARATOR).append(nativeLibraryPath)
882 .append(ServiceConstants::PATH_SEPARATOR);
883 }
884 tmpSoPath = (tmpSoPath.back() == ServiceConstants::PATH_SEPARATOR[0]) ? (tmpSoPath + moduleName) :
885 (tmpSoPath + ServiceConstants::PATH_SEPARATOR + moduleName + ServiceConstants::PATH_SEPARATOR);
886 LOG_D(BMS_TAG_DEFAULT, "real so path is %{public}s tmpSoPath is %{public}s",
887 realSoFilesPath.c_str(), tmpSoPath.c_str());
888 return InstalldClient::GetInstance()->ExtractEncryptedSoFiles(hapPath, realSoFilesPath, cpuAbi, tmpSoPath, uid) ==
889 ERR_OK;
890 }
891
PrepareCodeSignatureParam(const AppQuickFix & appQuickFix,const HqfInfo & hqf,const BundleInfo & bundleInfo,const std::string & hqfSoPath,CodeSignatureParam & codeSignatureParam)892 void QuickFixDeployer::PrepareCodeSignatureParam(const AppQuickFix &appQuickFix, const HqfInfo &hqf,
893 const BundleInfo &bundleInfo, const std::string &hqfSoPath, CodeSignatureParam &codeSignatureParam)
894 {
895 std::string libraryPath;
896 std::string cpuAbi;
897 bool isLibIsolated = IsLibIsolated(appQuickFix.bundleName, hqf.moduleName);
898 if (!FetchPatchNativeSoAttrs(appQuickFix.deployingAppqfInfo, hqf, isLibIsolated, libraryPath, cpuAbi)) {
899 LOG_I(BMS_TAG_DEFAULT, "no so file");
900 codeSignatureParam.targetSoPath = "";
901 } else {
902 std::string soPath = hqfSoPath.substr(0, hqfSoPath.rfind(ServiceConstants::PATH_SEPARATOR) + 1) + libraryPath;
903 codeSignatureParam.targetSoPath = soPath;
904 }
905 codeSignatureParam.cpuAbi = cpuAbi;
906 codeSignatureParam.modulePath = hqf.hqfFilePath;
907 codeSignatureParam.isEnterpriseBundle =
908 (appDistributionType_ == Constants::APP_DISTRIBUTION_TYPE_ENTERPRISE_NORMAL ||
909 appDistributionType_ == Constants::APP_DISTRIBUTION_TYPE_ENTERPRISE_MDM ||
910 appDistributionType_ == Constants::APP_DISTRIBUTION_TYPE_ENTERPRISE);
911 codeSignatureParam.appIdentifier = DEBUG_APP_IDENTIFIER;
912 codeSignatureParam.isCompileSdkOpenHarmony =
913 bundleInfo.applicationInfo.compileSdkType == COMPILE_SDK_TYPE_OPEN_HARMONY;
914 // if not debug, so.diff contained, do not need to verify code signature for so
915 if (!isDebug_ || bundleInfo.applicationInfo.appProvisionType != Constants::APP_PROVISION_TYPE_DEBUG) {
916 codeSignatureParam.targetSoPath = "";
917 }
918 }
919
VerifyCodeSignatureForHqf(const InnerAppQuickFix & innerAppQuickFix,const std::string & hqfSoPath)920 ErrCode QuickFixDeployer::VerifyCodeSignatureForHqf(
921 const InnerAppQuickFix &innerAppQuickFix, const std::string &hqfSoPath)
922 {
923 AppQuickFix appQuickFix = innerAppQuickFix.GetAppQuickFix();
924 LOG_D(BMS_TAG_DEFAULT, "start, bundleName:%{public}s", appQuickFix.bundleName.c_str());
925 BundleInfo bundleInfo;
926 if (GetBundleInfo(appQuickFix.bundleName, bundleInfo) != ERR_OK) {
927 return ERR_BUNDLEMANAGER_QUICK_FIX_NOT_EXISTED_BUNDLE_INFO;
928 }
929 auto &appQfInfo = appQuickFix.deployingAppqfInfo;
930 if (appQfInfo.hqfInfos.empty()) {
931 LOG_E(BMS_TAG_DEFAULT, "hqfInfos is empty");
932 return ERR_BUNDLEMANAGER_QUICK_FIX_PROFILE_PARSE_FAILED;
933 }
934 for (const auto &hqf : appQfInfo.hqfInfos) {
935 auto iter = std::find_if(std::begin(bundleInfo.hapModuleInfos), std::end(bundleInfo.hapModuleInfos),
936 [hqf](const HapModuleInfo &info) {
937 return info.moduleName == hqf.moduleName;
938 });
939 if (iter == bundleInfo.hapModuleInfos.end()) {
940 LOG_W(BMS_TAG_DEFAULT, "moduleName:%{public}s not exist", hqf.moduleName.c_str());
941 continue;
942 }
943
944 CodeSignatureParam codeSignatureParam;
945 PrepareCodeSignatureParam(appQuickFix, hqf, bundleInfo, hqfSoPath, codeSignatureParam);
946 ErrCode ret = InstalldClient::GetInstance()->VerifyCodeSignatureForHap(codeSignatureParam);
947 if (ret != ERR_OK) {
948 LOG_E(BMS_TAG_DEFAULT, "moduleName: %{public}s verify code signature failed", hqf.moduleName.c_str());
949 return ret;
950 }
951 }
952 LOG_D(BMS_TAG_DEFAULT, "end");
953 return ERR_OK;
954 }
955
CheckHqfResourceIsValid(const std::vector<std::string> bundleFilePaths,const BundleInfo & bundleInfo)956 ErrCode QuickFixDeployer::CheckHqfResourceIsValid(
957 const std::vector<std::string> bundleFilePaths, const BundleInfo &bundleInfo)
958 {
959 LOG_D(BMS_TAG_DEFAULT, "start, bundleName:%{public}s", bundleInfo.name.c_str());
960 if (bundleInfo.applicationInfo.debug &&
961 (bundleInfo.applicationInfo.appProvisionType == Constants::APP_PROVISION_TYPE_DEBUG)) {
962 return ERR_OK;
963 }
964 PatchParser patchParser;
965 bool hasResourceFile = patchParser.HasResourceFile(bundleFilePaths);
966 if (hasResourceFile) {
967 LOG_W(BMS_TAG_DEFAULT, "bundleName:%{public}s check resource failed", bundleInfo.name.c_str());
968 return ERR_BUNDLEMANAGER_QUICK_FIX_RELEASE_HAP_HAS_RESOURCES_FILE_FAILED;
969 }
970 return ERR_OK;
971 }
972
ExtractQuickFixResFile(const AppQuickFix & appQuickFix,const BundleInfo & bundleInfo)973 ErrCode QuickFixDeployer::ExtractQuickFixResFile(const AppQuickFix &appQuickFix, const BundleInfo &bundleInfo)
974 {
975 LOG_D(BMS_TAG_DEFAULT, "ExtractQuickFixResFile start, bundleName:%{public}s", appQuickFix.bundleName.c_str());
976 auto &appQfInfo = appQuickFix.deployingAppqfInfo;
977 if (appQfInfo.hqfInfos.empty()) {
978 LOG_E(BMS_TAG_DEFAULT, "hqfInfos is empty");
979 return ERR_BUNDLEMANAGER_QUICK_FIX_PROFILE_PARSE_FAILED;
980 }
981 for (const auto &hqf : appQfInfo.hqfInfos) {
982 auto iter = std::find_if(std::begin(bundleInfo.hapModuleInfos), std::end(bundleInfo.hapModuleInfos),
983 [hqf](const HapModuleInfo &info) {
984 return info.moduleName == hqf.moduleName;
985 });
986 if (iter == bundleInfo.hapModuleInfos.end()) {
987 LOG_W(BMS_TAG_DEFAULT, "moduleName:%{public}s not exist", hqf.moduleName.c_str());
988 continue;
989 }
990
991 std::string targetPath = Constants::BUNDLE_CODE_DIR + ServiceConstants::PATH_SEPARATOR + appQuickFix.bundleName
992 + ServiceConstants::PATH_SEPARATOR + hqf.moduleName + ServiceConstants::PATH_SEPARATOR
993 + ServiceConstants::RES_FILE_PATH;
994 ExtractParam extractParam;
995 extractParam.extractFileType = ExtractFileType::RES_FILE;
996 extractParam.srcPath = hqf.hqfFilePath;
997 extractParam.targetPath = targetPath;
998 if (InstalldClient::GetInstance()->ExtractFiles(extractParam) != ERR_OK) {
999 LOG_W(BMS_TAG_DEFAULT, "moduleName: %{public}s extract so failed", hqf.moduleName.c_str());
1000 continue;
1001 }
1002 }
1003 LOG_D(BMS_TAG_DEFAULT, "ExtractQuickFixResFile end");
1004 return ERR_OK;
1005 }
1006 } // AppExecFwk
1007 } // OHOS