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