1 /*
2  * Copyright (c) 2021-2024 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 "installd/installd_operator.h"
17 
18 #include <algorithm>
19 #if defined(CODE_SIGNATURE_ENABLE)
20 #include "code_sign_utils.h"
21 #endif
22 #if defined(CODE_ENCRYPTION_ENABLE)
23 #include "linux/code_decrypt.h"
24 #endif
25 #include <cerrno>
26 #include <cstdio>
27 #include <dirent.h>
28 #include <dlfcn.h>
29 #include <fcntl.h>
30 #include <filesystem>
31 #include <fstream>
32 #include <map>
33 #include <regex>
34 #include <sstream>
35 #include <string.h>
36 #include <sys/ioctl.h>
37 #include <sys/mman.h>
38 #include <sys/quota.h>
39 #include <sys/stat.h>
40 #include <sys/types.h>
41 #include <unistd.h>
42 
43 #include "app_log_tag_wrapper.h"
44 #include "bundle_constants.h"
45 #include "bundle_service_constants.h"
46 #include "bundle_util.h"
47 #include "directory_ex.h"
48 #include "el5_filekey_manager_error.h"
49 #include "el5_filekey_manager_kit.h"
50 #include "ffrt.h"
51 #include "parameters.h"
52 #include "securec.h"
53 #include "hnp_api.h"
54 
55 namespace OHOS {
56 namespace AppExecFwk {
57 namespace {
58 constexpr const char* PREFIX_RESOURCE_PATH = "/resources/rawfile/";
59 constexpr const char* PREFIX_LIBS_PATH = "/libs/";
60 constexpr const char* PREFIX_TARGET_PATH = "/print_service/";
61 constexpr const char* HQF_DIR_PREFIX = "patch_";
62 #if defined(CODE_ENCRYPTION_ENABLE)
63 static const char LIB_CODE_CRYPTO_SO_PATH[] = "system/lib/libcode_crypto_metadata_process_utils.z.so";
64 static const char LIB64_CODE_CRYPTO_SO_PATH[] = "system/lib64/libcode_crypto_metadata_process_utils.z.so";
65 static const char CODE_CRYPTO_FUNCTION_NAME[] = "_ZN4OHOS8Security10CodeCrypto15CodeCryptoUtils28"
66     "EnforceMetadataProcessForAppERKNSt3__h13unordered_mapINS3_12basic_stringIcNS3_11char_traitsIcEENS3_"
67     "9allocatorIcEEEESA_NS3_4hashISA_EENS3_8equal_toISA_EENS8_INS3_4pairIKSA_SA_EEEEEEjRbNS2_17InstallBundleTypeERKb";
68 #endif
69 static constexpr int32_t INSTALLS_UID = 3060;
70 static constexpr int32_t MODE_BASE = 07777;
71 static constexpr int32_t KEY_ID_STEP = 2;
72 static constexpr int8_t STR_LIBS_LEN = 4;
73 constexpr const char* PROC_MOUNTS_PATH = "/proc/mounts";
74 constexpr const char* QUOTA_DEVICE_DATA_PATH = "/data";
75 constexpr const char* CACHE_DIR = "cache";
76 constexpr const char* BUNDLE_BASE_CODE_DIR = "/data/app/el1/bundle";
77 constexpr const char* AP_PATH = "ap/";
78 constexpr const char* AI_SUFFIX = ".ai";
79 constexpr const char* DIFF_SUFFIX = ".diff";
80 constexpr const char* BUNDLE_BACKUP_KEEP_DIR = "/.backup";
81 constexpr const char* ATOMIC_SERVICE_PATH = "+auid-";
82 #if defined(CODE_SIGNATURE_ENABLE)
83 using namespace OHOS::Security::CodeSign;
84 #endif
85 #if defined(CODE_ENCRYPTION_ENABLE)
86 static std::string CODE_DECRYPT = "/dev/code_decrypt";
87 static int32_t INVALID_RETURN_VALUE = -1;
88 static int32_t INVALID_FILE_DESCRIPTOR = -1;
89 #endif
90 std::recursive_mutex mMountsLock;
91 static std::map<std::string, std::string> mQuotaReverseMounts;
92 using ApplyPatch = int32_t (*)(const std::string, const std::string, const std::string);
93 
HandleScanResult(const std::string & dir,const std::string & subName,ResultMode resultMode)94 static std::string HandleScanResult(
95     const std::string &dir, const std::string &subName, ResultMode resultMode)
96 {
97     if (resultMode == ResultMode::RELATIVE_PATH) {
98         return subName;
99     }
100 
101     return dir + ServiceConstants::PATH_SEPARATOR + subName;
102 }
103 
StartsWith(const std::string & sourceString,const std::string & targetPrefix)104 static bool StartsWith(const std::string &sourceString, const std::string &targetPrefix)
105 {
106     return sourceString.find(targetPrefix) == 0;
107 }
108 
EndsWith(const std::string & sourceString,const std::string & targetSuffix)109 static bool EndsWith(const std::string &sourceString, const std::string &targetSuffix)
110 {
111     if (sourceString.length() < targetSuffix.length()) {
112         return false;
113     }
114     if (sourceString.rfind(targetSuffix) == (sourceString.length() - targetSuffix.length())) {
115         return true;
116     }
117     return false;
118 }
119 } // namespace
120 
121 #define FSCRYPT_KEY_DESCRIPTOR_SIZE 8
122 #define HMFS_IOCTL_MAGIC 0xf5
123 #define HMFS_IOC_SET_ASDP_ENCRYPTION_POLICY _IOW(HMFS_IOCTL_MAGIC, 84, struct fscrypt_asdp_policy)
124 #define FORCE_PROTECT 0x0
125 
126 struct fscrypt_asdp_policy {
127     char version;
128     char asdp_class;
129     char flags;
130     char reserved;
131     char app_key2_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE];
132 } __attribute__((__packed__));
133 
CheckAndDeleteLinkFile(const std::string & path)134 bool InstalldOperator::CheckAndDeleteLinkFile(const std::string &path)
135 {
136     struct stat path_stat;
137     if (lstat(path.c_str(), &path_stat) == 0) {
138         if (S_ISLNK(path_stat.st_mode)) {
139             if (unlink(path.c_str()) == 0) {
140                 return true;
141             }
142             LOG_E(BMS_TAG_INSTALLD, "CheckAndDeleteLinkFile unlink %{public}s failed, error: %{public}d",
143                 path.c_str(), errno);
144         }
145     }
146     LOG_E(BMS_TAG_INSTALLD, "CheckAndDeleteLinkFile lstat or S_ISLNK %{public}s failed, errno:%{public}d",
147         path.c_str(), errno);
148     return false;
149 }
150 
IsExistFile(const std::string & path)151 bool InstalldOperator::IsExistFile(const std::string &path)
152 {
153     if (path.empty()) {
154         LOG_E(BMS_TAG_INSTALLD, "path is empty");
155         return false;
156     }
157 
158     struct stat buf = {};
159     if (stat(path.c_str(), &buf) != 0) {
160         LOG_NOFUNC_E(BMS_TAG_INSTALLD, "stat fail %{public}d", errno);
161         return false;
162     }
163     return S_ISREG(buf.st_mode);
164 }
165 
IsExistApFile(const std::string & path)166 bool InstalldOperator::IsExistApFile(const std::string &path)
167 {
168     std::string realPath;
169     std::filesystem::path apFilePath(path);
170     std::string apDir = apFilePath.parent_path().string();
171     if (path.empty() || !PathToRealPath(apDir, realPath)) {
172         return false;
173     }
174 
175     std::error_code errorCode;
176     std::filesystem::directory_iterator iter(realPath, errorCode);
177 
178     if (errorCode) {
179         LOG_E(BMS_TAG_INSTALLD, "Error occurred while opening apDir: %{public}s", errorCode.message().c_str());
180         return false;
181     }
182     for (const auto& entry : iter) {
183         if (entry.path().extension() == ServiceConstants::AP_SUFFIX) {
184             return true;
185         }
186     }
187     return false;
188 }
189 
IsExistDir(const std::string & path)190 bool InstalldOperator::IsExistDir(const std::string &path)
191 {
192     if (path.empty()) {
193         LOG_E(BMS_TAG_INSTALLD, "path is empty");
194         return false;
195     }
196 
197     struct stat buf = {};
198     if (stat(path.c_str(), &buf) != 0) {
199         return false;
200     }
201     return S_ISDIR(buf.st_mode);
202 }
203 
IsDirEmpty(const std::string & dir)204 bool InstalldOperator::IsDirEmpty(const std::string &dir)
205 {
206     return OHOS::IsEmptyFolder(dir);
207 }
208 
MkRecursiveDir(const std::string & path,bool isReadByOthers)209 bool InstalldOperator::MkRecursiveDir(const std::string &path, bool isReadByOthers)
210 {
211     if (!OHOS::ForceCreateDirectory(path)) {
212         LOG_E(BMS_TAG_INSTALLD, "mkdir failed");
213         return false;
214     }
215     mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH;
216     mode |= (isReadByOthers ? S_IROTH : 0);
217     return OHOS::ChangeModeDirectory(path, mode);
218 }
219 
DeleteDir(const std::string & path)220 bool InstalldOperator::DeleteDir(const std::string &path)
221 {
222     if (IsExistFile(path)) {
223         return OHOS::RemoveFile(path);
224     }
225     if (IsExistDir(path)) {
226         LOG_NOFUNC_I(BMS_TAG_COMMON, "del %{public}s", path.c_str());
227         return OHOS::ForceRemoveDirectory(path);
228     }
229     return true;
230 }
231 
DeleteDirFast(const std::string & path)232 bool InstalldOperator::DeleteDirFast(const std::string &path)
233 {
234     std::string newPath = GetSameLevelTmpPath(path);
235     if (newPath.empty()) {
236         return DeleteDir(path);
237     }
238     if (rename(path.c_str(), newPath.c_str()) != 0) {
239         LOG_W(BMS_TAG_INSTALLD, "rename failed:%{public}s,%{public}s,%{public}s",
240             std::strerror(errno), path.c_str(), newPath.c_str());
241         return DeleteDir(path);
242     }
243     auto task = [newPath]() {
244         bool ret = InstalldOperator::DeleteDir(newPath);
245         if (!ret) {
246             LOG_E(BMS_TAG_INSTALLD, "async del failed,%{public}s", newPath.c_str());
247         }
248     };
249     ffrt::submit(task);
250     return true;
251 }
252 
DeleteDirFlexible(const std::string & path,const bool async)253 bool InstalldOperator::DeleteDirFlexible(const std::string &path, const bool async)
254 {
255     if (async) {
256         return DeleteDirFast(path);
257     }
258     return DeleteDir(path);
259 }
260 
DeleteUninstallTmpDir(const std::string & path)261 bool InstalldOperator::DeleteUninstallTmpDir(const std::string &path)
262 {
263     std::vector<std::string> deleteDirs;
264     std::error_code ec;
265     if (!std::filesystem::exists(path, ec) || !std::filesystem::is_directory(path, ec)) {
266         LOG_W(BMS_TAG_INSTALLD, "invalid path:%{public}s,err:%{public}s", path.c_str(), ec.message().c_str());
267         return false;
268     }
269     std::filesystem::directory_iterator dirIter(path, std::filesystem::directory_options::skip_permission_denied, ec);
270     std::filesystem::directory_iterator endIter;
271     if (ec) {
272         LOG_W(BMS_TAG_INSTALLD, "create iterator failed,%{public}s,err:%{public}s", path.c_str(), ec.message().c_str());
273         return false;
274     }
275     for (; dirIter != endIter; dirIter.increment(ec)) {
276         if (ec) {
277             LOG_W(BMS_TAG_INSTALLD, "iteration failed,%{public}s,err:%{public}s", path.c_str(), ec.message().c_str());
278             return false;
279         }
280         const std::filesystem::directory_entry &entry = *dirIter;
281         std::string fileName = entry.path().filename().string();
282         if (fileName.rfind(ServiceConstants::UNINSTALL_TMP_PREFIX, 0) == 0) {
283             deleteDirs.emplace_back(entry.path().string());
284         }
285     }
286     bool ret = true;
287     for (const std::string &dir : deleteDirs) {
288         LOG_W(BMS_TAG_INSTALLD, "begin to delete dir %{public}s", dir.c_str());
289         if (!DeleteDir(dir)) {
290             ret = false;
291             LOG_W(BMS_TAG_INSTALLD, "delete dir failed:%{public}s", dir.c_str());
292         }
293     }
294     return ret;
295 }
296 
GetSameLevelTmpPath(const std::string & path)297 std::string InstalldOperator::GetSameLevelTmpPath(const std::string &path)
298 {
299     if (path.empty()) {
300         LOG_I(BMS_TAG_INSTALLD, "path empty");
301         return Constants::EMPTY_STRING;
302     }
303     std::filesystem::path parentPath = std::filesystem::path(path).parent_path();
304     if (parentPath.empty()) {
305         LOG_I(BMS_TAG_INSTALLD, "parentPath empty");
306         return Constants::EMPTY_STRING;
307     }
308     std::error_code ec;
309     std::filesystem::path canonicalParentPath = std::filesystem::canonical(parentPath, ec);
310     if (ec) {
311         LOG_I(BMS_TAG_INSTALLD, "canonical failed:%{public}s", ec.message().c_str());
312         return Constants::EMPTY_STRING;
313     }
314     uint32_t maxTry = 3;
315     for (uint32_t i = 1; i <= maxTry; ++i) {
316         std::string childPath = ServiceConstants::UNINSTALL_TMP_PREFIX + std::to_string(BundleUtil::GetCurrentTimeNs());
317         std::filesystem::path fullPath = canonicalParentPath / childPath;
318         if (std::filesystem::exists(fullPath, ec)) {
319             LOG_I(BMS_TAG_INSTALLD, "fullPath exists");
320             continue;
321         }
322         if (ec) {
323             LOG_I(BMS_TAG_INSTALLD, "exists failed:%{public}s", ec.message().c_str());
324             continue;
325         }
326         return fullPath.string();
327     }
328     LOG_I(BMS_TAG_INSTALLD, "GetSameLevelTmpPath failed");
329     return Constants::EMPTY_STRING;
330 }
331 
ExtractFiles(const std::string & sourcePath,const std::string & targetSoPath,const std::string & cpuAbi)332 bool InstalldOperator::ExtractFiles(const std::string &sourcePath, const std::string &targetSoPath,
333     const std::string &cpuAbi)
334 {
335     LOG_D(BMS_TAG_INSTALLD, "InstalldOperator::ExtractFiles start");
336     if (targetSoPath.empty()) {
337         LOG_D(BMS_TAG_INSTALLD, "targetSoPath is empty");
338         return true;
339     }
340 
341     BundleExtractor extractor(sourcePath);
342     if (!extractor.Init()) {
343         return false;
344     }
345 
346     std::vector<std::string> soEntryFiles;
347     if (!ObtainNativeSoFile(extractor, cpuAbi, soEntryFiles)) {
348         LOG_E(BMS_TAG_INSTALLD, "ExtractFiles obtain native so file entryName failed");
349         return false;
350     }
351 
352     for_each(soEntryFiles.begin(), soEntryFiles.end(), [&extractor, &targetSoPath, &cpuAbi](const auto &entry) {
353         ExtractTargetFile(extractor, entry, targetSoPath, cpuAbi);
354     });
355 
356     LOG_D(BMS_TAG_INSTALLD, "InstalldOperator::ExtractFiles end");
357     return true;
358 }
359 
ExtractFiles(const ExtractParam & extractParam)360 bool InstalldOperator::ExtractFiles(const ExtractParam &extractParam)
361 {
362     LOG_D(BMS_TAG_INSTALLD, "InstalldOperator::ExtractFiles start");
363     BundleExtractor extractor(extractParam.srcPath);
364     if (!extractor.Init()) {
365         LOG_E(BMS_TAG_INSTALLD, "extractor init failed");
366         return false;
367     }
368 
369     if (extractParam.extractFileType == ExtractFileType::RESOURCE) {
370         return ExtractResourceFiles(extractParam, extractor);
371     }
372 
373     if ((extractParam.extractFileType == ExtractFileType::AP) &&
374         !extractor.IsDirExist(AP_PATH)) {
375         LOG_D(BMS_TAG_INSTALLD, "hap has no ap files and does not need to be extracted");
376         return true;
377     }
378 
379     std::vector<std::string> entryNames;
380     if (!extractor.GetZipFileNames(entryNames) || entryNames.empty()) {
381         LOG_E(BMS_TAG_INSTALLD, "get entryNames failed");
382         return false;
383     }
384 
385     for (const auto &entryName : entryNames) {
386         if (strcmp(entryName.c_str(), ".") == 0 ||
387             strcmp(entryName.c_str(), "..") == 0) {
388             continue;
389         }
390         if (entryName.back() == ServiceConstants::PATH_SEPARATOR[0]) {
391             continue;
392         }
393         // handle native file
394         if (IsNativeFile(entryName, extractParam)) {
395             ExtractTargetFile(extractor, entryName, extractParam.targetPath,
396                 extractParam.cpuAbi, extractParam.extractFileType);
397             continue;
398         }
399     }
400 
401     LOG_D(BMS_TAG_INSTALLD, "InstalldOperator::ExtractFiles end");
402     return true;
403 }
404 
ExtractFiles(const std::string hnpPackageInfo,const ExtractParam & extractParam)405 bool InstalldOperator::ExtractFiles(const std::string hnpPackageInfo, const ExtractParam &extractParam)
406 {
407     std::map<std::string, std::string> hnpPackageInfoMap;
408     std::stringstream hnpPackageInfoString(hnpPackageInfo);
409     std::string keyValue;
410     while (getline(hnpPackageInfoString, keyValue, '}')) {
411         size_t pos = keyValue.find(":");
412         if (pos != std::string::npos) {
413             std::string key = keyValue.substr(1, pos - 1);
414             std::string value = keyValue.substr(pos + 1);
415             hnpPackageInfoMap[key] = value;
416         }
417     }
418 
419     BundleExtractor extractor(extractParam.srcPath);
420     if (!extractor.Init()) {
421         LOG_E(BMS_TAG_INSTALLD, "extractor init failed");
422         return false;
423     }
424 
425     std::vector<std::string> entryNames;
426     if (!extractor.GetZipFileNames(entryNames) || entryNames.empty()) {
427         LOG_E(BMS_TAG_INSTALLD, "get entryNames failed");
428         return false;
429     }
430     std::string targetPathAndName = "";
431     for (const auto &entryName : entryNames) {
432         if (strcmp(entryName.c_str(), ".") == 0 ||
433             strcmp(entryName.c_str(), "..") == 0) {
434                 continue;
435         }
436         if (entryName.back() == ServiceConstants::PATH_SEPARATOR[0]) {
437             continue;
438         }
439         // handle native file
440         if (IsNativeFile(entryName, extractParam)) {
441             std::string prefix;
442 
443             if (!DeterminePrefix(extractParam.extractFileType, extractParam.cpuAbi, prefix)) {
444                 LOG_E(BMS_TAG_INSTALLD, "determine prefix failed");
445                 return false;
446             }
447 
448             std::string targetName = entryName.substr(prefix.length());
449             if (hnpPackageInfoMap.find(targetName) == hnpPackageInfoMap.end()) {
450                 LOG_E(BMS_TAG_INSTALLD, "illegal native bundle");
451                 continue;
452             }
453             targetPathAndName = extractParam.targetPath + hnpPackageInfoMap[targetName]
454                                 + ServiceConstants::PATH_SEPARATOR + targetName;
455             ExtractTargetHnpFile(extractor, entryName, targetPathAndName, extractParam.extractFileType);
456             hnpPackageInfoMap.erase(targetName);
457             continue;
458         }
459     }
460 
461     if (hnpPackageInfoMap.size() > 0) {
462         return false;
463     }
464     LOG_D(BMS_TAG_INSTALLD, "InstalldOperator::ExtractFiles end");
465     return true;
466 }
IsNativeFile(const std::string & entryName,const ExtractParam & extractParam)467 bool InstalldOperator::IsNativeFile(
468     const std::string &entryName, const ExtractParam &extractParam)
469 {
470     LOG_D(BMS_TAG_INSTALLD, "IsNativeFile, entryName : %{public}s", entryName.c_str());
471     if (extractParam.targetPath.empty()) {
472         LOG_D(BMS_TAG_INSTALLD, "current hap not include so");
473         return false;
474     }
475     std::string prefix;
476     std::vector<std::string> suffixes;
477     if (!DeterminePrefix(extractParam.extractFileType, extractParam.cpuAbi, prefix) ||
478         !DetermineSuffix(extractParam.extractFileType, suffixes)) {
479         LOG_E(BMS_TAG_INSTALLD, "determine prefix or suffix failed");
480         return false;
481     }
482 
483     if (!StartsWith(entryName, prefix)) {
484         LOG_D(BMS_TAG_INSTALLD, "entryName not start with %{public}s", prefix.c_str());
485         return false;
486     }
487 
488     bool checkSuffix = false;
489     for (const auto &suffix : suffixes) {
490         if (EndsWith(entryName, suffix)) {
491             checkSuffix = true;
492             break;
493         }
494     }
495 
496     if (!checkSuffix && extractParam.extractFileType != ExtractFileType::RES_FILE
497         && extractParam.extractFileType != ExtractFileType::SO
498         && extractParam.extractFileType != ExtractFileType::HNPS_FILE) {
499         LOG_D(BMS_TAG_INSTALLD, "file type error");
500         return false;
501     }
502 
503     LOG_D(BMS_TAG_INSTALLD, "find native file, prefix: %{public}s, entryName: %{public}s",
504         prefix.c_str(), entryName.c_str());
505     return true;
506 }
507 
IsNativeSo(const std::string & entryName,const std::string & cpuAbi)508 bool InstalldOperator::IsNativeSo(const std::string &entryName, const std::string &cpuAbi)
509 {
510     LOG_D(BMS_TAG_INSTALLD, "IsNativeSo, entryName : %{public}s", entryName.c_str());
511     std::string prefix = ServiceConstants::LIBS + cpuAbi + ServiceConstants::PATH_SEPARATOR;
512     if (!StartsWith(entryName, prefix)) {
513         LOG_D(BMS_TAG_INSTALLD, "entryName not start with %{public}s", prefix.c_str());
514         return false;
515     }
516     LOG_D(BMS_TAG_INSTALLD, "find native so, entryName : %{public}s", entryName.c_str());
517     return true;
518 }
519 
IsDiffFiles(const std::string & entryName,const std::string & targetPath,const std::string & cpuAbi)520 bool InstalldOperator::IsDiffFiles(const std::string &entryName,
521     const std::string &targetPath, const std::string &cpuAbi)
522 {
523     LOG_D(BMS_TAG_INSTALLD, "IsDiffFiles, entryName : %{public}s", entryName.c_str());
524     if (targetPath.empty()) {
525         LOG_D(BMS_TAG_INSTALLD, "current hap not include diff");
526         return false;
527     }
528     std::string prefix = ServiceConstants::LIBS + cpuAbi + ServiceConstants::PATH_SEPARATOR;
529     if (!StartsWith(entryName, prefix)) {
530         LOG_D(BMS_TAG_INSTALLD, "entryName not start with %{public}s", prefix.c_str());
531         return false;
532     }
533     if (!EndsWith(entryName, DIFF_SUFFIX)) {
534         LOG_D(BMS_TAG_INSTALLD, "file name not diff format");
535         return false;
536     }
537     LOG_D(BMS_TAG_INSTALLD, "find native diff, entryName : %{public}s", entryName.c_str());
538     return true;
539 }
540 
ExtractTargetHnpFile(const BundleExtractor & extractor,const std::string & entryName,const std::string & targetPath,const ExtractFileType & extractFileType)541 void InstalldOperator::ExtractTargetHnpFile(const BundleExtractor &extractor, const std::string &entryName,
542     const std::string &targetPath, const ExtractFileType &extractFileType)
543 {
544     std::string path = targetPath;
545     std::string dir = GetPathDir(path);
546     if (!IsExistDir(dir) && !MkRecursiveDir(dir, true)) {
547         LOG_E(BMS_TAG_INSTALLD, "create dir %{public}s failed", dir.c_str());
548         return;
549     }
550     bool ret = extractor.ExtractFile(entryName, path);
551     if (!ret) {
552         LOG_E(BMS_TAG_INSTALLD, "extract file failed, entryName : %{public}s", entryName.c_str());
553         return;
554     }
555     mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
556     if (extractFileType == ExtractFileType::AP) {
557         struct stat buf = {};
558         if (stat(targetPath.c_str(), &buf) != 0) {
559             LOG_E(BMS_TAG_INSTALLD, "fail to stat errno:%{public}d", errno);
560             return;
561         }
562         ChangeFileAttr(path, buf.st_uid, buf.st_gid);
563         mode = (buf.st_uid == buf.st_gid) ? (S_IRUSR | S_IWUSR) : (S_IRUSR | S_IWUSR | S_IRGRP);
564     }
565     if (!OHOS::ChangeModeFile(path, mode)) {
566         LOG_E(BMS_TAG_INSTALLD, "ChangeModeFile %{public}s failed, errno: %{public}d", path.c_str(), errno);
567         return;
568     }
569     LOG_D(BMS_TAG_INSTALLD, "extract file success, path : %{public}s", path.c_str());
570 }
571 
ProcessBundleInstallNative(const std::string & userId,const std::string & hnpRootPath,const std::string & hapPath,const std::string & cpuAbi,const std::string & packageName)572 bool InstalldOperator::ProcessBundleInstallNative(const std::string &userId, const std::string &hnpRootPath,
573     const std::string &hapPath, const std::string &cpuAbi, const std::string &packageName)
574 {
575     struct HapInfo hapInfo;
576     int res = strcpy_s(hapInfo.packageName, packageName.length() + 1, packageName.c_str());
577     if (res != ERR_OK) {
578         LOG_E(BMS_TAG_INSTALLD, "failed to strcpy_s packageName");
579     }
580     res = strcpy_s(hapInfo.hapPath, hapPath.length() + 1, hapPath.c_str());
581     if (res != ERR_OK) {
582         LOG_E(BMS_TAG_INSTALLD, "failed to strcpy_s hapPath");
583     }
584     res = strcpy_s(hapInfo.abi, cpuAbi.length() + 1, cpuAbi.c_str());
585     if (res != ERR_OK) {
586         LOG_E(BMS_TAG_INSTALLD, "failed to strcpy_s cpuAbi");
587     }
588     int ret = NativeInstallHnp(userId.c_str(), hnpRootPath.c_str(), &hapInfo, 1);
589     LOG_D(BMS_TAG_INSTALLD, "NativeInstallHnp ret: %{public}d", ret);
590     if (ret != 0) {
591         LOG_E(BMS_TAG_INSTALLD, "Native package installation failed with error code: %{public}d", ret);
592         return false;
593     }
594     return true;
595 }
596 
ProcessBundleUnInstallNative(const std::string & userId,const std::string & packageName)597 bool InstalldOperator::ProcessBundleUnInstallNative(const std::string &userId, const std::string &packageName)
598 {
599     int ret = NativeUnInstallHnp(userId.c_str(), packageName.c_str());
600     LOG_D(BMS_TAG_INSTALLD, "NativeUnInstallHnp ret: %{public}d", ret);
601     if (ret != 0) {
602         LOG_E(BMS_TAG_INSTALLD, "Native package uninstallation failed with error code: %{public}d", ret);
603         return false;
604     }
605     return true;
606 }
607 
ExtractTargetFile(const BundleExtractor & extractor,const std::string & entryName,const std::string & targetPath,const std::string & cpuAbi,const ExtractFileType & extractFileType)608 void InstalldOperator::ExtractTargetFile(const BundleExtractor &extractor, const std::string &entryName,
609     const std::string &targetPath, const std::string &cpuAbi, const ExtractFileType &extractFileType)
610 {
611     // create dir if not exist
612     if (!IsExistDir(targetPath)) {
613         if (!MkRecursiveDir(targetPath, true)) {
614             LOG_E(BMS_TAG_INSTALLD, "create targetPath %{public}s failed", targetPath.c_str());
615             return;
616         }
617     }
618 
619     std::string prefix;
620     if (!DeterminePrefix(extractFileType, cpuAbi, prefix)) {
621         LOG_E(BMS_TAG_INSTALLD, "determine prefix failed");
622         return;
623     }
624     std::string targetName = entryName.substr(prefix.length());
625     std::string path = targetPath;
626     if (path.back() != ServiceConstants::FILE_SEPARATOR_CHAR) {
627         path += ServiceConstants::FILE_SEPARATOR_CHAR;
628     }
629     path += targetName;
630     if (targetName.find(ServiceConstants::PATH_SEPARATOR) != std::string::npos) {
631         std::string dir = GetPathDir(path);
632         if (!IsExistDir(dir) && !MkRecursiveDir(dir, true)) {
633             LOG_E(BMS_TAG_INSTALLD, "create dir %{public}s failed", dir.c_str());
634             return;
635         }
636     }
637     bool ret = extractor.ExtractFile(entryName, path);
638     if (!ret) {
639         LOG_E(BMS_TAG_INSTALLD, "extract file failed, entryName : %{public}s", entryName.c_str());
640         return;
641     }
642     mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
643     if (extractFileType == ExtractFileType::AP) {
644         struct stat buf = {};
645         if (stat(targetPath.c_str(), &buf) != 0) {
646             LOG_E(BMS_TAG_INSTALLD, "fail to stat errno:%{public}d", errno);
647             return;
648         }
649         ChangeFileAttr(path, buf.st_uid, buf.st_gid);
650         mode = (buf.st_uid == buf.st_gid) ? (S_IRUSR | S_IWUSR) : (S_IRUSR | S_IWUSR | S_IRGRP);
651     }
652     if (!OHOS::ChangeModeFile(path, mode)) {
653         LOG_E(BMS_TAG_INSTALLD, "ChangeModeFile %{public}s failed, errno: %{public}d", path.c_str(), errno);
654         return;
655     }
656     FsyncFile(path);
657     LOG_D(BMS_TAG_INSTALLD, "extract file success, path : %{public}s", path.c_str());
658 }
659 
FsyncFile(const std::string & path)660 void InstalldOperator::FsyncFile(const std::string &path)
661 {
662     int32_t fileFd = open(path.c_str(), O_RDONLY);
663     if (fileFd < 0) {
664         LOG_E(BMS_TAG_INSTALLER, "open %{public}s failed %{public}d", path.c_str(), errno);
665         return;
666     }
667     if (fsync(fileFd) != 0) {
668         LOG_E(BMS_TAG_INSTALLER, "fsync %{public}s failed %{public}d", path.c_str(), errno);
669     }
670     close(fileFd);
671 }
672 
DeterminePrefix(const ExtractFileType & extractFileType,const std::string & cpuAbi,std::string & prefix)673 bool InstalldOperator::DeterminePrefix(const ExtractFileType &extractFileType, const std::string &cpuAbi,
674     std::string &prefix)
675 {
676     switch (extractFileType) {
677         case ExtractFileType::SO: {
678             prefix = ServiceConstants::LIBS + cpuAbi + ServiceConstants::PATH_SEPARATOR;
679             break;
680         }
681         case ExtractFileType::AN: {
682             prefix = ServiceConstants::AN + cpuAbi + ServiceConstants::PATH_SEPARATOR;
683             break;
684         }
685         case ExtractFileType::AP: {
686             prefix = AP_PATH;
687             break;
688         }
689         case ExtractFileType::RES_FILE: {
690             prefix = ServiceConstants::RES_FILE_PATH;
691             break;
692         }
693         case ExtractFileType::HNPS_FILE: {
694             prefix = ServiceConstants::HNPS + cpuAbi + ServiceConstants::PATH_SEPARATOR;
695             break;
696         }
697         default: {
698             return false;
699         }
700     }
701     return true;
702 }
703 
DetermineSuffix(const ExtractFileType & extractFileType,std::vector<std::string> & suffixes)704 bool InstalldOperator::DetermineSuffix(const ExtractFileType &extractFileType, std::vector<std::string> &suffixes)
705 {
706     switch (extractFileType) {
707         case ExtractFileType::SO: {
708             break;
709         }
710         case ExtractFileType::AN: {
711             suffixes.emplace_back(ServiceConstants::AN_SUFFIX);
712             suffixes.emplace_back(AI_SUFFIX);
713             break;
714         }
715         case ExtractFileType::AP: {
716             suffixes.emplace_back(ServiceConstants::AP_SUFFIX);
717             break;
718         }
719         case ExtractFileType::RES_FILE: {
720             break;
721         }
722         case ExtractFileType::HNPS_FILE: {
723             break;
724         }
725         default: {
726             return false;
727         }
728     }
729     return true;
730 }
731 
RenameDir(const std::string & oldPath,const std::string & newPath)732 bool InstalldOperator::RenameDir(const std::string &oldPath, const std::string &newPath)
733 {
734     if (oldPath.empty() || oldPath.size() > PATH_MAX) {
735         LOG_E(BMS_TAG_INSTALLD, "oldpath error");
736         return false;
737     }
738     if (access(oldPath.c_str(), F_OK) != 0 && access(newPath.c_str(), F_OK) == 0) {
739         LOG_E(BMS_TAG_INSTALLD, "fail to access file errno:%{public}d", errno);
740         return true;
741     }
742     std::string realOldPath;
743     realOldPath.reserve(PATH_MAX);
744     realOldPath.resize(PATH_MAX - 1);
745     if (realpath(oldPath.c_str(), &(realOldPath[0])) == nullptr) {
746         LOG_NOFUNC_E(BMS_TAG_INSTALLD, "realOldPath:%{public}s errno:%{public}d", realOldPath.c_str(), errno);
747         return false;
748     }
749 
750     if (!(IsValidCodePath(realOldPath) && IsValidCodePath(newPath))) {
751         LOG_E(BMS_TAG_INSTALLD, "IsValidCodePath failed");
752         return false;
753     }
754     return RenameFile(realOldPath, newPath);
755 }
756 
GetPathDir(const std::string & path)757 std::string InstalldOperator::GetPathDir(const std::string &path)
758 {
759     std::size_t pos = path.rfind(ServiceConstants::PATH_SEPARATOR);
760     if (pos == std::string::npos) {
761         return std::string();
762     }
763     return path.substr(0, pos + 1);
764 }
765 
ChangeDirOwnerRecursively(const std::string & path,const int uid,const int gid)766 bool InstalldOperator::ChangeDirOwnerRecursively(const std::string &path, const int uid, const int gid)
767 {
768     std::string subPath;
769     bool ret = true;
770     DIR *dir = opendir(path.c_str());
771     if (dir == nullptr) {
772         LOG_D(BMS_TAG_INSTALLD, "fail to opendir:%{public}s, errno:%{public}d", path.c_str(), errno);
773         return false;
774     }
775 
776     while (true) {
777         struct dirent *ptr = readdir(dir);
778         if (ptr == nullptr) {
779             LOG_D(BMS_TAG_INSTALLD, "fail to readdir errno:%{public}d", errno);
780             break;
781         }
782 
783         if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
784             continue;
785         }
786 
787         subPath = OHOS::IncludeTrailingPathDelimiter(path) + std::string(ptr->d_name);
788         if (ptr->d_type == DT_DIR) {
789             ret = ChangeDirOwnerRecursively(subPath, uid, gid);
790             continue;
791         }
792 
793         if (access(subPath.c_str(), F_OK) == 0) {
794             if (!ChangeFileAttr(subPath, uid, gid)) {
795                 LOG_D(BMS_TAG_INSTALLD, "Failed to ChangeFileAttr %{public}s, uid=%{public}d", subPath.c_str(), uid);
796                 closedir(dir);
797                 return false;
798             }
799         }
800     }
801 
802     closedir(dir);
803     std::string currentPath = OHOS::ExcludeTrailingPathDelimiter(path);
804     if (access(currentPath.c_str(), F_OK) == 0) {
805         if (!ChangeFileAttr(currentPath, uid, gid)) {
806             LOG_D(BMS_TAG_INSTALLD, "Failed to ChangeFileAttr %{public}s, uid=%{public}d", currentPath.c_str(), uid);
807             return false;
808         }
809     }
810 
811     return ret;
812 }
813 
ChangeFileAttr(const std::string & filePath,const int uid,const int gid)814 bool InstalldOperator::ChangeFileAttr(const std::string &filePath, const int uid, const int gid)
815 {
816     LOG_D(BMS_TAG_INSTALLD, "begin to change %{public}s file attribute", filePath.c_str());
817     if (chown(filePath.c_str(), uid, gid) != 0) {
818         LOG_E(BMS_TAG_INSTALLD, "fail to change %{public}s ownership, uid=%{public}d, errno:%{public}d",
819             filePath.c_str(), uid, errno);
820         return false;
821     }
822     LOG_D(BMS_TAG_INSTALLD, "change %{public}s file attribute successfully", filePath.c_str());
823     return true;
824 }
825 
RenameFile(const std::string & oldPath,const std::string & newPath)826 bool InstalldOperator::RenameFile(const std::string &oldPath, const std::string &newPath)
827 {
828     if (oldPath.empty() || newPath.empty()) {
829         LOG_E(BMS_TAG_INSTALLD, "old path or new path is empty");
830         return false;
831     }
832     if (!DeleteDir(newPath)) {
833         return false;
834     }
835     return rename(oldPath.c_str(), newPath.c_str()) == 0;
836 }
837 
IsValidPath(const std::string & rootDir,const std::string & path)838 bool InstalldOperator::IsValidPath(const std::string &rootDir, const std::string &path)
839 {
840     if (rootDir.find(ServiceConstants::PATH_SEPARATOR) != 0 ||
841         rootDir.rfind(ServiceConstants::PATH_SEPARATOR) != (rootDir.size() - 1) ||
842         rootDir.find("..") != std::string::npos) {
843         return false;
844     }
845     if (path.find("..") != std::string::npos) {
846         return false;
847     }
848     return path.compare(0, rootDir.size(), rootDir) == 0;
849 }
850 
IsValidCodePath(const std::string & codePath)851 bool InstalldOperator::IsValidCodePath(const std::string &codePath)
852 {
853     if (codePath.empty()) {
854         LOG_E(BMS_TAG_INSTALLD, "code path is empty");
855         return false;
856     }
857     return IsValidPath(BUNDLE_BASE_CODE_DIR + ServiceConstants::PATH_SEPARATOR, codePath);
858 }
859 
DeleteFiles(const std::string & dataPath)860 bool InstalldOperator::DeleteFiles(const std::string &dataPath)
861 {
862     LOG_D(BMS_TAG_INSTALLD, "InstalldOperator::DeleteFiles start");
863     std::string subPath;
864     bool ret = true;
865     DIR *dir = opendir(dataPath.c_str());
866     if (dir == nullptr) {
867         LOG_D(BMS_TAG_INSTALLD, "fail to opendir:%{public}s, errno:%{public}d", dataPath.c_str(), errno);
868         return true;
869     }
870     while (true) {
871         struct dirent *ptr = readdir(dir);
872         if (ptr == nullptr) {
873             LOG_D(BMS_TAG_INSTALLD, "fail to readdir errno:%{public}d", errno);
874             break;
875         }
876         if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
877             continue;
878         }
879         subPath = OHOS::IncludeTrailingPathDelimiter(dataPath) + std::string(ptr->d_name);
880         if (ptr->d_type == DT_DIR) {
881             if (!OHOS::ForceRemoveDirectory(subPath)) {
882                 ret = false;
883                 LOG_W(BMS_TAG_INSTALLD, "ForceRemoveDirectory %{public}s failed, error: %{public}d",
884                     dataPath.c_str(), errno);
885             }
886             continue;
887         }
888         if (access(subPath.c_str(), F_OK) == 0) {
889             ret = OHOS::RemoveFile(subPath);
890             if (!ret) {
891                 LOG_W(BMS_TAG_INSTALLD, "RemoveFile %{public}s failed, error: %{public}d", dataPath.c_str(), errno);
892             }
893             continue;
894         }
895         // maybe lnk_file
896         ret = CheckAndDeleteLinkFile(subPath);
897     }
898     closedir(dir);
899     return ret;
900 }
901 
DeleteFilesExceptDirs(const std::string & dataPath,const std::vector<std::string> & dirsToKeep)902 bool InstalldOperator::DeleteFilesExceptDirs(const std::string &dataPath, const std::vector<std::string> &dirsToKeep)
903 {
904     LOG_D(BMS_TAG_INSTALLD, "InstalldOperator::DeleteFilesExceptBundleDataDirs start");
905     std::string filePath;
906     DIR *dir = opendir(dataPath.c_str());
907     if (dir == nullptr) {
908         LOG_E(BMS_TAG_INSTALLD, "fail to opendir:%{public}s, errno:%{public}d", dataPath.c_str(), errno);
909         return false;
910     }
911     bool ret = true;
912     while (true) {
913         struct dirent *ptr = readdir(dir);
914         if (ptr == nullptr) {
915             LOG_E(BMS_TAG_INSTALLD, "fail to readdir errno:%{public}d", errno);
916             break;
917         }
918         std::string dirName = ServiceConstants::PATH_SEPARATOR + std::string(ptr->d_name);
919         if (std::find(dirsToKeep.begin(), dirsToKeep.end(), dirName) != dirsToKeep.end() ||
920             std::string(BUNDLE_BACKUP_KEEP_DIR) == dirName) {
921             continue;
922         }
923         if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
924             continue;
925         }
926         filePath = OHOS::IncludeTrailingPathDelimiter(dataPath) + std::string(ptr->d_name);
927         if (ptr->d_type == DT_DIR) {
928             ret = OHOS::ForceRemoveDirectory(filePath);
929         } else {
930             if (access(filePath.c_str(), F_OK) == 0) {
931                 ret = OHOS::RemoveFile(filePath);
932             }
933         }
934     }
935     closedir(dir);
936     return ret;
937 }
938 
MkOwnerDir(const std::string & path,bool isReadByOthers,const int uid,const int gid)939 bool InstalldOperator::MkOwnerDir(const std::string &path, bool isReadByOthers, const int uid, const int gid)
940 {
941     if (!MkRecursiveDir(path, isReadByOthers)) {
942         return false;
943     }
944     return ChangeFileAttr(path, uid, gid);
945 }
946 
CheckPathIsSame(const std::string & path,int32_t mode,const int32_t uid,const int32_t gid,bool & isPathExist)947 bool InstalldOperator::CheckPathIsSame(const std::string &path, int32_t mode, const int32_t uid, const int32_t gid,
948     bool &isPathExist)
949 {
950     struct stat s;
951     if (stat(path.c_str(), &s) != 0) {
952         LOG_D(BMS_TAG_INSTALLD, "path :%{public}s is not exist, need create, errno:%{public}d", path.c_str(), errno);
953         isPathExist = false;
954         return false;
955     }
956     isPathExist = true;
957     if (((s.st_mode & MODE_BASE) == mode) && (static_cast<int32_t>(s.st_uid) == uid)
958         && (static_cast<int32_t>(s.st_gid) == gid)) {
959         LOG_D(BMS_TAG_INSTALLD, "path :%{public}s mode uid and gid are same, no need to create again", path.c_str());
960         return true;
961     }
962     LOG_NOFUNC_W(BMS_TAG_INSTALLD, "path:%{public}s exist, but mode uid or gid are not same, need to create again",
963         path.c_str());
964     return false;
965 }
966 
MkOwnerDir(const std::string & path,int mode,const int uid,const int gid)967 bool InstalldOperator::MkOwnerDir(const std::string &path, int mode, const int uid, const int gid)
968 {
969     bool isPathExist = false;
970     if (CheckPathIsSame(path, mode, uid, gid, isPathExist)) {
971         return true;
972     }
973     if (isPathExist) {
974         if (chown(path.c_str(), INSTALLS_UID, INSTALLS_UID) != 0) {
975             LOG_W(BMS_TAG_INSTALLD, "fail to change %{public}s ownership, errno:%{public}d", path.c_str(), errno);
976         }
977     }
978     if (!OHOS::ForceCreateDirectory(path)) {
979         LOG_E(BMS_TAG_INSTALLD, "mkdir failed, errno: %{public}d", errno);
980         return false;
981     }
982     // only modify parent dir mode
983     if (chmod(path.c_str(), mode) != 0) {
984         LOG_E(BMS_TAG_INSTALLD, "chmod path:%{public}s mode:%{public}d failed, errno:%{public}d",
985             path.c_str(), mode, errno);
986         return false;
987     }
988     if (!ChangeDirOwnerRecursively(path, uid, gid)) {
989         LOG_E(BMS_TAG_INSTALLD, "ChangeDirOwnerRecursively failed, errno: %{public}d", errno);
990         return false;
991     }
992     return true;
993 }
994 
GetDiskUsage(const std::string & dir,bool isRealPath)995 int64_t InstalldOperator::GetDiskUsage(const std::string &dir, bool isRealPath)
996 {
997     if (dir.empty() || (dir.size() > ServiceConstants::PATH_MAX_SIZE)) {
998         LOG_E(BMS_TAG_INSTALLD, "GetDiskUsage dir path invalid");
999         return 0;
1000     }
1001     std::string filePath = dir;
1002     if (!isRealPath && !PathToRealPath(dir, filePath)) {
1003         LOG_D(BMS_TAG_INSTALLD, "file is not real path, file path: %{public}s", dir.c_str());
1004         return 0;
1005     }
1006     DIR *dirPtr = opendir(filePath.c_str());
1007     if (dirPtr == nullptr) {
1008         LOG_E(BMS_TAG_INSTALLD, "GetDiskUsage open file dir:%{public}s is failure, errno:%{public}d",
1009             filePath.c_str(), errno);
1010         return 0;
1011     }
1012     if (filePath.back() != ServiceConstants::FILE_SEPARATOR_CHAR) {
1013         filePath.push_back(ServiceConstants::FILE_SEPARATOR_CHAR);
1014     }
1015     struct dirent *entry = nullptr;
1016     int64_t size = 0;
1017     while ((entry = readdir(dirPtr)) != nullptr) {
1018         if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)) {
1019             continue;
1020         }
1021         std::string path = filePath + entry->d_name;
1022         if (entry->d_type == DT_DIR) {
1023             size += GetDiskUsage(path, true);
1024             continue;
1025         }
1026         struct stat fileInfo = {0};
1027         if (stat(path.c_str(), &fileInfo) != 0) {
1028             LOG_E(BMS_TAG_INSTALLD, "call stat error %{public}s, errno:%{public}d", path.c_str(), errno);
1029             fileInfo.st_size = 0;
1030         }
1031         size += fileInfo.st_size;
1032     }
1033     closedir(dirPtr);
1034     return size;
1035 }
1036 
TraverseCacheDirectory(const std::string & currentPath,std::vector<std::string> & cacheDirs)1037 void InstalldOperator::TraverseCacheDirectory(const std::string &currentPath, std::vector<std::string> &cacheDirs)
1038 {
1039     if (currentPath.empty() || (currentPath.size() > ServiceConstants::PATH_MAX_SIZE)) {
1040         LOG_E(BMS_TAG_INSTALLD, "TraverseCacheDirectory current path invaild");
1041         return;
1042     }
1043     std::string filePath = "";
1044     if (!PathToRealPath(currentPath, filePath)) {
1045         LOG_E(BMS_TAG_INSTALLD, "file is not real path, file path: %{public}s", currentPath.c_str());
1046         return;
1047     }
1048     DIR* dir = opendir(filePath.c_str());
1049     if (dir == nullptr) {
1050         LOG_E(BMS_TAG_INSTALLD, "fail to opendir:%{public}s, errno:%{public}d", filePath.c_str(), errno);
1051         return;
1052     }
1053     if (filePath.back() != ServiceConstants::FILE_SEPARATOR_CHAR) {
1054         filePath.push_back(ServiceConstants::FILE_SEPARATOR_CHAR);
1055     }
1056     struct dirent *ptr = nullptr;
1057     while ((ptr = readdir(dir)) != nullptr) {
1058         if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
1059             continue;
1060         }
1061         if (ptr->d_type == DT_DIR && strcmp(ptr->d_name, CACHE_DIR) == 0) {
1062             std::string currentDir = filePath + std::string(ptr->d_name);
1063             cacheDirs.emplace_back(currentDir);
1064             continue;
1065         }
1066         if (ptr->d_type == DT_DIR) {
1067             std::string currentDir = filePath + std::string(ptr->d_name);
1068             TraverseCacheDirectory(currentDir, cacheDirs);
1069         }
1070     }
1071     closedir(dir);
1072 }
1073 
GetDiskUsageFromPath(const std::vector<std::string> & path)1074 int64_t InstalldOperator::GetDiskUsageFromPath(const std::vector<std::string> &path)
1075 {
1076     int64_t fileSize = 0;
1077     for (auto &st : path) {
1078         fileSize += GetDiskUsage(st);
1079         LOG_D(BMS_TAG_INSTALLD, "GetBundleStats get cache size from: %{public}s", st.c_str());
1080     }
1081     return fileSize;
1082 }
1083 
InitialiseQuotaMounts()1084 bool InstalldOperator::InitialiseQuotaMounts()
1085 {
1086     mQuotaReverseMounts.clear();
1087     std::ifstream mountsFile(PROC_MOUNTS_PATH);
1088 
1089     if (!mountsFile.is_open()) {
1090         LOG_E(BMS_TAG_INSTALLD, "Failed to open mounts file errno:%{public}d", errno);
1091         return false;
1092     }
1093     std::string line;
1094 
1095     while (std::getline(mountsFile, line)) {
1096         std::string device;
1097         std::string mountPoint;
1098         std::string fsType;
1099         std::istringstream lineStream(line);
1100 
1101         if (!(lineStream >> device >> mountPoint >> fsType)) {
1102             LOG_W(BMS_TAG_INSTALLD, "Failed to parse mounts file line: %{public}s", line.c_str());
1103             continue;
1104         }
1105 
1106         if (mountPoint == QUOTA_DEVICE_DATA_PATH) {
1107             struct dqblk dq;
1108             if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), 0, reinterpret_cast<char*>(&dq)) == 0) {
1109                 mQuotaReverseMounts[mountPoint] = device;
1110                 LOG_D(BMS_TAG_INSTALLD, "InitialiseQuotaMounts, mountPoint: %{public}s, device: %{public}s",
1111                     mountPoint.c_str(), device.c_str());
1112             } else {
1113                 LOG_W(BMS_TAG_INSTALLD, "InitialiseQuotaMounts, Failed to get quotactl, errno: %{public}d", errno);
1114             }
1115         }
1116     }
1117     return true;
1118 }
1119 
GetDiskUsageFromQuota(const int32_t uid)1120 int64_t InstalldOperator::GetDiskUsageFromQuota(const int32_t uid)
1121 {
1122     std::lock_guard<std::recursive_mutex> lock(mMountsLock);
1123     std::string device = "";
1124     if (mQuotaReverseMounts.find(QUOTA_DEVICE_DATA_PATH) == mQuotaReverseMounts.end()) {
1125         if (!InitialiseQuotaMounts()) {
1126             LOG_E(BMS_TAG_INSTALLD, "Failed to initialise quota mounts");
1127             return 0;
1128         }
1129     }
1130     device = mQuotaReverseMounts[QUOTA_DEVICE_DATA_PATH];
1131     if (device.empty()) {
1132         LOG_W(BMS_TAG_INSTALLD, "skip when device no quotas present");
1133         return 0;
1134     }
1135     struct dqblk dq;
1136     if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid, reinterpret_cast<char*>(&dq)) != 0) {
1137         LOG_E(BMS_TAG_INSTALLD, "Failed to get quotactl, errno: %{public}d", errno);
1138         return 0;
1139     }
1140     LOG_D(BMS_TAG_INSTALLD, "get disk usage from quota, uid: %{public}d, usage: %{public}llu",
1141         uid, static_cast<unsigned long long>(dq.dqb_curspace));
1142     return dq.dqb_curspace;
1143 }
1144 
ScanDir(const std::string & dirPath,ScanMode scanMode,ResultMode resultMode,std::vector<std::string> & paths)1145 bool InstalldOperator::ScanDir(
1146     const std::string &dirPath, ScanMode scanMode, ResultMode resultMode, std::vector<std::string> &paths)
1147 {
1148     if (dirPath.empty() || (dirPath.size() > ServiceConstants::PATH_MAX_SIZE)) {
1149         LOG_E(BMS_TAG_INSTALLD, "Scan dir path invaild");
1150         return false;
1151     }
1152 
1153     std::string realPath = "";
1154     if (!PathToRealPath(dirPath, realPath)) {
1155         LOG_E(BMS_TAG_INSTALLD, "file(%{public}s) is not real path", dirPath.c_str());
1156         return false;
1157     }
1158 
1159     DIR* dir = opendir(realPath.c_str());
1160     if (dir == nullptr) {
1161         LOG_E(BMS_TAG_INSTALLD, "Scan open dir(%{public}s) fail, errno:%{public}d", realPath.c_str(), errno);
1162         return false;
1163     }
1164 
1165     struct dirent *ptr = nullptr;
1166     while ((ptr = readdir(dir)) != nullptr) {
1167         if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
1168             continue;
1169         }
1170 
1171         std::string subName(ptr->d_name);
1172         if (scanMode == ScanMode::SUB_FILE_DIR) {
1173             if (ptr->d_type == DT_DIR) {
1174                 paths.emplace_back(HandleScanResult(dirPath, subName, resultMode));
1175             }
1176 
1177             continue;
1178         }
1179 
1180         if (scanMode == ScanMode::SUB_FILE_FILE) {
1181             if (ptr->d_type == DT_REG) {
1182                 paths.emplace_back(HandleScanResult(dirPath, subName, resultMode));
1183             }
1184 
1185             continue;
1186         }
1187 
1188         paths.emplace_back(HandleScanResult(dirPath, subName, resultMode));
1189     }
1190 
1191     closedir(dir);
1192     return true;
1193 }
1194 
ScanSoFiles(const std::string & newSoPath,const std::string & originPath,const std::string & currentPath,std::vector<std::string> & paths)1195 bool InstalldOperator::ScanSoFiles(const std::string &newSoPath, const std::string &originPath,
1196     const std::string &currentPath, std::vector<std::string> &paths)
1197 {
1198     if (currentPath.empty() || (currentPath.size() > ServiceConstants::PATH_MAX_SIZE)) {
1199         LOG_E(BMS_TAG_INSTALLD, "ScanSoFiles current path invalid");
1200         return false;
1201     }
1202     std::string filePath = "";
1203     if (!PathToRealPath(currentPath, filePath)) {
1204         LOG_E(BMS_TAG_INSTALLD, "file is not real path, file path: %{public}s", currentPath.c_str());
1205         return false;
1206     }
1207     DIR* dir = opendir(filePath.c_str());
1208     if (dir == nullptr) {
1209         LOG_E(BMS_TAG_INSTALLD, "ScanSoFiles open dir(%{public}s) fail, errno:%{public}d", filePath.c_str(), errno);
1210         return false;
1211     }
1212     if (filePath.back() != ServiceConstants::FILE_SEPARATOR_CHAR) {
1213         filePath.push_back(ServiceConstants::FILE_SEPARATOR_CHAR);
1214     }
1215     struct dirent *ptr = nullptr;
1216     while ((ptr = readdir(dir)) != nullptr) {
1217         if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
1218             continue;
1219         }
1220         if (ptr->d_type == DT_DIR) {
1221             std::string currentDir = filePath + std::string(ptr->d_name);
1222             if (!ScanSoFiles(newSoPath, originPath, currentDir, paths)) {
1223                 closedir(dir);
1224                 return false;
1225             }
1226         }
1227         if (ptr->d_type == DT_REG) {
1228             std::string currentFile = filePath + std::string(ptr->d_name);
1229             std::string prefixPath = originPath;
1230             if (prefixPath.back() != ServiceConstants::FILE_SEPARATOR_CHAR) {
1231                 prefixPath.push_back(ServiceConstants::FILE_SEPARATOR_CHAR);
1232             }
1233             std::string relativePath = currentFile.substr(prefixPath.size());
1234             paths.emplace_back(relativePath);
1235             std::string subNewSoPath = GetPathDir(newSoPath + ServiceConstants::PATH_SEPARATOR + relativePath);
1236             if (!IsExistDir(subNewSoPath) && !MkRecursiveDir(subNewSoPath, true)) {
1237                 LOG_E(BMS_TAG_INSTALLD, "ScanSoFiles create subNewSoPath (%{public}s) failed", filePath.c_str());
1238                 closedir(dir);
1239                 return false;
1240             }
1241         }
1242     }
1243     closedir(dir);
1244     return true;
1245 }
1246 
CopyFile(const std::string & sourceFile,const std::string & destinationFile)1247 bool InstalldOperator::CopyFile(
1248     const std::string &sourceFile, const std::string &destinationFile)
1249 {
1250     if (sourceFile.empty() || destinationFile.empty()) {
1251         LOG_E(BMS_TAG_INSTALLD, "Copy file failed due to sourceFile or destinationFile is empty");
1252         return false;
1253     }
1254 
1255     std::ifstream in(sourceFile);
1256     if (!in.is_open()) {
1257         LOG_E(BMS_TAG_INSTALLD, "Copy file failed due to open sourceFile failed errno:%{public}d", errno);
1258         return false;
1259     }
1260 
1261     std::ofstream out(destinationFile);
1262     if (!out.is_open()) {
1263         LOG_E(BMS_TAG_INSTALLD, "Copy file failed due to open destinationFile failed errno:%{public}d", errno);
1264         in.close();
1265         return false;
1266     }
1267 
1268     out << in.rdbuf();
1269     in.close();
1270     out.close();
1271     return true;
1272 }
1273 
CopyFileFast(const std::string & sourcePath,const std::string & destPath)1274 bool InstalldOperator::CopyFileFast(const std::string &sourcePath, const std::string &destPath)
1275 {
1276     LOG_D(BMS_TAG_INSTALLD, "begin");
1277     return BundleUtil::CopyFileFast(sourcePath, destPath);
1278 }
1279 
ExtractDiffFiles(const std::string & filePath,const std::string & targetPath,const std::string & cpuAbi)1280 bool InstalldOperator::ExtractDiffFiles(const std::string &filePath, const std::string &targetPath,
1281     const std::string &cpuAbi)
1282 {
1283     BundleExtractor extractor(filePath);
1284     if (!extractor.Init()) {
1285         return false;
1286     }
1287     std::vector<std::string> entryNames;
1288     if (!extractor.GetZipFileNames(entryNames)) {
1289         return false;
1290     }
1291     for (const auto &entryName : entryNames) {
1292         if (strcmp(entryName.c_str(), ".") == 0 ||
1293             strcmp(entryName.c_str(), "..") == 0) {
1294             continue;
1295         }
1296         if (entryName.back() == ServiceConstants::PATH_SEPARATOR[0]) {
1297             continue;
1298         }
1299         // handle diff file
1300         if (IsDiffFiles(entryName, targetPath, cpuAbi)) {
1301             ExtractTargetFile(extractor, entryName, targetPath, cpuAbi);
1302         }
1303     }
1304     return true;
1305 }
1306 
ProcessApplyDiffPatchPath(const std::string & oldSoPath,const std::string & diffFilePath,const std::string & newSoPath,std::vector<std::string> & oldSoFileNames,std::vector<std::string> & diffFileNames)1307 bool InstalldOperator::ProcessApplyDiffPatchPath(
1308     const std::string &oldSoPath, const std::string &diffFilePath,
1309     const std::string &newSoPath, std::vector<std::string> &oldSoFileNames, std::vector<std::string> &diffFileNames)
1310 {
1311     LOG_I(BMS_TAG_INSTALLD, "oldSoPath: %{public}s, diffFilePath: %{public}s, newSoPath: %{public}s",
1312         oldSoPath.c_str(), diffFilePath.c_str(), newSoPath.c_str());
1313     if (oldSoPath.empty() || diffFilePath.empty() || newSoPath.empty()) {
1314         return false;
1315     }
1316     if (!IsExistDir(oldSoPath) || !IsExistDir(diffFilePath)) {
1317         LOG_E(BMS_TAG_INSTALLD, "oldSoPath or diffFilePath not exist");
1318         return false;
1319     }
1320 
1321     if (!ScanSoFiles(newSoPath, oldSoPath, oldSoPath, oldSoFileNames)) {
1322         LOG_E(BMS_TAG_INSTALLD, "ScanSoFiles oldSoPath failed");
1323         return false;
1324     }
1325 
1326     if (!ScanSoFiles(newSoPath, diffFilePath, diffFilePath, diffFileNames)) {
1327         LOG_E(BMS_TAG_INSTALLD, "ScanSoFiles diffFilePath failed");
1328         return false;
1329     }
1330 
1331     if (oldSoFileNames.empty() || diffFileNames.empty()) {
1332         LOG_E(BMS_TAG_INSTALLD, "so or diff files empty");
1333         return false;
1334     }
1335 
1336     if (!IsExistDir(newSoPath)) {
1337         LOG_D(BMS_TAG_INSTALLD, "ProcessApplyDiffPatchPath create newSoPath");
1338         if (!MkRecursiveDir(newSoPath, true)) {
1339             LOG_E(BMS_TAG_INSTALLD, "ProcessApplyDiffPatchPath create newSo dir (%{public}s) failed",
1340                 newSoPath.c_str());
1341             return false;
1342         }
1343     }
1344     LOG_I(BMS_TAG_INSTALLD, "ProcessApplyDiffPatchPath end");
1345     return true;
1346 }
1347 
ApplyDiffPatch(const std::string & oldSoPath,const std::string & diffFilePath,const std::string & newSoPath,int32_t uid)1348 bool InstalldOperator::ApplyDiffPatch(const std::string &oldSoPath, const std::string &diffFilePath,
1349     const std::string &newSoPath, int32_t uid)
1350 {
1351     LOG_I(BMS_TAG_INSTALLD, "ApplyDiffPatch no need to process");
1352     return true;
1353 }
1354 
ObtainQuickFixFileDir(const std::string & dir,std::vector<std::string> & fileVec)1355 bool InstalldOperator::ObtainQuickFixFileDir(const std::string &dir, std::vector<std::string> &fileVec)
1356 {
1357     if (dir.empty()) {
1358         LOG_E(BMS_TAG_INSTALLD, "ObtainQuickFixFileDir dir path invaild");
1359         return false;
1360     }
1361 
1362     std::string realPath = "";
1363     if (!PathToRealPath(dir, realPath)) {
1364         LOG_E(BMS_TAG_INSTALLD, "dir(%{public}s) is not real path", dir.c_str());
1365         return false;
1366     }
1367 
1368     DIR* directory = opendir(realPath.c_str());
1369     if (directory == nullptr) {
1370         LOG_E(BMS_TAG_INSTALLD, "ObtainQuickFixFileDir open dir(%{public}s) fail, errno:%{public}d",
1371             realPath.c_str(), errno);
1372         return false;
1373     }
1374 
1375     struct dirent *ptr = nullptr;
1376     bool isBundleCodeDir = dir.compare(Constants::BUNDLE_CODE_DIR) == 0;
1377     while ((ptr = readdir(directory)) != nullptr) {
1378         std::string currentName(ptr->d_name);
1379         if (currentName.compare(".") == 0 || currentName.compare("..") == 0) {
1380             continue;
1381         }
1382 
1383         std::string curPath = dir + ServiceConstants::PATH_SEPARATOR + currentName;
1384         struct stat s;
1385         if (stat(curPath.c_str(), &s) == 0) {
1386             // directory
1387             if ((s.st_mode & S_IFDIR) && (isBundleCodeDir || BundleUtil::StartWith(currentName, HQF_DIR_PREFIX))) {
1388                 ObtainQuickFixFileDir(curPath, fileVec);
1389             }
1390 
1391             // file
1392             if ((s.st_mode & S_IFREG) &&
1393                 (currentName.find(ServiceConstants::QUICK_FIX_FILE_SUFFIX) != std::string::npos)) {
1394                     fileVec.emplace_back(dir);
1395                 }
1396         }
1397     }
1398     closedir(directory);
1399     return true;
1400 }
1401 
CopyFiles(const std::string & sourceDir,const std::string & destinationDir)1402 bool InstalldOperator::CopyFiles(const std::string &sourceDir, const std::string &destinationDir)
1403 {
1404     LOG_D(BMS_TAG_INSTALLD, "sourceDir is %{public}s, destinationDir is %{public}s",
1405         sourceDir.c_str(), destinationDir.c_str());
1406     if (sourceDir.empty() || destinationDir.empty()) {
1407         LOG_E(BMS_TAG_INSTALLD, "Copy file failed due to sourceDir or destinationDir is empty");
1408         return false;
1409     }
1410 
1411     std::string realPath = "";
1412     if (!PathToRealPath(sourceDir, realPath)) {
1413         LOG_E(BMS_TAG_INSTALLD, "sourceDir(%{public}s) is not real path", sourceDir.c_str());
1414         return false;
1415     }
1416 
1417     DIR* directory = opendir(realPath.c_str());
1418     if (directory == nullptr) {
1419         LOG_E(BMS_TAG_INSTALLD, "CopyFiles open dir(%{public}s) fail, errno:%{public}d", realPath.c_str(), errno);
1420         return false;
1421     }
1422 
1423     struct dirent *ptr = nullptr;
1424     while ((ptr = readdir(directory)) != nullptr) {
1425         std::string currentName(ptr->d_name);
1426         if (currentName.compare(".") == 0 || currentName.compare("..") == 0) {
1427             continue;
1428         }
1429 
1430         std::string curPath = sourceDir + ServiceConstants::PATH_SEPARATOR + currentName;
1431         struct stat s;
1432         if ((stat(curPath.c_str(), &s) == 0) && (s.st_mode & S_IFREG)) {
1433             std::string innerDesStr = destinationDir + ServiceConstants::PATH_SEPARATOR + currentName;
1434             if (CopyFile(curPath, innerDesStr)) {
1435                 ChangeFileAttr(innerDesStr, Constants::FOUNDATION_UID, ServiceConstants::BMS_GID);
1436             }
1437         }
1438     }
1439     closedir(directory);
1440     return true;
1441 }
1442 
GetNativeLibraryFileNames(const std::string & filePath,const std::string & cpuAbi,std::vector<std::string> & fileNames)1443 bool InstalldOperator::GetNativeLibraryFileNames(const std::string &filePath, const std::string &cpuAbi,
1444     std::vector<std::string> &fileNames)
1445 {
1446     BundleExtractor extractor(filePath);
1447     if (!extractor.Init()) {
1448         return false;
1449     }
1450     std::vector<std::string> entryNames;
1451     if (!extractor.GetZipFileNames(entryNames)) {
1452         return false;
1453     }
1454     std::string prefix = ServiceConstants::LIBS + cpuAbi + ServiceConstants::PATH_SEPARATOR;
1455     for (const auto &entryName : entryNames) {
1456         if (StartsWith(entryName, prefix)) {
1457             fileNames.push_back(entryName.substr(prefix.length(), entryName.length()));
1458         }
1459     }
1460     LOG_D(BMS_TAG_INSTALLD, "InstalldOperator::GetNativeLibraryFileNames end");
1461     return true;
1462 }
1463 
1464 #if defined(CODE_SIGNATURE_ENABLE)
PrepareEntryMap(const CodeSignatureParam & codeSignatureParam,const std::vector<std::string> & soEntryFiles,Security::CodeSign::EntryMap & entryMap)1465 bool InstalldOperator::PrepareEntryMap(const CodeSignatureParam &codeSignatureParam,
1466     const std::vector<std::string> &soEntryFiles, Security::CodeSign::EntryMap &entryMap)
1467 {
1468     if (codeSignatureParam.targetSoPath.empty()) {
1469         return false;
1470     }
1471     const std::string prefix = ServiceConstants::LIBS + codeSignatureParam.cpuAbi + ServiceConstants::PATH_SEPARATOR;
1472     for_each(soEntryFiles.begin(), soEntryFiles.end(),
1473         [&entryMap, &prefix, &codeSignatureParam](const auto &entry) {
1474         std::string fileName = entry.substr(prefix.length());
1475         std::string path = codeSignatureParam.targetSoPath;
1476         if (path.back() != ServiceConstants::FILE_SEPARATOR_CHAR) {
1477             path += ServiceConstants::FILE_SEPARATOR_CHAR;
1478         }
1479         entryMap.emplace(entry, path + fileName);
1480         LOG_D(BMS_TAG_INSTALLD, "VerifyCode the targetSoPath is %{public}s", (path + fileName).c_str());
1481     });
1482     return true;
1483 }
1484 
PerformCodeSignatureCheck(const CodeSignatureParam & codeSignatureParam,const Security::CodeSign::EntryMap & entryMap)1485 ErrCode InstalldOperator::PerformCodeSignatureCheck(const CodeSignatureParam &codeSignatureParam,
1486     const Security::CodeSign::EntryMap &entryMap)
1487 {
1488     ErrCode ret = ERR_OK;
1489     if (codeSignatureParam.isCompileSdkOpenHarmony &&
1490         !Security::CodeSign::CodeSignUtils::IsSupportOHCodeSign()) {
1491         LOG_D(BMS_TAG_INSTALLD, "code signature is not supported");
1492         return ret;
1493     }
1494     if (codeSignatureParam.signatureFileDir.empty()) {
1495         std::shared_ptr<CodeSignHelper> codeSignHelper = std::make_shared<CodeSignHelper>();
1496         Security::CodeSign::FileType fileType = codeSignatureParam.isPreInstalledBundle ?
1497             FILE_ENTRY_ONLY : FILE_ENTRY_ADD;
1498         if (codeSignatureParam.isEnterpriseBundle) {
1499             LOG_D(BMS_TAG_INSTALLD, "Verify code signature for enterprise bundle");
1500             ret = codeSignHelper->EnforceCodeSignForAppWithOwnerId(codeSignatureParam.appIdentifier,
1501                 codeSignatureParam.modulePath, entryMap, fileType);
1502         } else {
1503             LOG_D(BMS_TAG_INSTALLD, "Verify code signature for non-enterprise bundle");
1504             ret = codeSignHelper->EnforceCodeSignForApp(codeSignatureParam.modulePath, entryMap, fileType);
1505         }
1506         LOG_I(BMS_TAG_INSTALLD, "Verify code signature %{public}s", codeSignatureParam.modulePath.c_str());
1507     } else {
1508         ret = CodeSignUtils::EnforceCodeSignForApp(entryMap, codeSignatureParam.signatureFileDir);
1509     }
1510     return ret;
1511 }
1512 #endif
1513 
VerifyCodeSignature(const CodeSignatureParam & codeSignatureParam)1514 bool InstalldOperator::VerifyCodeSignature(const CodeSignatureParam &codeSignatureParam)
1515 {
1516     BundleExtractor extractor(codeSignatureParam.modulePath);
1517     if (!extractor.Init()) {
1518         return false;
1519     }
1520 
1521     std::vector<std::string> soEntryFiles;
1522     if (!ObtainNativeSoFile(extractor, codeSignatureParam.cpuAbi, soEntryFiles)) {
1523         return false;
1524     }
1525 
1526     if (soEntryFiles.empty()) {
1527         LOG_D(BMS_TAG_INSTALLD, "soEntryFiles is empty");
1528         return true;
1529     }
1530 
1531 #if defined(CODE_SIGNATURE_ENABLE)
1532     Security::CodeSign::EntryMap entryMap;
1533     if (!PrepareEntryMap(codeSignatureParam, soEntryFiles, entryMap)) {
1534         return false;
1535     }
1536 
1537     ErrCode ret = PerformCodeSignatureCheck(codeSignatureParam, entryMap);
1538     if (ret != ERR_OK) {
1539         LOG_E(BMS_TAG_INSTALLD, "VerifyCode failed due to %{public}d", ret);
1540         return false;
1541     }
1542 #endif
1543     return true;
1544 }
1545 
CheckEncryption(const CheckEncryptionParam & checkEncryptionParam,bool & isEncryption)1546 bool InstalldOperator::CheckEncryption(const CheckEncryptionParam &checkEncryptionParam, bool &isEncryption)
1547 {
1548     if (checkEncryptionParam.cpuAbi.empty() && checkEncryptionParam.targetSoPath.empty()) {
1549         return CheckHapEncryption(checkEncryptionParam, isEncryption);
1550     }
1551     const std::string cpuAbi = checkEncryptionParam.cpuAbi;
1552     const int32_t bundleId = checkEncryptionParam.bundleId;
1553     InstallBundleType installBundleType = checkEncryptionParam.installBundleType;
1554     const bool isCompressNativeLibrary = checkEncryptionParam.isCompressNativeLibrary;
1555     LOG_D(BMS_TAG_INSTALLD,
1556         "bundleId %{public}d, installBundleType %{public}d, isCompressNativeLibrary %{public}d, path %{public}s",
1557         bundleId, installBundleType, isCompressNativeLibrary, checkEncryptionParam.modulePath.c_str());
1558 
1559     BundleExtractor extractor(checkEncryptionParam.modulePath);
1560     if (!extractor.Init()) {
1561         return false;
1562     }
1563 
1564     std::vector<std::string> soEntryFiles;
1565     if (!ObtainNativeSoFile(extractor, cpuAbi, soEntryFiles)) {
1566         LOG_E(BMS_TAG_INSTALLD, "ObtainNativeSoFile failed");
1567         return false;
1568     }
1569 
1570     if (soEntryFiles.empty()) {
1571         LOG_D(BMS_TAG_INSTALLD, "no so file in installation file %{public}s", checkEncryptionParam.modulePath.c_str());
1572         return true;
1573     }
1574 
1575 #if defined(CODE_ENCRYPTION_ENABLE)
1576     const std::string targetSoPath = checkEncryptionParam.targetSoPath;
1577     std::unordered_map<std::string, std::string> entryMap;
1578     entryMap.emplace(ServiceConstants::CODE_SIGNATURE_HAP, checkEncryptionParam.modulePath);
1579     if (!targetSoPath.empty()) {
1580         const std::string prefix = ServiceConstants::LIBS + cpuAbi + ServiceConstants::PATH_SEPARATOR;
1581         std::for_each(soEntryFiles.begin(), soEntryFiles.end(), [&entryMap, &prefix, &targetSoPath](const auto &entry) {
1582             std::string fileName = entry.substr(prefix.length());
1583             std::string path = targetSoPath;
1584             if (path.back() != ServiceConstants::FILE_SEPARATOR_CHAR) {
1585                 path += ServiceConstants::FILE_SEPARATOR_CHAR;
1586             }
1587             entryMap.emplace(entry, path + fileName);
1588             LOG_D(BMS_TAG_INSTALLD, "CheckEncryption the targetSoPath is %{public}s", (path + fileName).c_str());
1589         });
1590     }
1591     if (!EnforceEncryption(entryMap, bundleId, isEncryption, installBundleType, isCompressNativeLibrary)) {
1592         return false;
1593     }
1594 #endif
1595     return true;
1596 }
1597 
CheckHapEncryption(const CheckEncryptionParam & checkEncryptionParam,bool & isEncryption)1598 bool InstalldOperator::CheckHapEncryption(const CheckEncryptionParam &checkEncryptionParam, bool &isEncryption)
1599 {
1600     const std::string hapPath = checkEncryptionParam.modulePath;
1601     const int32_t bundleId = checkEncryptionParam.bundleId;
1602     InstallBundleType installBundleType = checkEncryptionParam.installBundleType;
1603     const bool isCompressNativeLibrary = checkEncryptionParam.isCompressNativeLibrary;
1604     LOG_D(BMS_TAG_INSTALLD, "CheckHapEncryption the hapPath is %{public}s, installBundleType is %{public}d, "
1605         "bundleId is %{public}d, isCompressNativeLibrary is %{public}d", hapPath.c_str(),
1606         installBundleType, bundleId, isCompressNativeLibrary);
1607 #if defined(CODE_ENCRYPTION_ENABLE)
1608     std::unordered_map<std::string, std::string> entryMap;
1609     entryMap.emplace(ServiceConstants::CODE_SIGNATURE_HAP, hapPath);
1610     if (!EnforceEncryption(entryMap, bundleId, isEncryption, installBundleType, isCompressNativeLibrary)) {
1611         return false;
1612     }
1613 #endif
1614     return true;
1615 }
1616 
ObtainNativeSoFile(const BundleExtractor & extractor,const std::string & cpuAbi,std::vector<std::string> & soEntryFiles)1617 bool InstalldOperator::ObtainNativeSoFile(const BundleExtractor &extractor, const std::string &cpuAbi,
1618     std::vector<std::string> &soEntryFiles)
1619 {
1620     std::vector<std::string> entryNames;
1621     if (!extractor.GetZipFileNames(entryNames)) {
1622         LOG_E(BMS_TAG_INSTALLD, "GetZipFileNames failed");
1623         return false;
1624     }
1625     if (entryNames.empty()) {
1626         LOG_E(BMS_TAG_INSTALLD, "entryNames is empty");
1627         return false;
1628     }
1629 
1630     for (const auto &entryName : entryNames) {
1631         if (strcmp(entryName.c_str(), ".") == 0 ||
1632             strcmp(entryName.c_str(), "..") == 0) {
1633             continue;
1634         }
1635         if (entryName.back() == ServiceConstants::PATH_SEPARATOR[0]) {
1636             continue;
1637         }
1638         // save native so file entryName in the hap
1639         if (IsNativeSo(entryName, cpuAbi)) {
1640             soEntryFiles.emplace_back(entryName);
1641             continue;
1642         }
1643     }
1644 
1645     if (soEntryFiles.empty()) {
1646         LOG_D(BMS_TAG_INSTALLD, "no so file in installation file");
1647     }
1648     return true;
1649 }
1650 
MoveFiles(const std::string & srcDir,const std::string & desDir,bool isDesDirNeedCreated)1651 bool InstalldOperator::MoveFiles(const std::string &srcDir, const std::string &desDir, bool isDesDirNeedCreated)
1652 {
1653     LOG_D(BMS_TAG_INSTALLD, "srcDir is %{public}s, desDir is %{public}s", srcDir.c_str(), desDir.c_str());
1654     if (isDesDirNeedCreated && !MkRecursiveDir(desDir, true)) {
1655         LOG_E(BMS_TAG_INSTALLD, "create desDir failed");
1656         return false;
1657     }
1658 
1659     if (srcDir.empty() || desDir.empty()) {
1660         LOG_E(BMS_TAG_INSTALLD, "move file failed due to srcDir or desDir is empty");
1661         return false;
1662     }
1663 
1664     std::string realPath = "";
1665     if (!PathToRealPath(srcDir, realPath)) {
1666         LOG_E(BMS_TAG_INSTALLD, "srcDir(%{public}s) is not real path", srcDir.c_str());
1667         return false;
1668     }
1669 
1670     std::string realDesDir = "";
1671     if (!PathToRealPath(desDir, realDesDir)) {
1672         LOG_E(BMS_TAG_INSTALLD, "desDir(%{public}s) is not real path", desDir.c_str());
1673         return false;
1674     }
1675 
1676     DIR* directory = opendir(realPath.c_str());
1677     if (directory == nullptr) {
1678         LOG_E(BMS_TAG_INSTALLD, "MoveFiles open dir(%{public}s) fail, errno:%{public}d", realPath.c_str(), errno);
1679         return false;
1680     }
1681 
1682     struct dirent *ptr = nullptr;
1683     while ((ptr = readdir(directory)) != nullptr) {
1684         std::string currentName(ptr->d_name);
1685         if (currentName.compare(".") == 0 || currentName.compare("..") == 0) {
1686             continue;
1687         }
1688 
1689         std::string curPath = realPath + ServiceConstants::PATH_SEPARATOR + currentName;
1690         std::string innerDesStr = realDesDir + ServiceConstants::PATH_SEPARATOR + currentName;
1691         struct stat s;
1692         if (stat(curPath.c_str(), &s) != 0) {
1693             LOG_D(BMS_TAG_INSTALLD, "MoveFiles stat %{public}s failed, errno:%{public}d", curPath.c_str(), errno);
1694             continue;
1695         }
1696         if (!MoveFileOrDir(curPath, innerDesStr, s.st_mode)) {
1697             closedir(directory);
1698             return false;
1699         }
1700     }
1701     closedir(directory);
1702     return true;
1703 }
1704 
MoveFileOrDir(const std::string & srcPath,const std::string & destPath,mode_t mode)1705 bool InstalldOperator::MoveFileOrDir(const std::string &srcPath, const std::string &destPath, mode_t mode)
1706 {
1707     if (mode & S_IFREG) {
1708         LOG_D(BMS_TAG_INSTALLD, "srcPath(%{public}s) is a file", srcPath.c_str());
1709         return MoveFile(srcPath, destPath);
1710     } else if (mode & S_IFDIR) {
1711         LOG_D(BMS_TAG_INSTALLD, "srcPath(%{public}s) is a dir", srcPath.c_str());
1712         return MoveFiles(srcPath, destPath, true);
1713     }
1714     return true;
1715 }
1716 
MoveFile(const std::string & srcPath,const std::string & destPath)1717 bool InstalldOperator::MoveFile(const std::string &srcPath, const std::string &destPath)
1718 {
1719     LOG_D(BMS_TAG_INSTALLD, "srcPath is %{public}s, destPath is %{public}s", srcPath.c_str(), destPath.c_str());
1720     if (!RenameFile(srcPath, destPath)) {
1721         LOG_E(BMS_TAG_INSTALLD, "move file from srcPath(%{public}s) to destPath(%{public}s) failed", srcPath.c_str(),
1722             destPath.c_str());
1723         return false;
1724     }
1725     mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
1726     if (!OHOS::ChangeModeFile(destPath, mode)) {
1727         LOG_E(BMS_TAG_INSTALLD, "change mode failed");
1728         return false;
1729     }
1730     return true;
1731 }
1732 
ExtractResourceFiles(const ExtractParam & extractParam,const BundleExtractor & extractor)1733 bool InstalldOperator::ExtractResourceFiles(const ExtractParam &extractParam, const BundleExtractor &extractor)
1734 {
1735     LOG_D(BMS_TAG_INSTALLD, "ExtractResourceFiles begin");
1736     std::string targetDir = extractParam.targetPath;
1737     if (!MkRecursiveDir(targetDir, true)) {
1738         LOG_E(BMS_TAG_INSTALLD, "create targetDir failed");
1739         return false;
1740     }
1741     std::vector<std::string> entryNames;
1742     if (!extractor.GetZipFileNames(entryNames)) {
1743         LOG_E(BMS_TAG_INSTALLD, "GetZipFileNames failed");
1744         return false;
1745     }
1746     for (const auto &entryName : entryNames) {
1747         if (StartsWith(entryName, ServiceConstants::LIBS)
1748             || StartsWith(entryName, ServiceConstants::AN)
1749             || StartsWith(entryName, AP_PATH)) {
1750             continue;
1751         }
1752         const std::string relativeDir = GetPathDir(entryName);
1753         if (!relativeDir.empty()) {
1754             if (!MkRecursiveDir(targetDir + relativeDir, true)) {
1755                 LOG_E(BMS_TAG_INSTALLD, "MkRecursiveDir failed");
1756                 return false;
1757             }
1758         }
1759         std::string filePath = targetDir + entryName;
1760         if (!extractor.ExtractFile(entryName, filePath)) {
1761             LOG_E(BMS_TAG_INSTALLD, "ExtractFile failed");
1762             continue;
1763         }
1764         mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
1765         if (!OHOS::ChangeModeFile(filePath, mode)) {
1766             LOG_E(BMS_TAG_INSTALLD, "change mode failed");
1767             return false;
1768         }
1769     }
1770     LOG_D(BMS_TAG_INSTALLD, "ExtractResourceFiles success");
1771     return true;
1772 }
1773 
ExtractDriverSoFiles(const std::string & srcPath,const std::unordered_multimap<std::string,std::string> & dirMap)1774 bool InstalldOperator::ExtractDriverSoFiles(const std::string &srcPath,
1775     const std::unordered_multimap<std::string, std::string> &dirMap)
1776 {
1777     LOG_D(BMS_TAG_INSTALLD, "ExtractDriverSoFiles start with src(%{public}s)", srcPath.c_str());
1778     if (srcPath.empty() || dirMap.empty()) {
1779         LOG_E(BMS_TAG_INSTALLD, "ExtractDriverSoFiles parameters are invalid");
1780         return false;
1781     }
1782 
1783     for (auto &[originalDir, destinedDir] : dirMap) {
1784         if ((originalDir.compare(".") == 0) || (originalDir.compare("..") == 0)) {
1785             LOG_E(BMS_TAG_INSTALLD, "the originalDir %{public}s is not existed in the hap", originalDir.c_str());
1786             return false;
1787         }
1788         if ((!BundleUtil::StartWith(originalDir, PREFIX_RESOURCE_PATH) &&
1789             !BundleUtil::StartWith(originalDir, PREFIX_LIBS_PATH)) ||
1790             !BundleUtil::StartWith(destinedDir, PREFIX_TARGET_PATH)) {
1791             LOG_E(BMS_TAG_INSTALLD, "the originalDir %{public}s and destined dir %{public}s are invalid",
1792                 originalDir.c_str(), destinedDir.c_str());
1793             return false;
1794         }
1795         std::string fileName = originalDir;
1796         if (fileName.front() == ServiceConstants::PATH_SEPARATOR[0]) {
1797             fileName = fileName.substr(1);
1798         }
1799         int fileNamePos = 0;
1800         fileNamePos = fileName.find(ServiceConstants::PATH_SEPARATOR[0], STR_LIBS_LEN + 1);
1801         fileName.erase(0, fileNamePos);
1802         LOG_D(BMS_TAG_INSTALLD, "ExtractDriverSoFiles fileName is %{public}s", fileName.c_str());
1803         std::string systemServiceDir = ServiceConstants::SYSTEM_SERVICE_DIR;
1804         if (!CopyDriverSoFiles(srcPath + fileName, systemServiceDir + destinedDir)) {
1805             LOG_E(BMS_TAG_INSTALLD, "CopyDriverSoFiles failed");
1806             return false;
1807         }
1808     }
1809     LOG_D(BMS_TAG_INSTALLD, "ExtractDriverSoFiles end");
1810     return true;
1811 }
1812 
CopyDriverSoFiles(const std::string & originalDir,const std::string & destinedDir)1813 bool InstalldOperator::CopyDriverSoFiles(const std::string &originalDir, const std::string &destinedDir)
1814 {
1815     LOG_D(BMS_TAG_INSTALLD, "CopyDriverSoFiles beign");
1816     auto pos = destinedDir.rfind(ServiceConstants::PATH_SEPARATOR);
1817     if ((pos == std::string::npos) || (pos == destinedDir.length() -1)) {
1818         LOG_E(BMS_TAG_INSTALLD, "destinedDir(%{public}s) is invalid path", destinedDir.c_str());
1819         return false;
1820     }
1821     std::string desDir = destinedDir.substr(0, pos);
1822     std::string realDesDir;
1823     if (!PathToRealPath(desDir, realDesDir)) {
1824         LOG_E(BMS_TAG_INSTALLD, "desDir(%{public}s) is not real path", desDir.c_str());
1825         return false;
1826     }
1827     std::string realDestinedDir = realDesDir + destinedDir.substr(pos);
1828     LOG_D(BMS_TAG_INSTALLD, "realDestinedDir is %{public}s", realDestinedDir.c_str());
1829     MoveFile(originalDir, realDestinedDir);
1830 
1831     struct stat buf = {};
1832     if (stat(realDesDir.c_str(), &buf) != 0) {
1833         LOG_E(BMS_TAG_INSTALLD, "failed to obtain the stat status of realDesDir %{public}s, errno:%{public}d",
1834             realDesDir.c_str(), errno);
1835         return false;
1836     }
1837     ChangeFileAttr(realDestinedDir, buf.st_uid, buf.st_gid);
1838     mode_t mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IROTH;
1839     if (!OHOS::ChangeModeFile(realDestinedDir, mode)) {
1840         LOG_E(BMS_TAG_INSTALLD, "ChangeModeFile %{public}s failed, errno: %{public}d", realDestinedDir.c_str(),
1841             errno);
1842         return false;
1843     }
1844     LOG_D(BMS_TAG_INSTALLD, "CopyDriverSoFiles end");
1845     return true;
1846 }
1847 
1848 #if defined(CODE_ENCRYPTION_ENABLE)
ExtractSoFilesToTmpHapPath(const std::string & hapPath,const std::string & cpuAbi,const std::string & tmpSoPath,int32_t uid)1849 ErrCode InstalldOperator::ExtractSoFilesToTmpHapPath(const std::string &hapPath, const std::string &cpuAbi,
1850     const std::string &tmpSoPath, int32_t uid)
1851 {
1852     LOG_D(BMS_TAG_INSTALLD, "start to obtain decoded so files from hapPath %{public}s", hapPath.c_str());
1853     BundleExtractor extractor(hapPath);
1854     if (!extractor.Init()) {
1855         LOG_E(BMS_TAG_INSTALLD, "init bundle extractor failed");
1856         return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
1857     }
1858 
1859     /* obtain the so list in the hap */
1860     std::vector<std::string> soEntryFiles;
1861     if (!ObtainNativeSoFile(extractor, cpuAbi, soEntryFiles)) {
1862         LOG_E(BMS_TAG_INSTALLD, "ExtractFiles obtain native so file entryName failed");
1863         return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
1864     }
1865 
1866     std::string innerTmpSoPath = tmpSoPath;
1867     if (innerTmpSoPath.back() != ServiceConstants::PATH_SEPARATOR[0]) {
1868         innerTmpSoPath += ServiceConstants::PATH_SEPARATOR;
1869     }
1870 
1871     /* create innerTmpSoPath */
1872     if (!IsExistDir(innerTmpSoPath)) {
1873         if (!MkRecursiveDir(innerTmpSoPath, true)) {
1874             LOG_E(BMS_TAG_INSTALLD, "create innerTmpSoPath %{public}s failed", innerTmpSoPath.c_str());
1875             return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
1876         }
1877     }
1878 
1879     for (const auto &entry : soEntryFiles) {
1880         LOG_D(BMS_TAG_INSTALLD, "entryName is %{public}s", entry.c_str());
1881         auto pos = entry.rfind(ServiceConstants::PATH_SEPARATOR[0]);
1882         if (pos == std::string::npos) {
1883             LOG_W(BMS_TAG_INSTALLD, "invalid so entry %{public}s", entry.c_str());
1884             continue;
1885         }
1886         std::string soFileName = entry.substr(pos + 1);
1887         if (soFileName.empty()) {
1888             LOG_W(BMS_TAG_INSTALLD, "invalid so entry %{public}s", entry.c_str());
1889             continue;
1890         }
1891         LOG_D(BMS_TAG_INSTALLD, "so file is %{public}s", soFileName.c_str());
1892         uint32_t offset = 0;
1893         uint32_t length = 0;
1894         if (!extractor.GetFileInfo(entry, offset, length) || length == 0) {
1895             LOG_W(BMS_TAG_INSTALLD, "GetFileInfo failed or invalid so file");
1896             continue;
1897         }
1898         LOG_D(BMS_TAG_INSTALLD, "so file %{public}s has offset %{public}d and file size %{public}d",
1899             entry.c_str(), offset, length);
1900 
1901         /* mmap so to ram and write so file to temp path */
1902         ErrCode res = ERR_OK;
1903         if ((res = DecryptSoFile(hapPath, innerTmpSoPath + soFileName, uid, length, offset)) != ERR_OK) {
1904             LOG_E(BMS_TAG_INSTALLD, "decrypt file failed, srcPath is %{public}s and destPath is %{public}s",
1905                 hapPath.c_str(), (innerTmpSoPath + soFileName).c_str());
1906             return res;
1907         }
1908     }
1909 
1910     return ERR_OK;
1911 }
1912 
ExtractSoFilesToTmpSoPath(const std::string & hapPath,const std::string & realSoFilesPath,const std::string & cpuAbi,const std::string & tmpSoPath,int32_t uid)1913 ErrCode InstalldOperator::ExtractSoFilesToTmpSoPath(const std::string &hapPath, const std::string &realSoFilesPath,
1914     const std::string &cpuAbi, const std::string &tmpSoPath, int32_t uid)
1915 {
1916     LOG_D(BMS_TAG_INSTALLD, "start to obtain decoded so files from so path");
1917     if (realSoFilesPath.empty()) {
1918         LOG_E(BMS_TAG_INSTALLD, "real so file path is empty");
1919         return ERR_BUNDLEMANAGER_QUICK_FIX_INVALID_PATH;
1920     }
1921     BundleExtractor extractor(hapPath);
1922     if (!extractor.Init()) {
1923         LOG_E(BMS_TAG_INSTALLD, "init bundle extractor failed");
1924         return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
1925     }
1926     /* obtain the so list in the hap */
1927     std::vector<std::string> soEntryFiles;
1928     if (!ObtainNativeSoFile(extractor, cpuAbi, soEntryFiles)) {
1929         LOG_E(BMS_TAG_INSTALLD, "ExtractFiles obtain native so file entryName failed");
1930         return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
1931     }
1932 
1933     std::string innerTmpSoPath = tmpSoPath;
1934     if (innerTmpSoPath.back() != ServiceConstants::PATH_SEPARATOR[0]) {
1935         innerTmpSoPath += ServiceConstants::PATH_SEPARATOR;
1936     }
1937     // create innerTmpSoPath
1938     if (!IsExistDir(innerTmpSoPath)) {
1939         if (!MkRecursiveDir(innerTmpSoPath, true)) {
1940             LOG_E(BMS_TAG_INSTALLD, "create innerTmpSoPath %{public}s failed", innerTmpSoPath.c_str());
1941             return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
1942         }
1943     }
1944 
1945     for (const auto &entry : soEntryFiles) {
1946         auto pos = entry.rfind(ServiceConstants::PATH_SEPARATOR[0]);
1947         if (pos == std::string::npos) {
1948             LOG_W(BMS_TAG_INSTALLD, "invalid so entry %{public}s", entry.c_str());
1949             continue;
1950         }
1951         std::string soFileName = entry.substr(pos + 1);
1952         if (soFileName.empty()) {
1953             LOG_W(BMS_TAG_INSTALLD, "invalid so entry %{public}s", entry.c_str());
1954             continue;
1955         }
1956 
1957         std::string soPath = realSoFilesPath + soFileName;
1958         LOG_D(BMS_TAG_INSTALLD, "real path of the so file %{public}s is %{public}s",
1959             soFileName.c_str(), soPath.c_str());
1960 
1961         if (IsExistFile(soPath)) {
1962             /* mmap so file to ram and write to innerTmpSoPath */
1963             ErrCode res = ERR_OK;
1964             LOG_D(BMS_TAG_INSTALLD, "tmp so path is %{public}s", (innerTmpSoPath + soFileName).c_str());
1965             if ((res = DecryptSoFile(soPath, innerTmpSoPath + soFileName, uid, 0, 0)) != ERR_OK) {
1966                 LOG_E(BMS_TAG_INSTALLD, "decrypt file failed, srcPath is %{public}s and destPath is %{public}s",
1967                     soPath.c_str(), (innerTmpSoPath + soFileName).c_str());
1968                 return res;
1969             }
1970         } else {
1971             LOG_W(BMS_TAG_INSTALLD, "so file %{public}s is not existed", soPath.c_str());
1972         }
1973     }
1974     return ERR_OK;
1975 }
1976 
DecryptSoFile(const std::string & filePath,const std::string & tmpPath,int32_t uid,uint32_t fileSize,uint32_t offset)1977 ErrCode InstalldOperator::DecryptSoFile(const std::string &filePath, const std::string &tmpPath, int32_t uid,
1978     uint32_t fileSize, uint32_t offset)
1979 {
1980     LOG_D(BMS_TAG_INSTALLD, "src file is %{public}s, temp path is %{public}s, bundle uid is %{public}d",
1981         filePath.c_str(), tmpPath.c_str(), uid);
1982     ErrCode result = ERR_BUNDLEMANAGER_QUICK_FIX_DECRYPTO_SO_FAILED;
1983 
1984     /* call CallIoctl */
1985     int32_t dev_fd = INVALID_FILE_DESCRIPTOR;
1986     auto ret = CallIoctl(CODE_DECRYPT_CMD_SET_KEY, CODE_DECRYPT_CMD_SET_ASSOCIATE_KEY, uid, dev_fd);
1987     if (ret != 0) {
1988         LOG_E(BMS_TAG_INSTALLD, "CallIoctl failed");
1989         return result;
1990     }
1991 
1992     /* mmap hap or so file to ram */
1993     std::string newfilePath;
1994     if (!PathToRealPath(filePath, newfilePath)) {
1995         LOG_E(BMS_TAG_INSTALLD, "file is not real path, file path: %{public}s", filePath.c_str());
1996         return result;
1997     }
1998     auto fd = open(newfilePath.c_str(), O_RDONLY);
1999     if (fd < 0) {
2000         LOG_E(BMS_TAG_INSTALLD, "open hap failed errno:%{public}d", errno);
2001         close(dev_fd);
2002         return result;
2003     }
2004     struct stat st;
2005     if (fstat(fd, &st) == INVALID_RETURN_VALUE) {
2006         LOG_E(BMS_TAG_INSTALLD, "obtain hap file status faield errno:%{public}d", errno);
2007         close(dev_fd);
2008         close(fd);
2009         return result;
2010     }
2011     off_t innerFileSize = fileSize;
2012     if (fileSize == 0) {
2013         innerFileSize = st.st_size;
2014     }
2015     void *addr = mmap(NULL, innerFileSize, PROT_READ, MAP_PRIVATE, fd, offset);
2016     if (addr == MAP_FAILED) {
2017         LOG_E(BMS_TAG_INSTALLD, "mmap hap file status faield errno:%{public}d", errno);
2018         close(dev_fd);
2019         close(fd);
2020         return result;
2021     }
2022 
2023     /* write hap file to the temp path */
2024     auto outPutFd = BundleUtil::CreateFileDescriptor(tmpPath, 0);
2025     if (outPutFd < 0) {
2026         LOG_E(BMS_TAG_INSTALLD, "create fd for tmp hap file failed");
2027         close(dev_fd);
2028         close(fd);
2029         munmap(addr, innerFileSize);
2030         return result;
2031     }
2032     if (write(outPutFd, addr, innerFileSize) != INVALID_RETURN_VALUE) {
2033         result = ERR_OK;
2034         LOG_D(BMS_TAG_INSTALLD, "write hap to temp path successfully");
2035     }
2036     close(dev_fd);
2037     close(fd);
2038     close(outPutFd);
2039     munmap(addr, innerFileSize);
2040     return result;
2041 }
2042 
RemoveEncryptedKey(int32_t uid,const std::vector<std::string> & soList)2043 ErrCode InstalldOperator::RemoveEncryptedKey(int32_t uid, const std::vector<std::string> &soList)
2044 {
2045     if (uid == Constants::INVALID_UID) {
2046         LOG_D(BMS_TAG_INSTALLD, "invalid uid and no need to remove encrypted key");
2047         return ERR_OK;
2048     }
2049     if (soList.empty()) {
2050         LOG_D(BMS_TAG_INSTALLD, "no new so generated and no need to remove encrypted key");
2051         return ERR_OK;
2052     }
2053     ErrCode result = ERR_BUNDLEMANAGER_QUICK_FIX_DECRYPTO_SO_FAILED;
2054 
2055     /* call CallIoctl */
2056     int32_t dev_fd = INVALID_FILE_DESCRIPTOR;
2057     auto ret = CallIoctl(CODE_DECRYPT_CMD_REMOVE_KEY, CODE_DECRYPT_CMD_REMOVE_KEY, uid, dev_fd);
2058     if (ret == 0) {
2059         LOG_D(BMS_TAG_INSTALLD, "ioctl successfully");
2060         result = ERR_OK;
2061     }
2062     close(dev_fd);
2063     return result;
2064 }
2065 
CallIoctl(int32_t flag,int32_t associatedFlag,int32_t uid,int32_t & fd)2066 int32_t InstalldOperator::CallIoctl(int32_t flag, int32_t associatedFlag, int32_t uid, int32_t &fd)
2067 {
2068     int32_t installdUid = static_cast<int32_t>(getuid());
2069     int32_t bundleUid = uid;
2070     LOG_D(BMS_TAG_INSTALLD, "current process uid is %{public}d and bundle uid is %{public}d", installdUid, bundleUid);
2071 
2072     /* open CODE_DECRYPT */
2073     std::string newCodeDecrypt;
2074     if (!PathToRealPath(CODE_DECRYPT, newCodeDecrypt)) {
2075         LOG_E(BMS_TAG_INSTALLD, "file is not real path, file path: %{public}s", CODE_DECRYPT.c_str());
2076         return INVALID_RETURN_VALUE;
2077     }
2078     fd = open(newCodeDecrypt.c_str(), O_RDONLY);
2079     if (fd < 0) {
2080         LOG_E(BMS_TAG_INSTALLD, "call open failed errno:%{public}d", errno);
2081         return INVALID_RETURN_VALUE;
2082     }
2083 
2084     /* build ioctl args to set key or remove key*/
2085     struct code_decrypt_arg firstArg;
2086     firstArg.arg1_len = sizeof(bundleUid);
2087     firstArg.arg1 = reinterpret_cast<void *>(&bundleUid);
2088     auto ret = ioctl(fd, flag, &firstArg);
2089     if (ret != 0) {
2090         LOG_E(BMS_TAG_INSTALLD, "call ioctl failed errno:%{public}d", errno);
2091         close(fd);
2092     }
2093 
2094     struct code_decrypt_arg secondArg;
2095     secondArg.arg1_len = sizeof(installdUid);
2096     secondArg.arg1 = reinterpret_cast<void *>(&installdUid);
2097     if (associatedFlag == CODE_DECRYPT_CMD_SET_ASSOCIATE_KEY) {
2098         secondArg.arg2_len = sizeof(bundleUid);
2099         secondArg.arg2 = reinterpret_cast<void *>(&bundleUid);
2100     }
2101     ret = ioctl(fd, associatedFlag, &secondArg);
2102     if (ret != 0) {
2103         LOG_E(BMS_TAG_INSTALLD, "call ioctl failed errno:%{public}d", errno);
2104         close(fd);
2105     }
2106     return ret;
2107 }
2108 #endif
2109 
GenerateKeyIdAndSetPolicy(int32_t uid,const std::string & bundleName,const int32_t userId,std::string & keyId)2110 bool InstalldOperator::GenerateKeyIdAndSetPolicy(int32_t uid, const std::string &bundleName,
2111     const int32_t userId, std::string &keyId)
2112 {
2113     LOG_D(BMS_TAG_INSTALLD, "GenerateKeyId uid is %{public}d, bundleName is %{public}s, userId is %{public}d",
2114         uid, bundleName.c_str(), userId);
2115     auto ret = Security::AccessToken::El5FilekeyManagerKit::GenerateAppKey(
2116         static_cast<uint32_t>(uid), bundleName, keyId);
2117     if (ret == Security::AccessToken::EFM_ERR_KEYID_EXISTED) {
2118         LOG_I(BMS_TAG_INSTALLD, "key id is existed");
2119     } else if (ret != 0) {
2120         LOG_E(BMS_TAG_INSTALLD, "Call GenerateAppKey failed ret = %{public}d", ret);
2121         return false;
2122     }
2123     if (keyId.empty()) {
2124         LOG_E(BMS_TAG_INSTALLD, "keyId is empty");
2125         return false;
2126     }
2127     struct fscrypt_asdp_policy policy;
2128     policy.version = 0;
2129     policy.asdp_class = FORCE_PROTECT;
2130     // keyId length = KEY_ID_STEP * FSCRYPT_KEY_DESCRIPTOR_SIZE
2131     for (uint32_t i = 0; i < keyId.size(); i += KEY_ID_STEP) {
2132         if (i / KEY_ID_STEP >= FSCRYPT_KEY_DESCRIPTOR_SIZE) {
2133             break;
2134         }
2135         std::string byteString = keyId.substr(i, KEY_ID_STEP);
2136         char byte = (char)strtol(byteString.c_str(), NULL, 16);
2137         policy.app_key2_descriptor[i / KEY_ID_STEP] = byte;
2138     }
2139 
2140     std::vector<std::string> dirs;
2141     dirs.emplace_back(ServiceConstants::SCREEN_LOCK_FILE_DATA_PATH + ServiceConstants::PATH_SEPARATOR +
2142         std::to_string(userId) + ServiceConstants::BASE + bundleName);
2143     dirs.emplace_back(ServiceConstants::SCREEN_LOCK_FILE_DATA_PATH + ServiceConstants::PATH_SEPARATOR +
2144         std::to_string(userId) + ServiceConstants::DATABASE + bundleName);
2145     for (const auto &dir : dirs) {
2146         auto fd = open(dir.c_str(), O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
2147         if (fd < 0) {
2148             LOG_E(BMS_TAG_INSTALLD, "open filePath failed");
2149             return false;
2150         }
2151         // call ioctl to set e policy
2152         auto result = ioctl(fd, HMFS_IOC_SET_ASDP_ENCRYPTION_POLICY, &policy);
2153         if (result != 0) {
2154             LOG_E(BMS_TAG_INSTALLD, "ioctl failed result:%{public}d %{public}d", result, errno);
2155             close(fd);
2156             return false;
2157         }
2158         close(fd);
2159     }
2160     LOG_I(BMS_TAG_INSTALLD, "GenerateKeyIdAndSetPolicy success for %{public}s", bundleName.c_str());
2161     return true;
2162 }
2163 
DeleteKeyId(const std::string & bundleName,const int32_t userId)2164 bool InstalldOperator::DeleteKeyId(const std::string &bundleName, const int32_t userId)
2165 {
2166     LOG_D(BMS_TAG_INSTALLD, "DeleteKeyId bundleName is %{public}s", bundleName.c_str());
2167     auto ret = Security::AccessToken::El5FilekeyManagerKit::DeleteAppKey(bundleName, userId);
2168     if (ret != 0) {
2169         LOG_E(BMS_TAG_INSTALLD, "Call DeleteAppKey failed ret = %{public}d", ret);
2170         return false;
2171     }
2172     return true;
2173 }
2174 
GetAtomicServiceBundleDataDir(const std::string & bundleName,const int32_t userId,std::vector<std::string> & allPathNames)2175 bool InstalldOperator::GetAtomicServiceBundleDataDir(const std::string &bundleName,
2176     const int32_t userId, std::vector<std::string> &allPathNames)
2177 {
2178     std::string baseDir = ServiceConstants::BUNDLE_APP_DATA_BASE_DIR + ServiceConstants::BUNDLE_EL[0] +
2179         ServiceConstants::PATH_SEPARATOR + std::to_string(userId) + ServiceConstants::BASE;
2180     DIR *dir = opendir(baseDir.c_str());
2181     if (dir == nullptr) {
2182         LOG_E(BMS_TAG_INSTALLD, "fail to opendir:%{public}s, errno:%{public}d", baseDir.c_str(), errno);
2183         return false;
2184     }
2185     struct dirent *ptr = nullptr;
2186     while ((ptr = readdir(dir)) != nullptr) {
2187         if (ptr->d_type == DT_DIR) {
2188             std::string pathName(ptr->d_name);
2189             if (pathName.find(ATOMIC_SERVICE_PATH) != 0) {
2190                 continue;
2191             }
2192             auto pos = pathName.rfind(bundleName);
2193             if ((pos != std::string::npos) && (pos == (pathName.size() - bundleName.size()))) {
2194                 allPathNames.emplace_back(pathName);
2195             }
2196         }
2197     }
2198     closedir(dir);
2199     return !allPathNames.empty();
2200 }
2201 
2202 #if defined(CODE_ENCRYPTION_ENABLE)
2203 std::mutex InstalldOperator::encryptionMutex_;
2204 void *InstalldOperator::encryptionHandle_ = nullptr;
2205 EnforceMetadataProcessForApp InstalldOperator::enforceMetadataProcessForApp_ = nullptr;
2206 
OpenEncryptionHandle()2207 bool InstalldOperator::OpenEncryptionHandle()
2208 {
2209     std::lock_guard<std::mutex> lock(encryptionMutex_);
2210     if (encryptionHandle_ != nullptr && enforceMetadataProcessForApp_ != nullptr) {
2211         LOG_NOFUNC_I(BMS_TAG_INSTALLD, "encrypt handle opened");
2212         return true;
2213     }
2214     LOG_NOFUNC_I(BMS_TAG_INSTALLD, "OpenEncryption start");
2215     encryptionHandle_ = dlopen(LIB64_CODE_CRYPTO_SO_PATH, RTLD_NOW | RTLD_GLOBAL);
2216     if (encryptionHandle_ == nullptr) {
2217         LOG_W(BMS_TAG_INSTALLD, "open encrypt lib64 failed %{public}s", dlerror());
2218         encryptionHandle_ = dlopen(LIB_CODE_CRYPTO_SO_PATH, RTLD_NOW | RTLD_GLOBAL);
2219     }
2220     if (encryptionHandle_ == nullptr) {
2221         LOG_E(BMS_TAG_INSTALLD, "open encrypt lib failed %{public}s", dlerror());
2222         return false;
2223     }
2224     enforceMetadataProcessForApp_ =
2225         reinterpret_cast<EnforceMetadataProcessForApp>(dlsym(encryptionHandle_, CODE_CRYPTO_FUNCTION_NAME));
2226     if (enforceMetadataProcessForApp_ == nullptr) {
2227         LOG_E(BMS_TAG_INSTALLD, "dlsym encrypt err:%{public}s", dlerror());
2228         dlclose(encryptionHandle_);
2229         encryptionHandle_ = nullptr;
2230         return false;
2231     }
2232     return true;
2233 }
2234 
EnforceEncryption(std::unordered_map<std::string,std::string> & entryMap,int32_t bundleId,bool & isEncryption,InstallBundleType installBundleType,bool isCompressNativeLibrary)2235 bool InstalldOperator::EnforceEncryption(std::unordered_map<std::string, std::string> &entryMap, int32_t bundleId,
2236     bool &isEncryption, InstallBundleType installBundleType, bool isCompressNativeLibrary)
2237 {
2238     if (!OpenEncryptionHandle()) {
2239         return false;
2240     }
2241     ErrCode ret = enforceMetadataProcessForApp_(entryMap, bundleId,
2242         isEncryption, static_cast<int32_t>(installBundleType), isCompressNativeLibrary);
2243     if (ret != ERR_OK) {
2244         LOG_E(BMS_TAG_INSTALLD, "CheckEncryption failed due to %{public}d", ret);
2245         return false;
2246     }
2247     return true;
2248 }
2249 #endif
2250 }  // namespace AppExecFwk
2251 }  // namespace OHOS
2252