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