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