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