• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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