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