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