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