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