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