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